jb flags2.TCP_SOCK, :lastackTcp2 ; checkk which tcp conn ; is current mov tcp1State, w call @DeleteSocket1 ; delete the tcp conn. socket jmp :dumpy :lastackTcp2 mov tcp2State, w call @DeleteSocket2 ; delete the tcp conn. socket :dumpy _bank NIC_BANK ; needed for NICDumpRxFrame, we came from ; an upper bank jmp @NICDumpRxFrame :CLOSED call @NICDumpRxFrame jmp @TCPSendReset ; we shouldn't receive packets ; while closed :LISTEN call @NICDumpRxFrame ; discard received packet jb flags2.TCP_SOCK, :listen2Check bank TCB1_BANK snb tcb1Flags.TCP_FLAG_RST ; check for an RST retp ; ignore a packet with RST snb tcb1Flags.TCP_FLAG_ACK ; check for an ACK jmp @TCPSendReset ; bad ACK, send a RST jmp :contListen :listen2Check bank TCB2_BANK snb tcb2Flags.TCP_FLAG_RST ; check for an RST retp ; ignore a packet with RST snb tcb2Flags.TCP_FLAG_ACK ; check for an ACK jmp @TCPSendReset ; bad ACK, send a RST :contListen call @TCPCopySeqToNxt call @TCPSendSynAck bank TCP_BANK mov w, #TCP_ST_SYNRCVED ; change state sb flags2.TCP_SOCK mov tcp1State, w snb flags2.TCP_SOCK mov tcp2State, w retp :SYNSENT call @NICDumpRxFrame jb flags2.TCP_SOCK, :synsentCheck2 bank TCB1_BANK jnb tcb1Flags.TCP_FLAG_ACK, :noAck ; is the ACK bit set? jb tcb1Flags.TCP_FLAG_RST, :rst ; is the reset bit set? jnb tcb1Flags.TCP_FLAG_SYN, :noAck ; if SYN bit not set, ; ignore packet jmp :contSynsent :synsentCheck2 bank TCB2_BANK jnb tcb2Flags.TCP_FLAG_ACK, :noAck ; is the ACK bit set? jb tcb2Flags.TCP_FLAG_RST, :rst ; is the reset bit set? jnb tcb2Flags.TCP_FLAG_SYN, :noAck ; if SYN bit not set, ; ignore packet :contSynsent bank TCP_BANK mov w, #TCP_ST_ESTABED ; the connection is now estabished sb flags2.TCP_SOCK mov tcp1State, w snb flags2.TCP_SOCK mov tcp2State, w bank IP_BANK clr ipLengthMSB ; set the received data length to 1 mov ipLengthLSB, #1 ; " call @TCPAckUpdate jmp @TCPSendAck :rst bank TCP_BANK mov w, #TCP_ST_CLOSED ; close the TCP sb flags2.TCP_SOCK mov tcp1State, w snb flags2.TCP_SOCK mov tcp2State, w retp ; the peer wants us to raise the precedence. We can't. ; We are not happy about not being Acked. Send a Reset. :noAck jmp @TCPSendReset ORG $800 ; Page4 TCPRxHeader jmp _TCPRxHeader TCPStartPktOut jmp _TCPStartPktOut TCPTxByte jmp _TCPTxByte TCPReTransmit jmp _TCPReTransmit Compare4Inc jmp _Compare4Inc TCPAppTxDone jmp _TCPAppTxDone ; ****************************************************************************** NICReadAgain_4 ; Shortform for calling NICReadAgain(), which is in Page1 (This is in Page4) ; ****************************************************************************** jmp @NICReadAgain ; ****************************************************************************** NICWriteAgain_4 ; Shortform for calling NICWriteAgain(), which is in Page1 (This is in Page4) ; ****************************************************************************** jmp @NICWriteAgain ; ****************************************************************************** NICDumpRxFrame_4 ; Shortform for calling NICDumpRxFrame(), which is in Page1 (This is in Page4) ; ****************************************************************************** jmp @NICDumpRxFrame ; ****************************************************************************** TCPAddRcvNxt ; Add an 16-bit number to RCV.NXT ; INPUT: {ipLengthMSB,ipLengthLSB} = number to add ; OUTPUT: {tcb1RcvNxt1-4,tcb2RcvNxt1-4} ; ****************************************************************************** ; check for which tcp connection to add sb flags2.TCP_SOCK mov globTemp1, #tcb1RcvNxt1 ; make pointer to TCB1_BANK snb flags2.TCP_SOCK mov globTemp1, #tcb2RcvNxt1 ; make pointer to TCB2_BANK bank IP_BANK mov w, ipLengthLSB mov globTemp2, w ; store ipLengthLSB in globTemp2 mov fsr, globTemp1 ; point to TCB variable add indf, globTemp2 ; add ipLengthLSB to tcbRcvNxt1 bank IP_BANK mov w, ipLengthMSB snc mov w, ++ipLengthMSB mov globTemp2, w ; store in globTemp2 dec globTemp1 mov fsr, globTemp1 ; point to TCB variable add indf, globTemp2 ; add to tcb1(2)RcvNxt2 sc retp dec fsr incsz indf ; tcb1(2)RcvNxt3 retp dec fsr inc indf ; tcb1(2)RcvNxt4 retp ; ****************************************************************************** TCPIncRcvNxt ; Increment RCV.NXT by one ; INPUT: none ; OUTPUT: {tcb1RcvNxt1-4,tcb2RcvNxt1-4} ; ****************************************************************************** ; set pointer to correct TCB (TCB1_BANK for tcp1, ; TCB2_BANK for tcp2) mov globTemp1, #(tcb1RcvNxt1-TCB1_BANK) call @SetTCBPointer incsz indf ; 1 retp dec fsr ; 2 incsz indf retp dec fsr ; 3 incsz indf retp dec fsr ; 4 inc indf retp ; ****************************************************************************** TCPIncSndUna ; Increment SND.UNA by one ; INPUT: none ; OUTPUT: {tcb1SndUna1-4,tcb2SndUna1-4} ; ****************************************************************************** ; set pointer to correct TCB (TCB1_BANK for tcp1, ; TCB2_BANK for tcp2) mov globTemp1, #(tcb1SndUna1-TCB1_BANK) call @SetTCBPointer incsz indf ; 1 retp dec fsr ; 2 incsz indf retp dec fsr ; 3 incsz indf retp dec fsr ; 4 inc indf retp ; ****************************************************************************** TCPCopySeqToNxt ; Copy {tcpTmpSeq4-1} -> {tcb1RcvNxt4-1} or {tcb2RcvNxt4-1} ; INPUT: {tcpTmpSeq4-1} ; OUTPUT: {tcb1RcvNxt4-1,tcb2RcvNxt4-1} ; ****************************************************************************** sb flags2.TCP_SOCK mov globTemp1, #tcb1RcvNxt4 ; make pointer to TCB1_BANK snb flags2.TCP_SOCK mov globTemp1, #tcb2RcvNxt4 ; make pointer to TCB2_BANK mov globTemp3, #tcpTmpSeq4 ; make pointer to TCP BANK call @Copy4Inc ; copy 4 TCP variables to TCB retp ; by incrementing the pointers ; ****************************************************************************** TCPCopyAckToUna ; Copy {tcpTmpAck4-1} -> {tcb1SndUna4-1} or {tcb2SndUna4-1} ; INPUT: {tcpTmpAck4-1} ; OUTPUT: {tcb1SndUna4-1,{tcb2SndUna4-1}} ; ****************************************************************************** sb flags2.TCP_SOCK mov globTemp1, #tcb1SndUna4 ; make pointer to TCB1_BANK snb flags2.TCP_SOCK mov globTemp1, #tcb2SndUna4 ; make pointer to TCB2_BANK mov globTemp3, #tcpTmpAck4 ; make pointer to TCP BANK call @Copy4Inc ; copy 4 TCP variables to TCB retp ; ****************************************************************************** TCPAckUpdate ; Update SND.UNA and RCV.NXT ; INPUT: {tcpTmpAck4-1} ; {tcpTmpSeq4-1} ; {ipLengthMSB,ipLengthLSB} = length of received TCP Data ; OUTPUT: {tcpSndUna4-1} ; {tcpRcvNxt4-1} ; ****************************************************************************** call @TCPCopyAckToUna ; set SND.UNA = SEG.ACK call @TCPCopySeqToNxt ; set RCV.NXT = SEG.SEQ jmp @TCPAddRcvNxt ; add the length of the received ; packet to the ACK ; ****************************************************************************** TCPCmpNxtSeq ; Check if RCV.NXT == SEG.SEQ ; INPUT: {tcpTmpSeq4-1} = SEG.SEQ ; {tcb1RcvNxt4-1} = RCV.NXT or {tcb2RcvNxt4-1} = RCV.NXT ; OUTPUT: z is set if RCV.NXT == SEG.SEQ ; ****************************************************************************** sb flags2.TCP_SOCK mov globTemp1, #tcb1RcvNxt1 ; make pointer to TCB1_BANK snb flags2.TCP_SOCK mov globTemp1, #tcb2RcvNxt1 ; make pointer to TCB2_BANK mov globTemp3, #tcpTmpSeq1 ; make pointer to TCP BANK bank IP_BANK mov counter1, #4 ; load the counter :loop mov fsr, globTemp3 ; move tcp pointer to fsr mov w, indf ; move tcp var in w mov globTemp2, w ; store tcp var in global2 mov fsr, globTemp1 ; move tcb pointer to fsr mov w, indf ; move tcb var into w xor w, globTemp2 ; xor tcp var with tcb var jnz :CmpEnd ; test if equal dec globTemp1 ; dec pointer to tcb dec globTemp3 ; dec pointer to tcp _bank IP_BANK ; check loop counter until ; finished dec counter1 sz jmp :loop :CmpEnd retp ; ****************************************************************************** TCPSendEmptyPkt ; Constructs and sends a TCP packet containing no Data ; INPUT: {remoteIP0-3} = Destination IP addr for TCP pkt ; {tcb1SndUna4-1} or {tcb2SndUna4-1} = sequence number ; {tcb1RcvNxt4-1} or {tcb2RcvNxt4-1} = acknowledgement number ; tcb1Flags or tcb2Flags = code flags ; {tcb1LocalPortMSB,tcb1LocalPortLSB} = TCP Source Port ; or {tcb2LocalPortMSB,tcb2LocalPortLSB} = TCP Source Port ; {tcb1RemotePortMSB,tcb1RemotePortLSB} = TCP Destination Port ; or {tcb2RemotePortMSB,tcb2RemotePortLSB} = TCP Destination Port ; OUTPUT: ; ****************************************************************************** call @TCPCheckSumInit bank TCP_BANK clr tcpLengthMSB clr tcpLengthLSB call TCPStartPktOut call @NICSendTxFrame bank TIMER_BANK ; clear correct tcp connection's re-tx counters jb flags2.TCP_SOCK, :clrTcp2timer ; tcp conn1 clr tcp1TimerMSB clr tcp1TimerLSB retp ; tcp conn2 :clrTcp2timer clr tcp2TimerMSB clr tcp2TimerLSB retp ; ****************************************************************************** TCPSendReset ; Send a reset packet with <SEQ=SEG.ACK><CTL=RST> and Discard the received ; packet ; INPUT: {remoteIP0-3} = Destination IP addr for TCP pkt ; {tcb1RcvNxt4-1} or {tcb2RcvNxt4-1} = acknowledgement number ; {tcb1LocalPortMSB,tcb1LocalPortLSB} = TCP Source Port ; or {tcb2LocalPortMSB,tcb2LocalPortLSB} = TCP Source Port ; {tcb1RemotePortMSB,tcb1RemotePortLSB} = TCP Destination Port ; or {tcb2RemotePortMSB,tcb2RemotePortLSB} = TCP Destination Port ; OUTPUT: ; ****************************************************************************** ; point to correct tcb for current tcp connection mov globTemp1, #(tcb1Flags-TCB1_BANK) call @SetTCBPointer mov indf, #(1<<TCP_FLAG_RST) call @TCPCopyAckToUna ; copy the acknowledgement number. call @TCPSendEmptyPkt jmp NICDumpRxFrame_4 ; discard the received pkt ; ****************************************************************************** TCPSendSyn ; Send a SYN packet ; INPUT: {remoteIP0-3} = Destination IP addr for TCP pkt ; {tcb1RcvNxt4-1} or {tcb2RcvNxt4-1} = acknowledgement number ; {tcb1LocalPortMSB,tcb1LocalPortLSB} = TCP Source Port ; or {tcb2LocalPortMSB,tcb2LocalPortLSB} = TCP Source Port ; {tcb1RemotePortMSB,tcb1RemotePortLSB} = TCP Destination Port ; or {tcb2RemotePortMSB,tcb2RemotePortLSB} = TCP Destination Port ; OUTPUT: {tcpSndUna4-1} = new sequence number ; ****************************************************************************** ; point to correct tcb for current tcp connection mov globTemp1, #(tcb1Flags-TCB1_BANK) call @SetTCBPointer mov indf, #(1<<TCP_FLAG_SYN) jmp TCPSendISN ; ****************************************************************************** TCPSendISN ; Send the TCP initial sequence number ; INPUT: {remoteIP0-3} = Destination IP addr for TCP pkt ; {tcb1RcvNxt4-1} or {tcb2RcvNxt4-1} = acknowledgement number ; {tcb1LocalPortMSB,tcb1LocalPortLSB} = TCP Source Port ; or {tcb2LocalPortMSB,tcb2LocalPortLSB} = TCP Source Port ; {tcb1RemotePortMSB,tcb1RemotePortLSB} = TCP Destination Port ; or {tcb2RemotePortMSB,tcb2RemotePortLSB} = TCP Destination Port ; OUTPUT: {tcpSndUna4-1} = new sequence number ; ****************************************************************************** ; obtain a random number for starting sequence number bank NIC_BANK mov w, nicCurrPktPtr xor w, nicRemoteEth0 bank IP_BANK xor w, ipIdentLSB mov globTemp2, w ; store ; point to the correct tcb for current tcp connection mov globTemp1, #(tcb1SndUna4-TCB1_BANK) call @SetTCBPointer mov w, globTemp2 ; restore mov indf, w ; 1 inc fsr mov indf, w ; 2 inc fsr mov indf, w ; 3 inc fsr mov indf, w ; 4 call @TCPIncRcvNxt call @TCPSendEmptyPkt jmp @TCPIncSndUna ; ****************************************************************************** TCPSendSynAck ; Send an SYN-ACK packet with <SEQ=SND.NXT><ACK=RCV.NXT><CTL=SYN> ; INPUT: {remoteIP0-3} = Destination IP addr for TCP pkt ; {tcb1RcvNxt4-1} or {tcb2RcvNxt4-1} = acknowledgement number ; {tcb1LocalPortMSB,tcb1LocalPortLSB} = TCP Source Port ; or {tcb2LocalPortMSB,tcb2LocalPortLSB} = TCP Source Port ; {tcb1RemotePortMSB,tcb1RemotePortLSB} = TCP Destination Port ; or {tcb2RemotePortMSB,tcb2RemotePortLSB} = TCP Destination Port ; OUTPUT: {tcpSndUna4-1} = new sequence number ; ****************************************************************************** ; point to correct tcb for current tcp connection mov globTemp1, #(tcb1Flags-TCB1_BANK) call @SetTCBPointer mov indf, #((1<<TCP_FLAG_SYN)|(1<<TCP_FLAG_ACK)) jmp @TCPSendISN ; ****************************************************************************** TCPSendAck ; Send an ACK packet with <SEQ=SND.NXT><ACK=RCV.NXT><CTL=ACK> and Discard the ; received packet ; INPUT: {remoteIP0-3} = Destination IP addr for TCP pkt ; {tcb1SndUna4-1} or {tcb2SndUna4-1} = sequence number ; {tcb1RcvNxt4-1} or {tcb2RcvNxt4-1} = acknowledgement number ; {tcb1LocalPortMSB,tcb1LocalPortLSB} = TCP Source Port ; or {tcb2LocalPortMSB,tcb2LocalPortLSB} = TCP Source Port ; {tcb1RemotePortMSB,tcb1RemotePortLSB} = TCP Destination Port ; or {tcb2RemotePortMSB,tcb2RemotePortLSB} = TCP Destination Port ; OUTPUT: ; ****************************************************************************** ; point to correct tcb for current tcp connection mov globTemp1, #(tcb1Flags-TCB1_BANK) call @SetTCBPointer mov indf, #(1<<TCP_FLAG_ACK) call @TCPSendEmptyPkt jmp NICDumpRxFrame_4 ; discard the received pkt ; ****************************************************************************** TCPSendFin ; Send a FIN packet and discard the received packet ; INPUT: {remoteIP0-3} = Destination IP addr for TCP pkt ; {tcb1SndUna4-1} or {tcb2SndUna4-1} = sequence number ; {tcb1RcvNxt4-1} or {tcb2RcvNxt4-1} = acknowledgement number ; tcb1Flags or tcb2Flags = code flags ; {tcb1LocalPortMSB,tcb1LocalPortLSB} = TCP Source Port ; or {tcb2LocalPortMSB,tcb2LocalPortLSB} = TCP Source Port ; {tcb1RemotePortMSB,tcb1RemotePortLSB} = TCP Destination Port ; or {tcb2RemotePortMSB,tcb2RemotePortLSB} = TCP Destination Port ; OUTPUT: ; ****************************************************************************** ; point to correct tcb for current tcp connection mov globTemp1, #(tcb1Flags-TCB1_BANK) call @SetTCBPointer mov indf, #(1<<TCP_FLAG_FIN)|(1<<TCP_FLAG_ACK) call @TCPSendEmptyPkt jmp NICDumpRxFrame_4 ; discard the received pkt ; ****************************************************************************** TCPCheckSumInit ; Clear TCP checksum value to prepare for new checksum calculation ; INPUT: none ; OUTPUT: {tcpCheckSumMSB,tcpCheckSumLSB} ; ****************************************************************************** bank TCP_BANK clr tcpCheckSumMSB clr tcpCheckSumLSB clrb flags.TCP_CHKSUM_LSB ; next byte is MSB retp ; ****************************************************************************** TCPCheckSumAcc ; Accumulate the TCP checksum. Checksum is computed by Doing the one's ; complement of the one's complement sum of 16-bit numbers ; INPUT: w = byte to accumulate ; flags.TCP_CHKSUM_LSB = set if processing LSB, clear if processing MSB ; OUTPUT: {tcpCheckSumMSB,tcpCheckSumLSB} ; ****************************************************************************** bank TCP_BANK jnb flags.TCP_CHKSUM_LSB, :msb ; are we processing an MSB? :lsb add tcpCheckSumLSB, w ; add it to the checksum sc ; was there a carry? jmp :done inc tcpCheckSumMSB ; yes snz inc tcpCheckSumLSB jmp :done :msb add tcpCheckSumMSB, w ; add it to the checksum sc ; was there a carry? jmp :done inc tcpCheckSumLSB ; yes, this time it is ; added to the LSB snz inc tcpCheckSumMSB :done xor flags, #(1<<TCP_CHKSUM_LSB) retp ; ****************************************************************************** TCPCheckSumAddHdr ; Add to the TCP checksum, the pseudo-header fields ; INPUT: {myIP0-3} = source IP addr ; {remoteIP0-3} = Destination IP addr ; {tcpLengthMSB,tcpLengthLSB} = length of TCP header and Data ; OUTPUT: {tcpCheckSumMSB,tcpCheckSumLSB} ; ****************************************************************************** bank TCP_BANK ; <TCP_length> mov w, tcpLengthMSB call TCPCheckSumAcc mov w, tcpLengthLSB call TCPCheckSumAcc ; <zero>,<protocol> mov w, #0 call TCPCheckSumAcc mov w, #6 call TCPCheckSumAcc ; <source_IP> bank IP_BANK mov w, myIP3 call TCPCheckSumAcc bank IP_BANK mov w, myIP2 call TCPCheckSumAcc bank IP_BANK mov w, myIP1 call TCPCheckSumAcc bank IP_BANK mov w, myIP0 call TCPCheckSumAcc ; <destination_IP> bank IP_BANK mov w, remoteIP3 call TCPCheckSumAcc bank IP_BANK mov w, remoteIP2 call TCPCheckSumAcc bank IP_BANK mov w, remoteIP1 call TCPCheckSumAcc bank IP_BANK mov w, remoteIP0 call TCPCheckSumAcc retp ; ****************************************************************************** _TCPTxByte ; Transmit a TCP byte accumulating the checksum each time ; INPUT: w = byte to send ; OUTPUT: none ; ****************************************************************************** mov globTemp1, w call @TCPCheckSumAcc mov w, globTemp1 call NICWriteAgain_4 retp ; ****************************************************************************** _TCPStartPktOut ; Constructs the TCP and IP headers ; INPUT: {remoteIP0-3} = Destination IP addr for TCP pkt ; {tcpLengthMSB,tcpLengthLSB} = length of TCP Data (just Data) ; {tcpCheckSumMSB,tcpCheckSumLSB} = TCP checksum computed over just Data ; {tcb1SndUna4-1} or {tcb2SndUna4-1} = sequence number ; {tcb1RcvNxt4-1} or {tcb2RcvNxt4-1} = acknowledgement number ; tcb1Flags or tcb2Flags = code flags ; {tcb1LocalPortMSB,tcb1LocalPortLSB} = TCP Source Port ; or {tcb2LocalPortMSB,tcb2LocalPortLSB} = TCP Source Port ; {tcb1RemotePortMSB,tcb1RemotePortLSB} = TCP Destination Port ; or {tcb2RemotePortMSB,tcb2RemotePortLSB} = TCP Destination Port ; OUTPUT: ; ****************************************************************************** ; tcpLength += <TCP header length> _bank TCP_BANK mov w, #(TCP_HDR_LENGTH<<2) ; add in size of TCP hdr (20) add tcpLengthLSB, w snc inc tcpLengthMSB ; tcpLength now is the length of ; TCP hdr and Data ; IP <total_length> = tcpLength + <IP header length> mov w, #20 ; add in size of IP hdr (20) add w, tcpLengthLSB bank IP_BANK mov ipLengthLSB, w bank TCP_BANK mov w, tcpLengthMSB bank IP_BANK mov ipLengthMSB, w snc inc ipLengthMSB ; update IP <identifier> inc ipIdentLSB snz inc ipIdentMSB ; set IP <protocol> for TCP mov ipProtocol, #6 ; We should rather load remoteIP with tcp socketIP here, but Due ; to limited code space it is Done in IPGenCheckSum. ; compute IP <header_checksum> call @IPGenCheckSum ; now we're ready to construct the IP header call @IPStartPktOut ; then construct the TCP header ; point to correct tcb for current tcp connection mov globTemp1, #(tcb1Offset-TCB1_BANK) call @SetTCBPointer ; TCP <source_port>,<destination_port>,<sequence_number>, ; <acknowledgement_number>,<hlen>,<code>,<window> mov indf, #(TCP_HDR_LENGTH<<4) inc fsr inc fsr mov indf, #((TCP_WINDOW_SIZE&$FF00)>>8) inc fsr mov indf, #(TCP_WINDOW_SIZE&$00FF) ; make a pointer to the tcb for the current tcp connection sb flags2.TCP_SOCK mov globTemp3, #TCB1_BANK snb flags2.TCP_SOCK mov globTemp3, #TCB2_BANK :loop mov fsr, globTemp3 mov w, indf ; load the value call @TCPTxByte ; transmit and accumulate header ; checksum inc globTemp3 jb flags2.TCP_SOCK, :check2 cse globTemp3, #TCB1_END ; is the loop finished? jmp :loop jmp :outloop :check2 cse globTemp3, #TCB2_END ; is the loop finished? jmp :loop :outloop ; TCP <checksum> call @TCPCheckSumAddHdr bank TCP_BANK mov w, /tcpCheckSumMSB call NICWriteAgain_4 mov w, /tcpCheckSumLSB call NICWriteAgain_4 ; TCP <urgent_ptr> mov w, #0 call NICWriteAgain_4 call NICWriteAgain_4 retp ; ****************************************************************************** _TCPRxHeader ; Process the TCP header of a received TCP packet ; INPUT: none ; OUTPUT: Z is set to 1 if the packet is invalid, 0 otherwise ; {tcb1RemotePortMSB,tcb1RemotePortLSB} ; or {tcb2RemotePortMSB,tcb2RemotePortLSB} ; {tcb1SendWinMSB,tcb1SendWinLSB} or {tcb2SendWinMSB,tcb2SendWinLSB} ; tcb1Offset or tcb2Offset ; tcb1Flags or tcb2Flags ; tcpRxFlags ; {tcpTmpSeq4-1} = <sequence_number> ; {tcpTmpAck4-1} = <acknowledgement_number> ; {tcpLengthMSB,tcpLengthLSB} = length of TCP Data ; {ipLengthMSB,ipLengthLSB} = length of TCP Data ; ****************************************************************************** bank TCPPORT_BANK ; <remote_port> call NICReadAgain_4 mov tcpRemotePortMSB, w ; store remote port MSB call NICReadAgain_4 mov tcpRemotePortLSB, w ; store remote port LSB ; <destination_port> call NICReadAgain_4 mov tcpLocalPortMSB, w ; store dest port MSB call NICReadAgain_4 ; mov tcpLocalPortLSB, w ; store dest port LSB call @TCPConnectionManager ; start the tcp conn/socket ; manager snz ; is the packet OK? retp ; no, return ; <sequence_number> bank TCP_BANK call NICReadAgain_4 mov tcpTmpSeq4, w call NICReadAgain_4 mov tcpTmpSeq3, w call NICReadAgain_4 mov tcpTmpSeq2, w call NICReadAgain_4 mov tcpTmpSeq1, w _bank TCPTMP_BANK ; <acknowledgement_number> call NICReadAgain_4 mov tcpTmpAck4, w call NICReadAgain_4 mov tcpTmpAck3, w call NICReadAgain_4 mov tcpTmpAck2,w call NICReadAgain_4 mov tcpTmpAck1, w call NICReadAgain_4 ; receive the Data offset. ; Used to skip the options and w, #TCP_OFFSET_MASK ; mask out the offset mov globTemp2, w ; store w ; point to the correct tcb for the current tcp connection mov globTemp1, #(tcb1Offset-TCB1_BANK) call @SetTCBPointer mov indf, globTemp2 clc rr indf rr indf ; ipLength = tcpLength = length of TCP Data mov w, indf _bank IP_BANK sub ipLengthLSB, w ; subtract out size of TCP header mov w, ipLengthLSB bank TCP_BANK mov tcpLengthLSB, w bank IP_BANK sc dec ipLengthMSB mov w, ipLengthMSB bank TCP_BANK mov tcpLengthMSB, w ; <code> call NICReadAgain_4 ; receive the flags mov tcpRxFlags, w mov globTemp2, w ; point to the correct tcb for the current tcp connection mov globTemp1, #(tcb1Flags-TCB1_BANK) call @SetTCBPointer mov indf, globTemp2 ; <window> call NICReadAgain_4 mov globTemp2, w ; point to the correct tcb for the current tcp connection mov globTemp1, #(tcb1SendWinMSB-TCB1_BANK) call @SetTCBPointer mov indf, globTemp2 ; receive the window call NICReadAgain_4 mov globTemp2, w ; point to the correct tcb for the current tcp connection mov globTemp1, #(tcb1SendWinLSB-TCB1_BANK) call @SetTCBPointer mov indf, globTemp2 ; point to the correct tcb for the current tcp connection mov globTemp1, #(tcb1Offset-TCB1_BANK) call @SetTCBPointer sub indf, #((TCP_HDR_LENGTH<<2)-4) mov w, indf mov globTemp3, w clr indf :loop call NICReadAgain_4 decsz globTemp3 jmp :loop clz retp ; ****************************************************************************** _TCPReTransmit ; This is called to retransmit the TCP packet that's already setup in the NIC's ; TCP transmit buffer. Remember that a UDP/ICMP/ARP packet may have been sent ; after the TCP packet was initially sent, so we have to re-setup the NIC ; carefully. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; re-initialize the NIC's TPSR bank NIC_BANK clr nicIOAddr ; CR :wait call @NICRead jb wreg.2, :wait ; wait for prior transmission to ; complete mov w, #%00100010 ; Page0, abort DMA call @NICWrite mov nicIOAddr, #$04 ; TPSR ; point to correct tcp tx buffer for current tcp connection sb flags2.TCP_SOCK mov w, #TXBUF2_START snb flags2.TCP_SOCK mov w, #TXBUF3_START call @NICWrite ; read the NIC's TCP transmit buffer to find out the IP <length> ; so that we can re-initialize the NIC's TBCR sb flags2.TCP_SOCK mov w, #TXBUF2_START snb flags2.TCP_SOCK mov w, #TXBUF3_START mov nicCopySrcMSB, w mov nicCopySrcLSB, #(6+6+2+2) ; IP <length> (MSB) call @NICBufRead bank IP_BANK mov ipLengthMSB, w bank NIC_BANK inc nicCopySrcLSB ; IP <length> (LSB) call @NICBufRead bank IP_BANK mov ipLengthLSB, w jmp @NICSendTxFrame ; re-transmit the ethernet frame ; ****************************************************************************** _Compare4Inc ; Compares 4 variables in Databanks ; INPUT: globTemp1 = pointer1, globTemp3 = pointer2 ; OUTPUT: Z is set on a full match ; ****************************************************************************** bank IP_BANK mov counter1, #4 ; load the counter :loop mov fsr, globTemp3 ; move pointer to fsr mov w, indf ; move var in w mov globTemp2, w ; store var in global2 mov fsr, globTemp1 ; move pointer to fsr mov w, indf ; move var into w xor w, globTemp2 ; xor tcp var with tcb var jnz :CmpEnd ; test if equal inc globTemp1 ; increment pointer inc globTemp3 ; increment pointer _bank IP_BANK ; check loop counter until finished dec counter1 sz jmp :loop :CmpEnd retp ; ****************************************************************************** _TCPAppTxDone ; This is called following the last call to TCPAppTxData(). It signifies the ; transmitted Data has successfully reached the remote host ; [TCP API Function] ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; jump to current tcp connection code jb flags2.TCP_SOCK, :TCPAppTxDone2 ; tcp1 retp ; tcp2 :TCPAppTxDone2 retp ORG $A00 ; Page5 TCPAppRxData jmp _TCPAppRxData ; ****************************************************************************** TCPAppRxBytes ; Indicator to the application that a packet has been received and that ; TCPAppRxByte is about to be called as many times as they are bytes of data ; [TCP API Function] ; INPUT: {tcpAppRxBytesMSB,tcpAppRxBytesLSB} = number of received Data bytes ; OUTPUT: none ; ****************************************************************************** ; jump to current tcp connection code jb flags2.TCP_SOCK, :TCPAppRxBytes2 ; tcp1 IF DYNDNS mov globTemp2, #15 ; set rcv byte counter mov globTemp3, #DYNDNSReply ; set pointer to rcv buffer ENDIF retp ; tcp2 :TCPAppRxBytes2 retp ; ****************************************************************************** TCPAppTxBytes ; Called before transmitting a TCP packet to see if the application has any ; Data it wishes to send. The application cannot send more than TCP_SEG_SIZE ; bytes at one go. ; [TCP API Function] ; INPUT: none ; OUTPUT: {tcp1UnAckMSB,tcp1UnAckLSB} ; or {tcp2UnAckMSB,tcp2UnAckLSB} = number of bytes to transmit ; ****************************************************************************** ; check if tcp1 or tcp2's chance to transmit jb flags2.TCP_TXSEMA, :tcpConn2Tx ; tcp1 clrb flags2.TCP_SOCK ; indicate tcp1 conn. cse tcp1State, #TCP_ST_ESTABED ; check if in ; established state retp ; no, return IF DYNDNS sb flags2.DYNDNS_TXEN ; check if we may tx retp ; no clrb flags2.DYNDNS_TXEN ; yes, clear for next tx _bank DYNDNS_BANK ; DYNDNS_CLOSE = 0 ; DYNDNS closing or closed ; DYNDNS_CONNECT = 1 ; state machine in connection establishment ; DYNDNS_GET = 2 ; GET command sent, waiting for good/!good reply ; DYNDNS_RPLY = 3 ; Got reply. ; DYNDNS_WAIT = 4 ; Got WAIT response, now delay. ; DYNDNS_STOP = 5 ; Got 911 reply, now stop. cje DYNDNSState, #DYNDNS_GET, :DYNDNSSndGET ; chk if have to ; tx GET URL ; nothing cje DYNDNSState, #DYNDNS_RPLY, :DYNDNSWait ; chk if have to ; rx reply word cje DYNDNSState, #DYNDNS_CLOSE, :DYNDNSClose ; chk if have to ; close ;retp ; nothing? :DYNDNSSndGet mov DYNDNSStrPointer, #(DYNDNS_URL) ; make a pointer to the ; char string. bank TCP_BANK mov tcp1UnAckLSB, #(DYNDNS_URL_END-DYNDNS_URL) retp :DYNDNSClose ; Will the remote host will initiate the close? ; retp ENDIF retp ; tcp2 :tcpConn2Tx setb flags2.TCP_SOCK ; indicate tcp2 conn. cse tcp2State, #TCP_ST_ESTABED ; check if in ; established state retp ; no, return IF HTTP snb flags2.BROWSER_TYPE ; do not send anything to netscape ; type browser on a post. retp bank HTTP_BANK cje httpParseState, #2, :state2 cje httpParseState, #3, :state3 cje httpParseState, #4, :state4 retp :state2 ; check how much there is to send _bank EEPROM_BANK csae e2FileLenMSB, #(HTTP_SEG_SIZE>>8) jmp :lastSegment ; msb#1 < msb#2 cse e2FileLenMSB, #(HTTP_SEG_SIZE>>8) jmp :notLast ; msb#1 > msb#2 csa e2FileLenLSB, #(HTTP_SEG_SIZE&$00FF) jmp :lastSegment ; #1 <= #2 :notLast ; not the last segment so send as much as possible ; (i.e. full segment) sub e2FileLenLSB, #(HTTP_SEG_SIZE&$00FF) ; e2FileLen ; -= HTTP_SEG_SIZE sc ; dec e2FileLenMSB ; sub e2FileLenMSB, #(HTTP_SEG_SIZE>>8) ; _bank TCP_BANK mov tcp2UnAckMSB, #(HTTP_SEG_SIZE>>8) mov tcp2UnAckLSB, #(HTTP_SEG_SIZE&$00FF) retp :lastSegment ; last segment so send whatever is leftover mov w, e2FileLenMSB _bank TCP_BANK mov tcp2UnAckMSB, w _bank EEPROM_BANK mov w, e2FileLenLSB _bank TCP_BANK mov tcp2UnAckLSB, w bank HTTP_BANK inc httpParseState ; next-state = 3 retp ; no more to send so we close :state3 call @TCPAppClose retp :state4 ENDIF retp ; ****************************************************************************** TCPAppTxData ; This routine is called once for each byte the application has says it wishes ; to transmit. ; [TCP API Function] ; INPUT: none ; OUTPUT: w = Data byte to transmit ; ****************************************************************************** ; jump to current tcp connection code jb flags2.TCP_SOCK, :TCPAppTxData2 ; tcp1 IF DYNDNS _bank DYNDNS_BANK cje DYNDNSState, #DYNDNS_GET, :DYNDNSTxGet ; chk if we have ; to tx GET URL retp ; nothing? ; we have to send a GET URL <CRLF> :DYNDNSTxGet mov w, #(DYNDNS_URL >> 8) ; upper nibble jmp DYNDNSRdPrgMemData ENDIF retp ; tcp2 :TCPAppTxData2 IF HTTP bank HTTP_BANK cje httpURIHash, #URI1, :specialFile ; resource.htm cje httpURIHash, #URI2, :specialFile ; temperature.htm cje httpURIHash, #URI3, :specialFile2 ; postctrl.htm call @E2Read8Ack retp :specialFile call @E2Read8Ack mov globTemp1, w ; save temporarily csb globTemp1, #$F0 jmp :match mov w, globTemp1 retp ; look for magic number in file indicating Dynamic content :specialFile2 setb flags3.LED_LOCK ; lock access to LED call @E2Read8Ack mov globTemp1, w ; save temporarily csb globTemp1, #$F0 jmp :match2 mov w, globTemp1 retp :match2 ; look if led is on or off now jb LED_PORT.LED, :ledOffChar ; it is on, return last char of image for ledon.gif mov w, #'n' retp ; it is off, return last char of image for ledof.gif :ledOffChar mov w, #'f' retp :match cjne globTemp1, #$F0, :subMatch ; 0xF0 is the magic number :firstMatch bank HTTP_BANK mov globTemp2, httpURIHash mov fsr, #bcd3 cjne globTemp2, #URI1, :here mov w, pageCount inc pageCount jmp :here1 :here _bank ADC_BANK mov w, adc :here1 call @Bin8ToBCD mov w, bcd3+0 call @BCDToASCII retp :subMatch sub globTemp1, #$F0 _bank MISC_BANK mov fsr, #bcd3 add fsr, globTemp1 mov w, indf call @BCDToASCII ENDIF retp ; ****************************************************************************** _TCPAppRxData ; Called once for each byte received in a packet. Will only be called when ; tcpState is established. ; [TCP API Function] ; INPUT: w = received Data byte ; OUTPUT: none ; ****************************************************************************** ; jump to current tcp connection code jb flags2.TCP_SOCK, :TCPAppRxData2 ; tcp1 IF DYNDNS mov globTemp1, w ; store the rcvd byte test globTemp2 ; check if we got the reply code, ; the rest is junk snz retp ; yes, we got it, just return on junk ; bytes ; receive the reply code mov fsr, globTemp3 ; set pointer mov indf, globTemp1 ; move rcvd byte to rcv buffer inc globTemp3 ; advance pointer dec globTemp2 ; receive until counter done retp ; return to rcv some more bytes ENDIF retp ; tcp2 :TCPAppRxData2 IF HTTP mov globTemp1, w _bank HTTP_BANK ; check if this is 2nd packet from Netscape type browser, post jb flags2.BROWSER_TYPE, :fieldSrch ; look if we got the method already sb flags3.GOT_HTTP_METHOD jmp :methodSrch1 ; no, go to method search ; yes, we have the method, jump to correct method parser jb flags3.HTTP_METHOD, :postMethod jmp :defaultMethod :methodSrch1 cje globTemp1, #'P', :isPost ; is it a P ? clrb flags3.HTTP_METHOD ; it's GET setb flags3.GOT_HTTP_METHOD ; indicate we have the method jmp :defaultMethod :isPost setb flags3.HTTP_METHOD ; yes, so it must be POST or PUT setb flags3.GOT_HTTP_METHOD ; indicate we have the method setb flags3.LED_LOCK ; lock access to the LED clr httpParseState clr httpParseState2 retp :postMethod ; have to get the requested resource now to set file pointer jb flags3.GOT_URI, :fieldSrch ; check if we have to go test httpParseState ; directly to field srch jz :stateN0 cje httpParseState, #1, :stateN1 :stateN0 cse globTemp1, #' ' ; search for the space after the method retp ; keyword inc httpParseState ; got it, next-state = 1 retp :stateN1 cje globTemp1, #' ', :gotURI ; make URI until space after ; requested resource add httpURIHash, globTemp1 retp ; we have to search for the input field now. It's after 2 CRLFs :fieldSrch cje httpParseState, #1, :gotCtrl cje httpParseState, #2, :gotLf cje httpParseState, #3, :gotBlkLine cje httpParseState, #4, :gotField csne globTemp1, #$0d ; check for first ctrl inc httpParseState ; yes, got it retp ; no :gotCtrl cjne globTemp1, #$0a, :fldSrchRst inc httpParseState ; yes, got it retp ; no :gotLf cjne globTemp1, #$0d, :fldSrchRst ; check for blank line inc httpParseState ; yes, got to blank line retp ; no :gotBlkLine cjne globTemp1, #$0a, :fldSrchRst ; check for last char of ; blank line inc httpParseState ; yes, we are at the field now retp :gotField cje httpParseState2, #1, :gotl cje httpParseState2, #2, :gote cje httpParseState2, #3, :gotd cje httpParseState2, #4, :gotequal csne globTemp1, #'l' ; look for 'l' inc httpParseState2 ; yes, got it retp ; no :gotl csne globTemp1, #'e' ; look for 'e' inc httpParseState2 ; yes, got it retp ; no :gote csne globTemp1, #'d' ; look for 'd' inc httpParseState2 ; yes, got it retp ; no :gotd csne globTemp1, #'=' ; look for '=' inc httpParseState2 ; yes, got it retp ; no ; now the next byte is the control byte for the led control :gotequal cje globTemp1, #'1', :ledOn cje globTemp1, #'0', :ledOff cje globTemp1, #'t', :ledToggle retp :ledOn clrb LED_PORT.LED ; switch led on retp :ledOff setb LED_PORT.LED ; switch led off retp :ledToggle mov w, #(1<<LED) ; toggle led status xor LED_PORT, w retp :fldSrchRst clr httpParseState ; no, gotta start over. retp :defaultMethod test httpParseState jz :state0 cje httpParseState, #1, :state1 cjae httpParseState, #2, :state2 :state0 cse globTemp1, #' ' ; search for the space after the method retp inc httpParseState ; got it, next-state = 1 retp :state1 cje globTemp1, #' ', :gotURI; make URI until space after ; requested resource add httpURIHash, globTemp1 retp :gotURI ; got the requested resource, obtain pointer to file ; check if coming from post method jnb flags3.HTTP_METHOD, :gotURICont ; bit is set, so we came from post method clr httpParseState ; clear for field parser setb flags3.GOT_URI ; indicate we got URI for post field parser :gotURICont mov w, httpURIHash _bank EEPROM_BANK mov e2AddrLSB, w clr e2AddrMSB clc ; e2Addr = httpURIHash * 2 rl e2AddrLSB ; rl e2AddrMSB ; call @E2Init ; reset EEPROM call @E2SetAddr call @E2SendRdCmd call @E2Read8Ack mov e2AddrMSB, w call @E2Read8NoAckStop mov e2AddrLSB, w ; start reading from file call @E2SetAddr call @E2SendRdCmd ; file length call @E2Read8Ack mov e2FileLenMSB, w call @E2Read8Ack mov e2FileLenLSB, w ; file checksum (ignore) call @E2Read8Ack call @E2Read8Ack _bank HTTP_BANK sb flags3.HTTP_METHOD ; do not increment if post inc httpParseState ; next-state = 2 retp :state2 ; here we receive bytes from after the requested resource ENDIF retp IF DYNDNS ; ****************************************************************************** DYNDNSRdPrgMemData ; not relocatable. Must be in same page as caller ; Reads DYNDNS Data stored in program memory. ; INPUT: w contains upper nibble of prog memory location. ; DYNDNSPointer contains lower byte of prog mem location. ; OUTPUT: Data in w register ; ****************************************************************************** mov m, w ; into MODE register mov w, DYNDNSStrPointer ; lower byte (2 nibbles) inc DYNDNSStrPointer ; increment pointer iread ; read data from prog memory into w register retp ENDIF ORG $C00 ; Page6 TCPTransmit jmp _TCPTransmit TCPAppRxDone jmp _TCPAppRxDone TCPApp1Init jmp _TCPApp1Init IF DYNDNS DYNDNSCompareGood jmp _DYNDNSCompareGood DYNDNSCompareWait jmp _DYNDNSCompareWait DYNDNSCompare911 jmp _DYNDNSCompare911 DYNDNSCompare354 jmp _DYNDNSCompare354 ENDIF ; ****************************************************************************** SetTCBPointer ; Sets the fsr register to point to the correct TCB ; INPUT: globTemp1=offset into TCB1_BANK or TCB2_BANK ; OUTPUT: fsr contains pointer to variable in TCB bank ; ****************************************************************************** ; check if pointer to be set for tcp1 or 2 connection. jb flags2.TCP_SOCK, :tcb2pointer ; tcp1 add globTemp1, #TCB1_BANK mov fsr, globTemp1 ; make pointer to TCB1_BANK for tcp1 retp ; tcp2 :tcb2pointer add globTemp1, #TCB2_BANK mov fsr, globTemp1 ; make pointer to TCB2_BANK for tcp2 retp ; ****************************************************************************** CheckSocket1IP ; Checks if remoteIP is in tcp socket1 ; INPUT: remoteIP3-0, sock1RemoteIP3-0 ; OUTPUT: Z set if in there ; ****************************************************************************** mov globTemp1, #remoteIP3 mov globTemp3, #sock1RemoteIP3 call @Compare4Inc retp ; ****************************************************************************** CheckSocket2IP ; Checks if remoteIP is in tcp socket2 ; INPUT: remoteIP3-0, sock2RemoteIP3-0 ; OUTPUT: Z set if in there ; ****************************************************************************** mov globTemp1, #remoteIP3 mov globTemp3, #sock2RemoteIP3 call @Compare4Inc retp ; ****************************************************************************** CopyRemotePortTCB1 ; Copies tcpRemotePortMSB,LSB into tcb1RemotePortMSB,LSB ; INPUT: tcpRemotePortMSB,LSB ; OUTPUT: tcb1RemotePortMSB,LSB ; ****************************************************************************** bank TCPPORT_BANK mov w, tcpRemotePortMSB bank TCB1_BANK mov tcb1RemotePortMSB, w bank TCPPORT_BANK mov w, tcpRemotePortLSB bank TCB1_BANK mov tcb1RemotePortLSB, w retp ; ****************************************************************************** CopyRemotePortTCB2 ; Copies tcpRemotePortMSB,LSB into tcb2RemotePortMSB,LSB ; INPUT: tcpRemotePortMSB,LSB ; OUTPUT: tcb2RemotePortMSB,LSB ; ****************************************************************************** bank TCPPORT_BANK mov w, tcpRemotePortMSB bank TCB2_BANK mov tcb2RemotePortMSB, w bank TCPPORT_BANK mov w, tcpRemotePortLSB bank TCB2_BANK mov tcb2RemotePortLSB, w retp ; ****************************************************************************** CheckLocalPortTCB1 ; Compares tcpLocalPortLSB, tcpLocalPortMSB against tcb1LocalPortLSB, ; tcb1LocalPortMSB ; INPUT: tcpLocalPortLSB, tcpLocalPortMSB, tcb1LocalPortLSB, tcb1LocalPortMSB ; OUTPUT: Z set if match ; ****************************************************************************** bank TCPPORT_BANK mov w, tcpLocalPortMSB bank TCB1_BANK xor w, tcb1LocalPortMSB sz retp mov w, tcb1LocalPortLSB bank TCPPORT_BANK xor w, tcpLocalPortLSB retp ; ****************************************************************************** CheckLocalPortTCB2 ; Compares tcpLocalPortLSB, tcpLocalPortMSB against tcb2LocalPortLSB, ; tcb2LocalPortMSB ; INPUT: tcpLocalPortLSB, tcpLocalPortMSB, tcb2LocalPortLSB, tcb2LocalPortMSB ; OUTPUT: Z set if match ; ****************************************************************************** bank TCPPORT_BANK mov w, tcpLocalPortMSB bank TCB2_BANK xor w, tcb2LocalPortMSB sz retp mov w, tcb2LocalPortLSB bank TCPPORT_BANK xor w, tcpLocalPortLSB retp ; ****************************************************************************** TCPConnectionManager ; Manages TCP connections. Checks incoming tcp packets against listening ports, ; makes new sockets and indicates for which tcp connection the packet is. ; INPUT: none ; OUTPUT: flags2.TCP_SOCK ; ****************************************************************************** ; check if we are waiting for an ARP response. ; have to Dump & ignore all incoming tcp packets until ARP ; response received or ARP timed out. The tcp receive functions ; can respond with sending tcp packets which will overwrite ; the stalled tcp packet. If we recorded which tcp conn. buffer ; has a stalled packet, we can accept tcp packets for the other ; tcp conn. but let's keep it simple now jb flags3.ARP_REQ_SENT, :ignorePacket ; pre-screening to check if the local port=service is offered call @CheckLocalPortTCB1 ; check if for a port ; we're listening on jz :TCPSocket1 ; yes, service is bound ; to TCB1_BANK call @CheckLocalPortTCB2 ; check if for a port ; we're listening on jz :TCPSocket2 ; yes, service is bound ; to TCB2_BANK jmp :ignorePacket ; no, we Don't offer the service :TCPSocket1 call @CheckSocket1IP ; check if remote IP ; is in socket1 jnz :CreateTCPSocket1 ; no, make a new conn./socket call @CheckRemotePortTCB1 ; yes, check if remote port ; is in TCB1_BANK jz :TCPConnection1 ; yes, packet is for tcp conn. 1 jmp :CreateTCPSocket1 ; no, but make a new conn. ; if we're listening :TCPSocket2 call @CheckSocket2IP ; check if remote IP ; is in socket2 jnz :CreateTCPSocket2 ; no, make a new conn./socket call @CheckRemotePortTCB2 ; yes, check if remote port ; is in TCB2_BANK jz :TCPConnection2 ; yes, packet is for tcp conn. 2 jmp :CreateTCPSocket2 ; no, but make a new conn. ; if we're listening :CreateTCPSocket1 ; we may only create a socket when tcp1 connection is in ; LISTEN state _bank TCP_BANK cjne tcp1State, #TCP_ST_LISTEN, :ignorePacket ; create tcp1 socket call @CopyRemoteIPSocket1 ; store remote IP in socket1 call @CopyRemotePortTCB1 ; store remote port in socket1 jmp :TCPConnection1 :CreateTCPSocket2 ; we may only create a socket when tcp2 connection is in ; LISTEN state _bank TCP_BANK cjne tcp2State, #TCP_ST_LISTEN, :ignorePacket ; create tcp2 socket call @CopyRemoteIPSocket2 ; store remote IP in socket2 call @CopyRemotePortTCB2 ; store remote port in socket2 jmp :TCPConnection2 :TCPConnection1 clrb flags2.TCP_SOCK ; indicate tcp packet is for tcp1 clz ; indicate packet is ok retp :TCPConnection2 setb flags2.TCP_SOCK ; indicate tcp packet is for tcp2 clz ; indicate packet is ok retp :ignorePacket call @NICDumpRxFrame ; discard the tcp packet stz ; indicate packet is not ok - ; don't process it retp ; ****************************************************************************** _TCPTransmit ; See if the application has any Data to transmit. If there are no outstanding ; packets and the application has Data, then transmit a packet. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank TCP_BANK ; _bank cus we called ; TCPAppInit priorly ; check which tcp connection has chance to tx jb flags2.TCP_TXSEMA, :tcp2Tx ; tcp1 has tx chance cjae tcp1State, #TCP_ST_ESTABED, :ok1 ; is tcp1 ; connection estab? retp ; exit, tcp1 connection ; not established ; yes, tcp1 is est. :ok1 test tcp1UnAckMSB ; are there any bytes ; unacknowledged? jnz :timeout1 test tcp1UnAckLSB jnz :timeout1 cje tcp1State, #TCP_ST_FINWAIT1, :finTimeout ; check for ; FIN timeout jmp :askAppTxData ; tcp2 has tx chance :tcp2Tx cjae tcp2State, #TCP_ST_ESTABED, :ok2 ; is tcp2 ; connection estab? retp ; exit, tcp2 connection ; not established ; yes, tcp2 is est. :ok2 test tcp2UnAckMSB ; are there any bytes ; unacknowledged? jnz :timeout2 test tcp2UnAckLSB jnz :timeout2 cje tcp2State, #TCP_ST_FINWAIT1, :finTimeout ; check for ; FIN timeout :askAppTxData call @TCPAppTxBytes ; ask the application if ; it wants to tx _bank TCP_BANK ; _bank cus we called ; TCPAppTxBytes priorly ; check if unack bytes from tcp1 or 2 jb flags2.TCP_SOCK, :chkAppTxDataCon2 ; tcp1 mov w, tcp1UnAckMSB or w, tcp1UnAckLSB jnz :appHasTxData retp ; nope, it Doesn't; so we're Done here then ; tcp2 :chkAppTxDataCon2 mov w, tcp2UnAckMSB or w, tcp2UnAckLSB jnz :appHasTxData retp ; nope, it Doesn't; so we're Done here then :appHasTxData ; start a TCP packet ; check if for tcp1 or 2 jb flags2.TCP_SOCK, :loadUnackTcp2 ; tcp1 mov tcpLengthLSB, tcp1UnAckLSB ; tcpLength = ; # bytes to transmit mov tcpLengthMSB, tcp1UnAckMSB jmp :contAppHasTxData ; tcp2 ; tcpLength = # bytes to transmit :loadUnackTcp2 mov tcpLengthLSB, tcp2UnAckLSB mov tcpLengthMSB, tcp2UnAckMSB :contAppHasTxData mov globTemp1, #(tcb1Flags-TCB1_BANK) ; set pointer to correct tcb for current tcp connection call @SetTCBPointer mov indf, #((1<TCP_FLAG_PSH)|(1<<TCP_FLAG_ACK)) call @TCPCheckSumInit call @TCPStartPktOut ; send the header ; insert the packet Data while computing the checksum ; over the Data bank TCP_BANK ; check if copy for tcp1 or 2 jb flags2.TCP_SOCK, :cpyUnAckTCP2 ; tcp1 mov tcpTmpLSB, tcp1UnAckLSB mov tcpTmpMSB, tcp1UnAckMSB jmp :dataLoopBgn ; tcp2 :cpyUnAckTCP2 mov tcpTmpLSB, tcp2UnAckLSB mov tcpTmpMSB, tcp2UnAckMSB :dataLoopBgn inc tcpTmpMSB ; so that we can loop easier later :dataLoop call @TCPAppTxData _banky TCP_BANK ; cus we called TCPAppTxData ; priorly call @NICWriteAgain ; which Doesn't clobber w, ; which is nice call @TCPCheckSumAcc ; accumulate the checksum decsz tcpTmpLSB jmp :dataLoop decsz tcpTmpMSB jmp :dataLoop ; now go back and fill in the TCP checksum bank NIC_BANK ; use correct tx buffer for current tcp connection sb flags2.TCP_SOCK mov w, #TXBUF2_START snb flags2.TCP_SOCK mov w, #TXBUF3_START mov nicCopySrcMSB, w mov nicCopySrcLSB, #(6+6+2+20+16) ; TCP <checksum> (MSB) bank TCP_BANK mov w, /tcpCheckSumMSB call @NICBufWrite bank NIC_BANK inc nicCopySrcLSB bank TCP_BANK mov w, /tcpCheckSumLSB call @NICBufWrite call @NICSendTxFrame ; end and send the packet bank TIMER_BANK ; initialise the restart timer ; check if tcp1 or 2 timer to be cleared jb flags2.TCP_SOCK, :initTcp2Timer ; tcp1 clr tcp1TimerMSB clr tcp1TimerLSB retp ; tcp2 :initTcp2Timer clr tcp2TimerMSB clr tcp2TimerLSB retp :finTimeout bank TIMER_BANK ; check if tcp1 or 2 timer to be checked jb flags2.TCP_TXSEMA, :chkClrTcp2Tmr ; tcp1 csae tcp1TimerMSB, #TCP_RESTART_EXP ; has the restart timer ; expired? retp ; no clr tcp1TimerMSB ; yes, initialise the ; restart timer clr tcp1TimerLSB jmp @TCPSendFin ; tcp2 :chkClrTcp2Tmr csae tcp2TimerMSB, #TCP_RESTART_EXP ; has the timer expired? retp ; no clr tcp2TimerMSB ; yes, initialise the ; restart timer clr tcp2TimerLSB jmp @TCPSendFin ; check if timed out on waiting for ack on tcp connection1 :timeout1 bank TIMER_BANK csae tcp1TimerMSB, #TCP_RESTART_EXP ; has the restart timer ; expired? retp ; no clr tcp1TimerMSB ; yes, initialise the ; restart timer clr tcp1TimerLSB clrb flags2.TCP_SOCK ; indicate conn1. jmp @TCPReTransmit ; transmit the packet ; again :timeout2 bank TIMER_BANK csae tcp2TimerMSB, #TCP_RESTART_EXP ; has the restart timer ; expired? retp ; no clr tcp2TimerMSB ; yes, initialise the ; restart timer clr tcp2TimerLSB setb flags2.TCP_SOCK ; indicate conn2. jmp @TCPReTransmit ; transmit the packet ; again IF DYNDNS ; ****************************************************************************** _DYNDNSCompareGood ; Compares the DYNDNS reply code in memory against Good. ; INPUT: DYNDNSReplyCode ; OUTPUT: Z = set if reply code ; ****************************************************************************** _bank DYNDNSREPLY_BANK mov w, #'g' xor w, DYNDNSReplyCode sz retp mov w, #'o' xor w, DYNDNSReplyCode+1 sz retp mov w, #'o' xor w, DYNDNSReplyCode+2 retp ; ****************************************************************************** _DYNDNSCompareWait ; Compares the DYNDNS reply code in memory against Wait. ; INPUT: DYNDNSReplyCode ; OUTPUT: Z = set if reply code ; ****************************************************************************** _bank DYNDNSREPLY_BANK mov w, #'w' xor w, DYNDNSReplyCode sz retp mov w, #'a' xor w, DYNDNSReplyCode+1 sz retp mov w, #'i' xor w, DYNDNSReplyCode+2 retp ; ****************************************************************************** _DYNDNSCompare911 ; Compares the DYNDNS reply code in memory against 911 ; INPUT: DYNDNSReplyCode ; OUTPUT: Z = set if reply code is 911 ; ****************************************************************************** _bank DYNDNSREPLY_BANK mov w, #'9' xor w, DYNDNSReplyCode sz retp mov w, #'1' xor w, DYNDNSReplyCode+1 sz retp mov w, #'1' xor w, DYNDNSReplyCode+2 retp ; ****************************************************************************** _DYNDNSCompare354 ; Compares the DYNDNS reply code in memory against 354 ; INPUT: DYNDNSReplyCode ; OUTPUT: Z = set if reply code is 220 ; ****************************************************************************** _bank DYNDNSREPLY_BANK mov w, #'3' xor w, DYNDNSReplyCode3 sz retp mov w, #'5' xor w, DYNDNSReplyCode2 sz retp mov w, #'4' xor w, DYNDNSReplyCode1 retp ENDIF ; ****************************************************************************** _TCPAppRxDone ; This is called following the last call to TCPAppRxData(). It signifies the ; end of the received packet ; [TCP API Function] ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; jump to current tcp connection code jb flags2.TCP_SOCK, :TCPAppRxDone2 ; tcp1 IF DYNDNS _bank DYNDNS_BANK cje DYNDNSState, #DYNDNS_GET, :DYNDNSGet ; check if we ; sent a GETR URL retp ; nothing? ; we have established a tcp conn with a remote DYNDNS :DYNDNSGet call @DYNDNSCompareGood ; check if we got Good. ; sz ; jmp :DYNDNSWeQuit ; no, we got something else ; we got a 220 service ready reply ; jmp :DYNDNSNxtState ; we have received a response to our HELO sent. ; We expect it to be 250 :DYNDNSNxtState _bank DYNDNS_BANK inc DYNDNSState setb flags2.DYNDNS_TXEN ; enable DYNDNS transmit so that ; a new command ; or text can be sent ENDIF retp ; tcp2 :TCPAppRxDone2 IF HTTP ; check if end of 2nd packet rcvd from Netscape type browser _bank HTTP_BANK jnb flags2.BROWSER_TYPE, :methodChk clrb flags2.BROWSER_TYPE ; yes, clear flag jmp :getM ; reset other flags ; check if we rcvd a packet with http post and did not get 'led' ; field meaning it came from a Netscape browser. :methodChk jnb flags3.HTTP_METHOD, :getM ; skip chk if method get ; it is post. check if we got the 'led' field in this packet cje httpParseState2, #4, :getM setb flags2.BROWSER_TYPE ; no, netscape type browser clr httpParseState ; clear for parser in 2nd pkt :getM clrb flags3.GOT_HTTP_METHOD ; clear have method for nxt pkt clrb flags3.GOT_URI mov w, #2 ; restore the state of the mov httpParseState, w ; httpParseState variable we ENDIF ; borrowed for the POST parser retp ; ****************************************************************************** _TCPApp1Init ; Called repeatedly as long as TCP connection1 state is closed ; [TCP API Function] ; INPUT: none ; OUTPUT: none ; ****************************************************************************** IF DYNDNS ; ; DYNDNS - Check if 8 byte timer has expired, or if button pressed ; ; ; check if this is the first time sw is pressed, or if it is ; still held in from the first time it was pressed. ; If email goes through before switch is released this will ; prevent another. jnb flags2.SW_PRESSED, :firstPressChk mov w, #(1<<SW) ; look if SW1 is pressed and w, SW_PORT snz ; no, so it must be released now retp ; yes, have to wait until released clrb flags2.SW_PRESSED ; check if the prev email was accepted by the remote DYNDNS, so we ; can try again. jnb flags3.DYNDNS_OK, :sendMailAgain ; check here if we want to send email. :firstPressChk mov w, #(1<<SW) ; look if SW1 is pressed and w, SW_PORT sz ; yes retp ; no, just return setb flags2.SW_PRESSED ; indicate switch is pressed ; yes, so we need to send an email now or again :sendMailAgain clrb flags3.DYNDNS_OK ; clear the 'mail went through' indicator ; before we send it _bank DYNDNS_BANK mov w, #DYNDNS_CONNECT ; start DYNDNS state machine to connect mov DYNDNSState, w ; set up local & remote ports for tcp1 connection _bank TCB1_BANK mov tcb1LocalPortLSB, #100 mov tcb1LocalPortMSB, #100 mov tcb1RemotePortLSB, #DYNDNS_PORT_LSB mov tcb1RemotePortMSB, #DYNDNS_PORT_MSB ; fill in remote IP to connect with in tcp socket _bank TCPSOCKET_BANK mov sock1RemoteIP3, #DYNDNS_SERVER_IP3 mov sock1RemoteIP2, #DYNDNS_SERVER_IP2 mov sock1RemoteIP1, #DYNDNS_SERVER_IP1 mov sock1RemoteIP0, #DYNDNS_SERVER_IP0 ; indicate tcp1 connection clrb flags2.TCP_SOCK jmp @TCPAppActiveOpen ; open a tcp connection on socket1 ENDIF retp ORG $E00 ; Page7 TCPApp2Init jmp _TCPApp2Init DeleteSocket1 jmp _DeleteSocket1 DeleteSocket2 jmp _DeleteSocket2 IF HTTP ; jump table can be moved with all E2 functions if neccessary. E2Delay600ns jmp _E2Delay600ns E2Delay900ns jmp _E2Delay900ns E2Delay1300ns jmp _E2Delay1300ns E2SDAInput jmp _E2SDAInput E2SDAOutputHi jmp _E2SDAOutputHi E2SDAOutputLo jmp _E2SDAOutputLo E2GenStartCond jmp _E2GenStartCond E2GenStopCond jmp _E2GenStopCond E2Write8 jmp _E2Write8 E2Read8 jmp _E2Read8 E2Read8Ack jmp _E2Read8Ack E2Read8NoAckStop jmp _E2Read8NoAckStop E2RecvAck jmp _E2RecvAck E2SendAck jmp _E2SendAck E2SendNotAck jmp _E2SendNotAck E2SendRdCmd jmp _E2SendRdCmd E2SendWrCmd jmp _E2SendWrCmd E2SetAddr jmp _E2SetAddr Bin8ToBCD jmp _Bin8ToBCD BCDToASCII jmp _BCDToASCII ENDIF IF DHCP DHCPREQUESTSend jmp _DHCPREQUESTSend DHCPDISCOVERSend jmp _DHCPDISCOVERSend DHCPSendCommon2 jmp _DHCPSendCommon2 UDPProcBcstPktIn jmp _UDPProcBcstPktIn ENDIF ; ****************************************************************************** NICReadAgain_7 ; Shortform for calling NICReadAgain(), which is in Page1 (This is in Page7) ; ****************************************************************************** jmp @NICReadAgain ; ****************************************************************************** NICWriteAgain_7 ; Shortform for calling NICWriteAgain(), which is in Page1 (This is in Page7) ; ****************************************************************************** jmp @NICWriteAgain ; ****************************************************************************** NICDumpRxFrame_7 ; Shortform for calling NICDumpRxFrame(), which is in Page1 (This is in Page7) ; ****************************************************************************** jmp @NICDumpRxFrame ; ****************************************************************************** UDPEndPktOut ; Wraps up and transmits the UDP packet ; [UDP API Function] ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank NIC_BANK jmp @NICSendTxFrameNow ; ****************************************************************************** UDPAppInit ; Application UDP Initialization code (Example) ; This function is called automatically once by the stack During startup ; [UDP API Function] ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank UDP_BANK mov udpRxDestPortMSB, #UDP_RX_DEST_MSB mov udpRxDestPortLSB, #UDP_RX_DEST_LSB retp ; ****************************************************************************** UDPAppProcPktIn ; Application Incoming UDP packet handler (Example) ; This function is called whenever an application (matches udpRxDestPortxSB) ; packet is received. The appplication can call NICReadAgain() to extract ; sequentially extract each byte of the <data> field in the UDP packet. ; [UDP API Function] ; INPUT: {udpRxDataLenMSB,udpRxDataLenLSB} = number of bytes in UDP <data> ; {udpRxSrcPortMSB,udpRxSrcPortLSB} = UDP <source_port> ; OUTPUT: none ; ****************************************************************************** call NICReadAgain_7 and w, #%01000000 xor ra, w ; toggle I/O pins _bank UDP_BANK clr udpTxSrcPortMSB clr udpTxSrcPortLSB mov udpTxDestPortMSB, udpRxSrcPortMSB mov udpTxDestPortLSB, udpRxSrcPortLSB clr udpTxDataLenMSB ; send 2 bytes of data mov udpTxDataLenLSB, #2 ; call UDPStartPktOut mov w, ra ; send new port state call NICWriteAgain_7 mov w, #$00 ; one-byte padding call NICWriteAgain_7 jmp UDPEndPktOut ; ****************************************************************************** UDPStartPktOut ; Starts an outgoing UDP packet by constructing an IP and UDP packet header ; [UDP API Function] ; INPUT: {remoteIP0-3} = Destination IP addr for UDP pkt ; {udpTxSrcPortMSB,udpTxSrcPortLSB} = UDP Source Port ; {udpTxDestPortMSB,udpTxDestPortLSB} = UDP Destination Port ; {udpTxDataLenMSB,udpTxDataLenLSB} = UDP Data Length (just Data) ; OUTPUT: none ; ****************************************************************************** ; compute IP <total_length> _bank UDP_BANK mov w, udpTxDataLenLSB _bank IP_BANK mov ipLengthLSB, w _bank UDP_BANK mov w, udpTxDataLenMSB _bank IP_BANK mov ipLengthMSB, w add ipLengthLSB, #(20+8) ; add in size of UDP hdr (8) ; and IP hdr (20) snc inc ipLengthMSB ; update IP <identifier> inc ipIdentLSB snz inc ipIdentMSB ; set IP <protocol> for UDP mov ipProtocol, #17 ; compute IP <header_checksum> call @IPGenCheckSum ; now we're ready to construct the IP header call @IPStartPktOut ; then construct the UDP header _bank UDP_BANK ; UDP <source_port> mov w, udpTxSrcPortMSB call NICWriteAgain_7 mov w, udpTxSrcPortLSB call NICWriteAgain_7 ; UDP <destination_port> mov w, udpTxDestPortMSB call NICWriteAgain_7 mov w, udpTxDestPortLSB call NICWriteAgain_7 ; UDP <length> mov w, #8 add w, udpTxDataLenLSB mov w, udpTxDataLenMSB snc inc wreg call NICWriteAgain_7 mov w, #8 add w, udpTxDataLenLSB call NICWriteAgain_7 ; UDP <checksum> = 0 mov w, #$0 call NICWriteAgain_7 jmp NICWriteAgain_7 ; ****************************************************************************** UDPProcPktIn ; Processes an Incoming UDP packet ; INPUT: nicCurrPktPtr = points to beginning of received packet ; OUTPUT: none ; ****************************************************************************** _bank UDP_BANK ; UDP <source_port> call NICReadAgain_7 mov udpRxSrcPortMSB, w call NICReadAgain_7 mov udpRxSrcPortLSB, w ; UDP <destination_port> call NICReadAgain_7 xor w, udpRxDestPortMSB jnz :outtaHere call NICReadAgain_7 xor w, udpRxDestPortLSB jnz :outtaHere ; UDP <message_length> call NICReadAgain_7 mov udpRxDataLenMSB, w call NICReadAgain_7 mov udpRxDataLenLSB, w ; ignore UDP <checksum> REPT 2 call NICReadAgain_7 ENDR ; UDP <data> IF DHCP snb flags.RX_IS_IP_BCST call UDPProcBcstPktIn ; prevent UDP API func call when in config _bank DHCP_BANK jb dhcpFlags.DHCP_CONFIG, :outtaHere ENDIF sb flags.RX_IS_IP_BCST call UDPAppProcPktIn :outtaHere _bank IP_BANK jmp NICDumpRxFrame_7 IF DHCP ; ****************************************************************************** CheckIPLeaseExpire ; Checks if our IP lease has expired. If it has, renew it. If we never got a ; lease in the first place, just return. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** sb flags2.GOT_IP_LEASE ; test if we got an IP lease retp ; return, we never got an IP lease ; we got an IP lease previously ; check if it is expiring. We're comparing seconds against ; seconds here _bank DHCP_BANK mov w, dhcpIPLeaseTm3 xor w, dhcpTimer3 jnz :outtaLeaseChk mov w, dhcpIPLeaseTm2 xor w, dhcpTimer2 jnz :outtaLeaseChk mov w, dhcpIPLeaseTm1 xor w, dhcpTimer1 jnz :outtaLeaseChk mov w, dhcpIPLeaseTm0 xor w, dhcpTimer0 jnz :outtaLeaseChk ; Lease has expired, renew it clrb flags2.GOT_IP_LEASE ; reset IP lease. setb flags2.RENEW_IP_LEASE ; indicate this is a lease ; renewal jmp DHCPConfig ; start the DHCP configuration :outtaLeaseChk retp ; ****************************************************************************** DHCPConfig ; This function uses DHCP, Dynamic Host Configuration Protocol, to configure the ; iSX. The result is an assigned IP address for a certain time. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank DHCP_BANK setb dhcpFlags.DHCP_CONFIG ; indicate DHCP config in progress ; initialize UDP receive port for DHCP _bank UDP_BANK clr udpRxDestPortMSB ; DHCP(BOOTP) Client (Port 68) mov udpRxDestPortLSB, #68 ; ; DHCPConfig will be called again and again for IP lease ; renewals. Check if this is a renewal or a first entry from ; startup jb flags2.RENEW_IP_LEASE, :leaseRenew ; Send a DHCP Discovery message :dhcpDiscSend call DHCPDISCOVERSend ; send DHCPDISCOVER message _bank DHCP_BANK clr dhcpTimer0 ; initialize receive timeout timer ; Wait with timeout for an incoming frame ; on each timeout, a new Discovery will be sent until max tries ; reached :dhcpWaitOffer call @NICWaitRxFrame ; check if we received something jb flags2.GOT_RX_FRAME, :dhcpGotRxFrame ; check if we ; got something _bank DHCP_BANK cje dhcpTimer0, #DHCP_DISC_EXP, :outtaDHCP ; check if ; timeout - Disc jmp :dhcpWaitOffer ; not timed out yet, wait some more ; Check if rcvd frame is UDP (DHCP carrier). ; If it is UDP, process contents, else go back to ; waiting for an incoming frame. :dhcpGotRxFrame call @CheckIPDatagram jnb flags.RX_IS_UDP, :dhcpWaitOffer clrb flags.RX_IS_UDP call UDPProcPktIn sb flags.GOT_DHCP_OFFER jmp :dhcpWaitOffer ; If we got to here, we rcvd a valid DHCP offer. ; Send a DHCP request message :leaseRenew clr globTemp3 ; initialize re-transmit counter :dhcpReqSend cje globTemp3, #DHCP_REQ_TRIES, :outtaDHCP ; tried enough? _bank DHCP_BANK clr dhcpTimer0 call DHCPREQUESTSend inc globTemp3 ; Wait with timeout for an incoming frame ; on each timeout, a new request will be sent ; until max tries reached :dhcpWaitAck call @NICWaitRxFrame jb flags2.GOT_RX_FRAME, :dhcpGotAck _bank DHCP_BANK cje dhcpTimer0, #DHCP_REQ_EXP, :dhcpReqSend jmp :dhcpWaitAck ; wait some more ; Check if rcvd frame is UDP (DHCP carrier). ; If it is UDP, process contents, else go back to waiting ; for an incoming frame. :dhcpGotAck call @CheckIPDatagram ; check packet type jnb flags.RX_IS_UDP, :dhcpWaitAck ; if not UDP ; go back to waiting clrb flags.RX_IS_UDP call UDPProcPktIn ; is UDP, process contents sb flags2.GOT_IP_LEASE ; check if we got an IP lease jmp :dhcpWaitAck ; no wait some more ; reset 1sec renewal timers _bank DHCP_BANK clr dhcpBaseTimer0 clr dhcpBaseTimer1 clr dhcpTimer0 clr dhcpTimer1 clr dhcpTimer2 clr dhcpTimer3 :outtaDHCP clrb dhcpFlags.DHCP_CONFIG ; reset call @UDPAppInit ; restore the user UDP application port ; check if successful, otherwise rebind jb flags2.GOT_IP_LEASE, :dhcpConfigExit jmp @Main ; rebind ; success, exit normally :dhcpConfigExit clrb flags2.RENEW_IP_LEASE ; reset IP lease renewal retp ; ****************************************************************************** DHCPSendCommon1 ; Helper function for DHCPDISCOVERSend and DHCPREQUESTSend ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; set ethernet addr to broadcast addr _bank NIC_BANK mov w, #$FF mov nicRemoteEth0, w mov nicRemoteEth1, w mov nicRemoteEth2, w mov nicRemoteEth3, w mov nicRemoteEth4, w mov nicRemoteEth5, w ; set IP addr to broadcast addr bank IP_BANK mov w, #$FF mov remoteIP3, w mov remoteIP2, w mov remoteIP1, w mov remoteIP0, w _bank UDP_BANK clr udpTxSrcPortMSB ; DHCP client mov udpTxSrcPortLSB, #68 ; clr udpTxDestPortMSB ; DHCP server mov udpTxDestPortLSB, #67 ; call @UDPStartPktOut ; <op> mov w, #1 call NICWriteAgain_7 ; <htype> mov w, #1 call NICWriteAgain_7 ; <hlen> mov w, #6 call NICWriteAgain_7 ; <hops> mov w, #0 call NICWriteAgain_7 ; <transaction_id> = 0xABABABAB mov w, #$AB REPT 4 call NICWriteAgain_7 ENDR ; <seconds> = 256 mov w, #1 REPT 2 call NICWriteAgain_7 ENDR ; <flags> mov w, #$80 call NICWriteAgain_7 mov w, #0 jmp NICWriteAgain_7 ; ****************************************************************************** _DHCPSendCommon2 ; Helper function for DHCPDISCOVERSend and DHCPREQUESTSend ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; <client_hw_addr> mov w, #SX_ETH_ADDR0 call NICWriteAgain_7 mov w, #SX_ETH_ADDR1 call NICWriteAgain_7 mov w, #SX_ETH_ADDR2 call NICWriteAgain_7 mov w, #SX_ETH_ADDR3 call NICWriteAgain_7 mov w, #SX_ETH_ADDR4 call NICWriteAgain_7 mov w, #SX_ETH_ADDR5 call NICWriteAgain_7 ; <client_hw_addr>,<server_host_name>,<boot_filename> mov globTemp1, #(10+64+128) mov w, #0 :loop2 call NICWriteAgain_7 decsz globTemp1 jmp :loop2 ; <option_magic_cookie> mov w, #99 call NICWriteAgain_7 mov w, #130 call NICWriteAgain_7 mov w, #83 call NICWriteAgain_7 mov w, #99 jmp NICWriteAgain_7 ; ****************************************************************************** _DHCPDISCOVERSend ; Send DHCPDISCOVER message ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank UDP_BANK clr udpTxDataLenMSB mov udpTxDataLenLSB, #(240+3+0+1) ; without req-IP option ;mov udpTxDataLenLSB, #(240+3+6+1) ; with req-IP option call DHCPSendCommon1 ; <client_IP>, <your_IP>,<server_IP>,<router_IP> = 0 mov globTemp1, #(4+4+4+4) mov w, #0 :loop1 call NICWriteAgain_7 decsz globTemp1 jmp :loop1 call DHCPSendCommon2 ; <option-message_type> mov w, #53 call NICWriteAgain_7 mov w, #1 call NICWriteAgain_7 mov w, #1 ; DHCPDISCOVER call NICWriteAgain_7 ; <option-requested_IP> -- optional ;mov w, #50 ;call NICWriteAgain_7 ;mov w, #4 ;call NICWriteAgain_7 ;mov w, #SX_IP_ADDR3 ;call NICWriteAgain_7 ;mov w, #SX_IP_ADDR2 ;call NICWriteAgain_7 ;mov w, #SX_IP_ADDR1 ;call NICWriteAgain_7 ;mov w, #SX_IP_ADDR0 ;call NICWriteAgain_7 ; <option-end_option> -- not optional mov w, #255 call NICWriteAgain_7 ; and ... that should Do it! jmp UDPEndPktOut ; ****************************************************************************** _DHCPREQUESTSend ; Send DHCPREQUEST message ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank UDP_BANK mov udpTxDataLenMSB, #((240+3+6+6+1)>>8) mov udpTxDataLenLSB, #((240+3+6+6+1)&$FF) call DHCPSendCommon1 ; <client_IP> _bank IP_BANK mov w, myIP3 call NICWriteAgain_7 mov w, myIP2 call NICWriteAgain_7 mov w, myIP1 call NICWriteAgain_7 mov w, myIP0 call NICWriteAgain_7 ; <your_IP>,<server_IP>,<router_IP> = 0 mov globTemp1, #(4+4+4) mov w, #0 :loop1 call NICWriteAgain_7 decsz globTemp1 jmp :loop1 call DHCPSendCommon2 ; <option-message_type> mov w, #53 call NICWriteAgain_7 mov w, #1 call NICWriteAgain_7 mov w, #3 ; DHCPREQUEST call NICWriteAgain_7 ; <option-server_id> mov w, #54 ; option server identifier call NICWriteAgain_7 mov w, #4 ; length call NICWriteAgain_7 _bank DHCP_BANK mov w, dhcpServerId3 call NICWriteAgain_7 mov w, dhcpServerId2 call NICWriteAgain_7 mov w, dhcpServerId1 call NICWriteAgain_7 mov w, dhcpServerId0 call NICWriteAgain_7 ; <option-requested_IP> -- not optional mov w, #50 call NICWriteAgain_7 mov w, #4 call NICWriteAgain_7 _bank IP_BANK mov w, myIP3 call NICWriteAgain_7 mov w, myIP2 call NICWriteAgain_7 mov w, myIP1 call NICWriteAgain_7 mov w, myIP0 call NICWriteAgain_7 ; <option-end_option> -- not optional mov w, #255 call NICWriteAgain_7 ; and ... that should do it! jmp UDPEndPktOut ; ****************************************************************************** _UDPProcBcstPktIn ; The only kind of broadcast UDP packets accepted are DHCP messages: DHCPOFFER ; and DHCPACK ; INPUT: none ; OUTPUT: none ; ****************************************************************************** call NICReadAgain_7 xor w, #2 ; check <op> = BOOTP reply jnz :outtaHere call NICReadAgain_7 xor w, #1 ; check <htype> = 1 jnz :outtaHere call NICReadAgain_7 xor w, #6 ; check <hlen> = 6 jnz :outtaHere ; ignore <hops> call NICReadAgain_7 ; check <transaction_id> = 0xABABABAB REPT 4 call NICReadAgain_7 xor w, #$AB jnz :outtaHere ENDR ; ignore <seconds>, <flags>, <client_IP> mov globTemp1, #(2+2+4) :loop1 call NICReadAgain_7 decsz globTemp1 jmp :loop1 ; record <your_IP> _bank IP_BANK call NICReadAgain_7 mov myIP3, w call NICReadAgain_7 mov myIP2, w call NICReadAgain_7 mov myIP1, w call NICReadAgain_7 mov myIP0, w ; check if it is non-zero mov w, myIP3 or w, myIP2 or w, myIP1 or w, myIP0 jz :outtaHere ; skip <server_IP>, <router_IP>, <client_hw_addr>, ; <sever_host_name>, <boot_filename>, <option_magic_cookie> mov globTemp1, #(4+4+16+64+128+4) :loop2 call @NICPseudoRead decsz globTemp1 jmp :loop2 ; <option-message_type> call NICReadAgain_7 xor w, #53 ; DHCP Message Type jnz :outtaHere call NICReadAgain_7 xor w, #1 ; length jnz :outtaHere call NICReadAgain_7 xor w, #2 ; DHCPOFFER snz setb flags.GOT_DHCP_OFFER xor w, #2 ; get back value in w xor w, #5 ; DHCPACK jnz :loop4 setb flags.GOT_IP_ADDR ; indicate we got ; assigned an IP addr setb flags2.GOT_IP_LEASE ; now search for that Dang(!) <option-server_id> :loop4 call NICReadAgain_7 xor w, #54 ; Server Identifier jz :foundServId xor w, #54 ; restore value xor w, #58 ; check for T1 (renewal time) jnz :more01 ; go to routine to read and discard call NICReadAgain_7 xor w, #4 ; length jnz :outtaHere _bank DHCP_BANK ; record T1 call NICReadAgain_7 mov dhcpIPLeaseTm3, w call NICReadAgain_7 mov dhcpIPLeaseTm2, w call NICReadAgain_7 mov dhcpIPLeaseTm1, w call NICReadAgain_7 mov dhcpIPLeaseTm0, w jmp :loop4 :more01 call NICReadAgain_7 ; length mov globTemp1, w :loop3 call @NICPseudoRead ; read Data but ignore decsz globTemp1 ; read as many times as length jmp :loop3 jmp :loop4 :foundServId call NICReadAgain_7 ; ignore length _bank DHCP_BANK call NICReadAgain_7 mov dhcpServerId3, w call NICReadAgain_7 mov dhcpServerId2, w call NICReadAgain_7 mov dhcpServerId1, w call NICReadAgain_7 mov dhcpServerId0, w :outtaHere retp ENDIF IF HTTP ; ****************************************************************************** _E2Delay600ns ; Delay 600ns ; INPUT: none ; OUTPUT: none ; ****************************************************************************** mov w, #6 :loop decsz wreg jmp :loop retp ; ****************************************************************************** _E2Delay900ns ; Delay 900ns ; INPUT: none ; OUTPUT: none ; ****************************************************************************** mov w, #8 :loop decsz wreg jmp :loop retp ; ****************************************************************************** _E2Delay1300ns ; Delay 1300ns ; INPUT: none ; OUTPUT: none ; ****************************************************************************** mov w, #13 :loop decsz wreg jmp :loop retp ; ****************************************************************************** _E2SDAInput _E2SDAOutputHi ; Set SDA as input ; INPUT: none ; OUTPUT: none ; ****************************************************************************** mov !E2_PORT, #E2_DDR_SDA_IN retp ; ****************************************************************************** _E2SDAOutputLo ; Set SDA as output-low ; INPUT: none ; OUTPUT: none ; ****************************************************************************** clrb E2SDA_PIN mov !E2_PORT, #E2_DDR_SDA_OUT retp ; ****************************************************************************** _E2GenStartCond ; Generate START condition ; INPUT: none ; OUTPUT: none ; ****************************************************************************** call E2SDAOutputHi setb E2SCL_PIN call E2Delay600ns call E2SDAOutputLo call E2Delay600ns clrb E2SCL_PIN call E2Delay600ns retp ; ****************************************************************************** _E2GenStopCond ; Generate STOP condition ; INPUT: none ; OUTPUT: none ; ****************************************************************************** call E2SDAOutputLo setb E2SCL_PIN call E2Delay600ns call E2SDAOutputHi call E2Delay1300ns retp ; ****************************************************************************** _E2Write8 ; Write 8 bits out the I2C bus ; INPUT: w = Data to write ; OUTPUT: none ; ****************************************************************************** mov globTemp1, w ; Data buffer mov globTemp2, #8 ; bit counter :loop call E2Delay900ns sb globTemp1.7 call E2SDAOutputLo snb globTemp1.7 call E2SDAOutputHi call E2Delay900ns setb E2SCL_PIN call E2Delay600ns clrb E2SCL_PIN rl globTemp1 decsz globTemp2 jmp :loop retp ; ****************************************************************************** _E2Read8 ; Read 8 bits from the I2C bus ; INPUT: none ; OUTPUT: w = Data read ; ****************************************************************************** call E2SDAInput mov globTemp2, #8 ; bit counter :loop call E2Delay900ns sb E2SDA_PIN clc snb E2SDA_PIN stc rl globTemp1 setb E2SCL_PIN call E2Delay600ns clrb E2SCL_PIN call E2Delay900ns decsz globTemp2 jmp :loop mov w, globTemp1 retp ; ****************************************************************************** _E2Read8Ack ; Read 8 bits from the I2C bus and send ACK ; INPUT: none ; OUTPUT: w = Data read ; ****************************************************************************** call E2Read8 mov globTemp1, w call E2SendAck mov w, globTemp1 retp ; ****************************************************************************** _E2Read8NoAckStop ; Read 8 bits from the I2C bus and send a no-ACK and stop-condition ; (terminates sequential read mode on EEPROM) ; INPUT: none ; OUTPUT: w = Data read ; ****************************************************************************** call E2Read8 mov globTemp1, w call E2SendNotAck call E2GenStopCond mov w, globTemp1 retp ; ****************************************************************************** _E2RecvAck ; Receive ACK bit from I2C receiver ; INPUT: none ; OUTPUT: z: 1 = received ACK, 0 = Didn't receive ACK ; ****************************************************************************** call E2SDAInput call E2Delay900ns setb E2SCL_PIN sb E2SDA_PIN stz snb E2SDA_PIN clz call E2Delay600ns clrb E2SCL_PIN call E2Delay900ns retp ; ****************************************************************************** _E2SendAck ; Send ACK bit as acknowledge ; INPUT: none ; OUTPUT: z: 1 = received ACK, 0 = Didn't receive ACK ; ****************************************************************************** call E2SDAOutputLo call E2Delay900ns setb E2SCL_PIN call E2Delay600ns clrb E2SCL_PIN call E2Delay900ns retp ; ****************************************************************************** _E2SendNotAck ; Send ACK bit as not-acknowledge ; INPUT: none ; OUTPUT: z: 1 = received ACK, 0 = Didn't receive ACK ; ****************************************************************************** call E2SDAOutputHi call E2Delay900ns setb E2SCL_PIN call E2Delay600ns clrb E2SCL_PIN call E2Delay900ns retp ; ****************************************************************************** _E2SendRdCmd ; Tell I2C Device we wish to read from it for this transaction ; INPUT: none ; OUTPUT: none ; ****************************************************************************** call E2GenStartCond mov w, #E2_CMD_RD call E2Write8 call E2RecvAck retp ; ****************************************************************************** _E2SendWrCmd ; Tell I2C Device we wish to write to it for this transaction ; INPUT: none ; OUTPUT: none ; ****************************************************************************** call E2GenStartCond mov w, #E2_CMD_WR call E2Write8 call E2RecvAck retp ; ****************************************************************************** _E2SetAddr ; Set address pointer ; INPUT: {e2AddrMSB, e2AddrLSB} = address to set to ; OUTPUT: none ; ****************************************************************************** call E2SendWrCmd _bank EEPROM_BANK mov w, e2AddrMSB call E2Write8 call E2RecvAck mov w, e2AddrLSB call E2Write8 call E2RecvAck retp ; ****************************************************************************** _Bin8ToBCD ; Converts 8-bit binary number to unpacked BCD ; INPUT: w = binary number to convert ; fsr = pointer to MSD (lowest addr) of a 3-byte buffer ; OUTPUT: [fsr] = unpacked BCD ; ****************************************************************************** clr indf inc fsr clr indf inc fsr ; LSD mov indf, w :loopHun mov w, #100 mov w, indf-w jnc :loopTen mov indf, w dec fsr dec fsr ; MSD inc indf inc fsr inc fsr ; LSD jmp :loopHun :loopTen mov w, #10 mov w, indf-w sc jmp :exit mov indf, w dec fsr inc indf inc fsr jmp :loopTen :exit retp ; ****************************************************************************** _BCDToASCII ; Converts an unpacked BCD number to an ASCII character ; INPUT: w = unpacked BCD ; OUTPUT: w = ASCII character ; ****************************************************************************** mov globTemp1, w mov w, #'0' add w, globTemp1 retp ENDIF ; ****************************************************************************** _TCPApp2Init ; Called repeatedly as long as TCP connection2 state is closed ; [TCP API Function] ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; set up local port for tcp2 connection IF HTTP _bank TCB2_BANK mov tcb2LocalPortLSB, #HTTP_PORT_LSB mov tcb2LocalPortMSB, #HTTP_PORT_MSB bank HTTP_BANK clr httpParseState clr httpURIHash ; indicate tcp2 connection setb flags2.TCP_SOCK jmp @TCPAppPassiveOpen ENDIF retp ; ****************************************************************************** _DeleteSocket1 ; Deletes TCP socket1 ; INPUT: none ; OUTPUT: sock1RemoteIP3-0 ; ****************************************************************************** _bank TCPSOCKET_BANK clr sock1RemoteIP3 clr sock1RemoteIP2 clr sock1RemoteIP1 clr sock1RemoteIP0 retp ; ****************************************************************************** _DeleteSocket2 ; Deletes TCP socket1 ; INPUT: none ; OUTPUT: sock2RemoteIP3-0 ; ****************************************************************************** _bank TCPSOCKET_BANK clr sock2RemoteIP3 clr sock2RemoteIP2 clr sock2RemoteIP1 clr sock2RemoteIP0 retp ; *********** ; *** END *** ; *********** END+
file: /Techref/scenix/lib/io/osi3/tcpip/dyndns-agm.htm, NaNKB (1 imgs) in 0.383s is NaNKBps, updated: 2002/6/30 21:55, local time: 2025/1/10 23:07,
owner: JMN-EFP-786,
18.220.81.170:LOG IN
|
©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://sxlist.com/techref/scenix/lib/io/osi3/tcpip/dyndns-agm.htm"> Convert DYNDNS to HTTP request Dynamic DNS. </A> |
Did you find what you needed? |
Welcome to sxlist.com!sales, advertizing, & kind contributors just like you! Please don't rip/copy (here's why Copies of the site on CD are available at minimal cost. |
Welcome to sxlist.com! |
.