;THINGS TO DO ;TIM THE SILOS WILL GIVE YOU ALREADY IN BCD SO YOU WILL ACTUALLY NEED TO JUST MAKE SHURE YOU HAVE 3 SPOTS ;FREE FOR WHAT EVER INFO YOU WANT TO PAS TO IT. YOU WILL ALSO WANT TO LOOK AND SEE HOW INFO IS PASSED ;AND HOW YOU COULD ADD MORE CHARACTERS AND THEN ALSO YOU WILL WANT TO SEE HOW THE POST CONTROL WORKS ON ;TURNING ON AND OFF THINGS. WATCH SILO1,3,FSTR WATCH SILO2,3,FSTR WATCH SILO3,3,FSTR WATCH SILO4,3,FSTR WATCH SILO5,3,FSTR WATCH SILO6,3,FSTR WATCH SILO7,3,FSTR WATCH SILO8,3,FSTR WATCH SILO9,3,FSTR WATCH ASCII_INC,8,UDEC WATCH ASCII,1,FSTR WATCH M_ASCII,1,FSTR WATCH SILO,8,UDEC DEVICE OSCHS2, DRT60MS ;USED WITH OLDER VERSION ;DEVICE SX52, OSCXT4, DRT60MS ;USED WITH NEWER VERSION FREQ 50000000 ; have to Debug at freq != resonant freq RESET Main ID 'SILOS' ; if you need to change the demo board's (webserver) IP address (default 10.1.1.20): SX_IP_ADDR3 = 10 ; SX's static IP address SX_IP_ADDR2 = 41 ; " SX_IP_ADDR1 = 128 ; " SX_IP_ADDR0 = 20 ; " ; if you need to change the demo board's MAC address (default 00-00-00-00-00-01): SX_ETH_ADDR0 = 1 ; SX's Ethernet Phy MAC Address SX_ETH_ADDR1 = 0 ; " SX_ETH_ADDR2 = 1 ; " SX_ETH_ADDR3 = 0 ; " SX_ETH_ADDR4 = 1 ; " SX_ETH_ADDR5 = 1 ; " ;********************************************************************************* ; SX48BD/52BD Mode addresses ; *On SX48BD/52BD, most registers addressed via mode are read and write, with the ; exception of CMP and WKPND which do an exchange with W. ;********************************************************************************* ; Timer (read) addresses TCPL_R = $00 ; Read Timer Capture register low byte TCPH_R = $01 ; Read Timer Capture register high byte TR2CML_R = $02 ; Read Timer R2 low byte TR2CMH_R = $03 ; Read Timer R2 high byte TR1CML_R = $04 ; Read Timer R1 low byte TR1CMH_R = $05 ; Read Timer R1 high byte TCNTB_R = $06 ; Read Timer control register B TCNTA_R = $07 ; Read Timer control register A ; Exchange addresses CMP = $08 ; Exchange Comparator enable/status register with W WAS CMP WKPND = $09 ; Exchange MIWU/RB Interrupts pending with W ; Port setup (read) addresses WKED_R = $0A ; Read MIWU/RB Interrupt edge setup, 0 = falling, 1 = rising WKEN_R = $0B ; Read MIWU/RB Interrupt edge setup, 0 = enabled, 1 = disabled ST_R = $0C ; Read Port Schmitt Trigger setup, 0 = enabled, 1 = disabled LVL_R = $0D ; Read Port Level setup, 0 = CMOS, 1 = TTL PLP_R = $0E ; Read Port Pull-up setup, 0 = enabled, 1 = disabled DIR_R = $0F ; Read Port Direction ; Timer (write) addresses TR2CML_W = $12 ; Write Timer R2 low byte TR2CMH_W = $13 ; Write Timer R2 high byte TR1CML_W = $14 ; Write Timer R1 low byte TR1CMH_W = $15 ; Write Timer R1 high byte TCNTB_W = $16 ; Write Timer control register B TCNTA_W = $17 ; Write Timer control register A ; Port setup (write) addresses WKED_W = $1A ; Write MIWU/RB Interrupt edge setup, 0 = falling, 1 = rising WKEN_W = $1B ; Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 = disabled ST_W = $1C ; Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled LVL_W = $1D ; Write Port Level setup, 0 = CMOS, 1 = TTL PLP_W = $1E ; Write Port Pull-up setup, 0 = enabled, 1 = disabled DIR_W = $1F ; Write Port Direction ;********************************************************************************* ; Setup and enable RTCC interrupt, WREG register, RTCC/WDT prescaler ;********************************************************************************* RTCC_ON = %10000000 ; Enables RTCC at address $01 (RTW hi) ; WREG at address $01 (RTW lo) by default RTCC_ID = %01000000 ; Disables RTCC edge interrupt (RTE_IE hi) ; RTCC edge interrupt (RTE_IE lo) enabled by default RTCC_INC_EXT = %00100000 ; Sets RTCC increment on RTCC pin transition (RTS hi) ; RTCC increment on internal instruction (RTS lo) is defalut RTCC_FE = %00010000 ; Sets RTCC to increment on falling edge (RTE_ES hi) ; RTCC to increment on rising edge (RTE_ES lo) is default RTCC_PS_OFF = %00001000 ; Assigns prescaler to Watchdog (PSA hi) PS_000 = %00000000 ; RTCC = 1:2, WDT = 1:1 PS_001 = %00000001 ; RTCC = 1:4, WDT = 1:2 PS_010 = %00000010 ; RTCC = 1:8, WDT = 1:4 PS_011 = %00000011 ; RTCC = 1:16, WDT = 1:8 PS_100 = %00000100 ; RTCC = 1:32, WDT = 1:16 PS_101 = %00000101 ; RTCC = 1:64, WDT = 1:32 PS_110 = %00000110 ; RTCC = 1:128, WDT = 1:64 PS_111 = %00000111 ; RTCC = 1:256, WDT = 1:128 ; *************************** ; *** CONDITIONAL DEFINES *** ; *************************** HTTP = 1 ; ***************** ; *** VARIABLES *** ; ***************** ; *** Global *** GLOBAL_ORG = $0A flags EQU GLOBAL_ORG+0 ; various flags used by TCP/IP stack flags2 EQU GLOBAL_ORG+1 ; various flags used by TCP/IP stack flags3 EQU GLOBAL_ORG+2 ; various flags used by TCP/IP stack globTemp1 EQU GLOBAL_ORG+3 ; not preserved across any function globTemp2 EQU GLOBAL_ORG+4 ; not preserved across anyfunction globTemp3 EQU GLOBAL_ORG+5 ; preserved across some functions ; ***************** ; *** BANK DEFINES ; ***************** ; *** Bank 0 *** ; (Don't use this bank - Difficulties with addressing Data) ORG $00 ; *** Bank 1 *** ORG $10 NIC_BANK = $ nicIOAddr DS 1 ; points to currently addressed register on NIC nicNextPktPtr DS 1 ; points to next packet in NIC's rx queue nicCurrPktPtr DS 1 ; points to current packet in NIC's rx queue nicRemoteEth0 DS 1 ; ethernet addr used for outgoing packet, overwritten by incoming packet nicRemoteEth1 DS 1 ; " nicRemoteEth2 DS 1 ; " nicRemoteEth3 DS 1 ; " nicRemoteEth4 DS 1 ; " nicRemoteEth5 DS 1 ; " nicCopySrcMSB DS 1 ; used by NICBufferCopy() nicCopySrcLSB DS 1 ; " nicCopyDestMSB DS 1 ; " nicCopyDestLSB DS 1 ; " nicCopyLenMSB DS 1 ; " nicCopyLenLSB DS 1 ; " nicCopyTemp DS 1 ; " ; *** Bank 2 *** ORG $20 IP_BANK = $ ; make sure IP_BANK[7] = NIC_BANK[7] remoteIP3 DS 1 ; IP addr used for outgoing packet, overwritten by incoming packet remoteIP2 DS 1 ; " remoteIP1 DS 1 ; " remoteIP0 DS 1 ; " myIP3 DS 1 ; filter value for incoming IP packets, also used in outgoing packet myIP2 DS 1 ; " myIP1 DS 1 ; " myIP0 DS 1 ; " ipCheckSumMSB DS 1 ; IP <header_checksum> ipCheckSumLSB DS 1 ; " ipLengthMSB DS 1 ; IP <length> ipLengthLSB DS 1 ; " ipProtocol DS 1 ; IP <protocol> ipIdentMSB DS 1 ; IP <identifier>, incremented each outgoing packet ipIdentLSB DS 1 ; " counter1 DS 1 ; general purpose counter variable ; *** Bank 3 *** ORG $30 TCB1_BANK = $ ; make sure TCB1_BANK[7] = NIC_BANK[7] ; TCB1 is bound to tcp connection1 indicated by flags2.TCP_SOCK cleared ; The ordering of these variables is significant. It is the same as the TCP ; header. This simpifies the send-packet code tcb1LocalPortMSB DS 1 ; source port - tcp conn1 tcb1LocalPortLSB DS 1 ; " tcb1RemotePortMSB DS 1 ; destination port - tcp conn1 tcb1RemotePortLSB DS 1 ; " tcb1SndUna4 DS 1 ; SND.UNA: oldest unacknowledged byte - tcp conn1 tcb1SndUna3 DS 1 ; " tcb1SndUna2 DS 1 ; " tcb1SndUna1 DS 1 ; " tcb1RcvNxt4 DS 1 ; RCV.NXT: next byte to receive - tcp conn1 tcb1RcvNxt3 DS 1 ; " tcb1RcvNxt2 DS 1 ; " tcb1RcvNxt1 DS 1 ; " tcb1Offset DS 1 ; length of the TCP options tcb1Flags DS 1 ; flags field tcb1SendWinMSB DS 1 ; send window tcb1SendWinLSB DS 1 ; " TCB1_END = $ ; *** Bank 4 *** ORG $40 TCB2_BANK = $ ; make sure TCB2_BANK[7] = NIC_BANK[7] ; TCB2 is bound to tcp connection2 indicated by flags2.TCP_SOCK set ; The ordering of these variables is significant. It is the same as the TCP ; header. This simpifies the send-packet code tcb2LocalPortMSB DS 1 ; source port - tcp conn2 tcb2LocalPortLSB DS 1 ; " tcb2RemotePortMSB DS 1 ; destination port - tcp conn2 tcb2RemotePortLSB DS 1 ; " tcb2SndUna4 DS 1 ; SND.UNA: oldest unacknowledged byte - tcp conn2 tcb2SndUna3 DS 1 ; " tcb2SndUna2 DS 1 ; " tcb2SndUna1 DS 1 ; " tcb2RcvNxt4 DS 1 ; RCV.NXT: next byte to receive - tcp conn2 tcb2RcvNxt3 DS 1 ; " tcb2RcvNxt2 DS 1 ; " tcb2RcvNxt1 DS 1 ; " tcb2Offset DS 1 ; length of the TCP options tcb2Flags DS 1 ; flags field tcb2SendWinMSB DS 1 ; send window tcb2SendWinLSB DS 1 ; " TCB2_END = $ ; *** Bank 5 *** ORG $50 TCP_BANK = $ ; make sure TCP_BANK[7] = NIC_BANK[7] tcp1State DS 1 ; tcp connection1 state-machine state tcp2State DS 1 ; tcp connection2 state-machine state tcpTmpSeq4 DS 1 ; TMP.SEQ. 1=LSB, 4=MSB tcpTmpSeq3 DS 1 ; temporary information from the received packet tcpTmpSeq2 DS 1 tcpTmpSeq1 DS 1 tcp1UnAckMSB DS 1 ; number of unacknowledged bytes for tcp connection1 tcp1UnAckLSB DS 1 ; " tcp2UnAckMSB DS 1 ; number of unacknowledged bytes for tcp connection2 tcp2UnAckLSB DS 1 ; " tcpRxFlags DS 1 ; copy of the received flags field tcpCheckSumMSB DS 1 tcpCheckSumLSB DS 1 tcpLengthMSB DS 1 tcpLengthLSB DS 1 tcpTmpMSB = tcpTmpSeq4 tcpTmpLSB = tcpTmpSeq3 tcpAppTxBytesMSB = tcp1UnAckMSB ; number of bytes app wants to transmit tcpAppTxBytesLSB = tcp1UnAckLSB ; " tcpAppTxBytesMSB = tcp2UnAckMSB ; number of bytes app wants to transmit tcpAppTxBytesLSB = tcp2UnAckLSB ; " tcpAppRxBytesMSB = tcpLengthMSB ; number of bytes app will be receiving tcpAppRxBytesLSB = tcpLengthLSB ; " ; *** Bank 6 *** ORG $60 ARP_BANK = $ ; make sure ARP_BANK[7] = NIC_BANK[7] host1IP3 DS 1 ; remote host1 IP address host1IP2 DS 1 ; " host1IP1 DS 1 ; " host1IP0 DS 1 ; " host1Eth0 DS 1 ; remote host1 Ethernet address host1Eth1 DS 1 ; " host1Eth2 DS 1 ; " host1Eth3 DS 1 ; " host1Eth4 DS 1 ; " host1Eth5 DS 1 ; " stPktTxBufStart DS 1 ; start address of stalled packet in NIC tx buffer TCPPORT_BANK = $ ; Incoming tcp packet ports tcpRemotePortMSB DS 1 tcpRemotePortLSB DS 1 tcpLocalPortMSB DS 1 tcpLocalPortLSB DS 1 ; *** Bank 7 *** ORG $70 TIMER_BANK = $ ; make sure TIMER_BANK[7] = NIC_BANK[7] baseTimer DS 1 ; lowest/common cog in timer chain arpTimerMSB DS 1 ; ARP-timer count arpTimerLSB DS 1 ; " tcp1TimerMSB DS 1 ; tcp1 re-transmission timer count tcp1TimerLSB DS 1 ; " tcp2TimerMSB DS 1 ; tcp2 re-transmission timer count tcp2TimerLSB DS 1 ; " conn1TimerMSB DS 1 ; tcp1 timeout timer count conn1TimerLSB DS 1 ; " conn2TimerMSB DS 1 ; tcp2 timeout timer count conn2TimerLSB DS 1 ; " IF HTTP HTTP_BANK = $ ; make sure HTTP_BANK[7] = NIC_BANK[7] httpParseState DS 1 ; state of the HTTP header parser httpURIHash DS 1 ; hash of the current URI httpParseState2 DS 1 ; state of the HTTP message parser ENDIF ; *** Bank 8 *** ORG $80 MISC_BANK = $ ; Watch out for this when moving Databanks! This is the only place where more ; than 1 byte is reserved for Data and it's not so obvious! BCD3 DS 3 ; buffer for binary-to-ascii conversion ADC_BANK = $ ; must be same bank as bcd3 EEPROM_BANK = $ ; make sure EEPROM_BANK[7] = NIC_BANK[7] e2AddrMSB DS 1 ; address in EEPROM to start reading from e2AddrLSB DS 1 ; " e2FileLenMSB DS 1 ; length of the file being read e2FileLenLSB DS 1 ; " ;THIS WAS ADDED BY TIM HOSEY SERIAL = $ ;THIS IS WHERE YOU ARE GETTING ASCII INPUT AT 2400 BPS FROM THE SILO. RX_COUNT DS 1 RX_DIVIDE DS 1 RX_BYTE DS 1 RX_BIT DS 1 RX_FLAG ; *** Bank 9 *** ORG $90 ; *** Bank A *** ORG $A0 UDP_BANK = $ udpRxSrcPortMSB DS 1 udpRxSrcPortLSB DS 1 udpRxDestPortMSB DS 1 ; filter value for incoming UDP packets udpRxDestPortLSB DS 1 ; " udpRxDataLenMSB DS 1 ; length of <data> field of incoming UDP packet udpRxDataLenLSB DS 1 ; " udpTxSrcPortMSB DS 1 udpTxSrcPortLSB DS 1 udpTxDestPortMSB DS 1 udpTxDestPortLSB DS 1 udpTxDataLenMSB DS 1 ; length of <data> field of outgoing UDP packet udpTxDataLenLSB DS 1 ; " TCPTMP_BANK = $ ; stores temporary tcp info tcpTmpAck4 DS 1 ; TMP.ACK tcpTmpAck3 DS 1 ; temporary information from the received packet tcpTmpAck2 DS 1 tcpTmpAck1 DS 1 ; *** Bank B *** ORG $B0 TCPSOCKET_BANK = $ ; contains the 2 TCP sockets ; socket1 - will always be bound to TCB1_BANK sock1RemoteIP3 DS 1 sock1RemoteIP2 DS 1 sock1RemoteIP1 DS 1 sock1RemoteIP0 DS 1 sock1RemotePortMSB DS 1 sock1RemotePortLSB DS 1 ; socket2 - will always be bound to TCB2_BANK sock2RemoteIP3 DS 1 sock2RemoteIP2 DS 1 sock2RemoteIP1 DS 1 sock2RemoteIP0 DS 1 sock2RemotePortMSB DS 1 sock2RemotePortLSB DS 1 ; *** Bank C *** ORG $C0 ;INFO FOR SILOS 1 - 8 SILO_BANK = $ SILO1 DS 3 SILO2 DS 3 SILO3 DS 3 SILO4 DS 3 SILOINC DS 1 ;THIS IS THE INCREMENTAL COUNT TO DETERMINE WHICH SILO TO LOOK AT. ASCII DS 1 ;THIS IS THE HOLD FOR W ASCII_INC DS 1 ;THIS IS WHAT NUMBER YOU ARE LOOKING AT IN THE STRING SILO DS 1 ;THIS IS THE SILO NUMBER YOU ARE RECEIVING DATA FOR. ;THAT IS IT FOR THIS BANK ; *** Bank D *** ORG $D0 SILO_BANK1 = $ ; INFO ON SILO 1 SILO5 DS 3 SILO6 DS 3 SILO7 DS 3 SILO8 DS 3 SILO9 DS 3 M_ASCII DS 1 ; *** Bank E *** ORG $E0 INFO_BANK = $ INFO DS 2 ;USE THIS TO STORE THE ASCII COMING IN INFO_CNT DS 1 ;USE THIS TO LET ME KNOW WHICH INFO TO PUT IT INTO. ; *** Bank F *** ORG $F0 ; *************** ; *** EQUATES *** ; *************** INT_PERIOD = 254 ;254 ; RTCC interrupt periodicity (345kHz) ; change this if you're not clocking the SX at 50MHz ; *** Pin Definitions *** RA_DIR = %10101010 ;GOOD RA.3 IS BEING SET AS AN INPUT RA_OUT = %01110101 ;THIS WAS LIKE THIS RA_OUT = %01110101 RA_LVL = %11111111 RA_PLP = %01110111 RB_DIR = %10000000 RB_OUT = %01100000 RB_LVL = %11111111 RB_PLP = %01111111 RC_DIR = %11111111 RC_OUT = %00000000 RC_LVL = %11111111 RC_PLP = %11111111 RD_DIR = %11111111 RD_OUT = %00000000 RD_LVL = %11111111 RD_PLP = %00000000 RE_DIR = %01111111 RE_OUT = %00000000 RE_LVL = %00111111 RE_PLP = %11000000 NIC_DATA_PORT = rc NIC_CTRL_PORT = rb IOWB_PIN = NIC_CTRL_PORT.5 IORB_PIN = NIC_CTRL_PORT.6 IOCH_PIN = NIC_CTRL_PORT.7 E2_PORT = ra E2SCL = 4 E2SDA = 5 E2SCL_PIN = E2_PORT.E2SCL E2SDA_PIN = E2_PORT.E2SDA LED_PORT = ra LED = 6 LED_PIN = LED_PORT.LED SW_PORT = ra SW = 7 SW_PIN = SW_PORT.SW ;RS-232 PORT SETTINGS AND BAUD RATE DIVIDERS. ;TIM A LITTLE REMINDER, GROUND THE DARN THING AND IT WILL WORK. OKAY!!!!!!!! LOL RX_PIN = RD.0 ;CHANGED THIS FROM RA.3 82 FRO 254 RTCC FOR 2400 BPS BAUD = 82 BAUD15 = 123 ;This should be .03% deviant. ; *** flags *** RX_IS_ARP = 0 ; incoming packet is an ARP packet RX_IS_ICMP = 1 ; incoming packet is an ICMP packet RX_IS_UDP = 2 ; incoming packet is a UDP packet RX_IS_TCP = 3 ; incoming packet is a TCP packet RX_IS_IP_BCST = 4 ; incoming packet is an IP Broadcast packet GOT_IP_ADDR = 6 ; received an IP address assignment (recv'ed DHCP ACK) IP_CHKSUM_LSB = 7 ; next byte to accumulate IP checksum is LSB TCP_CHKSUM_LSB = 5 ; next byte to accumulate TCP checksum is LSB ; *** flags2 *** GOT_RX_FRAME = 0 ; used by NICWaitRxFrame to indicate we got one. RENEW_IP_LEASE = 2 ; indicates an IP lease renewal is in progress TCP_SOCK = 3 ; tcp connection/socket indicator. 0=tcp1, 1=tcp2 TCP_TXSEMA = 4 ; tcp transmit semaphore. SW_PRESSED = 6 ; indicates the switch SW2 is held in (pressed) when 1 BROWSER_TYPE = 7 ; 1=netscape type, 0=IE type ; *** flags3 *** ARP_REQ_SENT = 0 ; indicates that an ARP request has been sent ARP_RSP_RCVD = 1 ; indicates that an ARP response has been received ARP_STL_TX = 2 ; indicates that the stalled packet is to be transmitted HTTP_METHOD = 4 ; 0=get, 1=post/put (requested method by remote browser) GOT_HTTP_METHOD = 5 ; indicates the HTTP_METHOD bit is valid GOT_URI = 6 ; indicates the file URI is complete LED_LOCK = 7 ; locks access to the LED when set to 1. ; *** NIC Constants *** RXBUF_START = $40 ; 3328 byte receive buffer (2 max-size packets) RXBUF_END = $4D ; " TXBUF1_START = $4D ; 1536 byte transmit buffer for ICMP/UDP TXBUF2_START = $53 ; 1536 byte transmit buffer for tcp connection1 TXBUF3_START = $59 ; 1536 byte transmit buffer for tcp connection2 TXBUF4_START = $5F ; 256 byte transmit buffer for ARP ; *** Ethernet Constants *** ; also see in "DEMO DEFINES" section ; *** ARP Constants *** ARP_TIMEOUT = 5 ; waiting for an ARP response timeout period ; *** IP Constants *** ; also see in "DEMO DEFINES" section IP_TTL = 32 ; *** UDP Constants *** UDP_RX_DEST_MSB = $04 ; user UDP RX Port: 1025 UDP_RX_DEST_LSB = $01 ; " ; *** TCP Constants *** ; TCP state-machine states (numbering order is signifcant) TCP_ST_CLOSED = 0 TCP_ST_LISTEN = 1 TCP_ST_SYNSENT = 2 TCP_ST_SYNRCVED = 3 TCP_ST_ESTABED = 4 TCP_ST_FINWAIT1 = 5 TCP_ST_FINWAIT2 = 6 TCP_ST_CLOSEWAIT= 7 TCP_ST_CLOSING = 8 TCP_ST_LASTACK = 9 TCP_ST_TIMEWAIT = 10 ; Bit positions in the TCP <flag> byte. TCP_FLAG_ACK = 4 TCP_FLAG_PSH = 3 TCP_FLAG_RST = 2 TCP_FLAG_SYN = 1 TCP_FLAG_FIN = 0 ; TCP Options TCP_OPTION_END = 0 TCP_OPTION_NOP = 1 TCP_OPTION_MSS = 2 ; max segment size TCP_HDR_LENGTH = 5 ; normal TCP header length. TCP_OFFSET_MASK = $F0 TCP_WINDOW_SIZE = 1400 ; max # of Data bytes we will accept TCP_SEG_SIZE = 1400 ; max # of Data bytes TCP will transmit per segment TCP_RESTART_EXP = 8 ; TCP re-transmission timeout period (0.19s per tick) TCP_CONN_EXP = 160 ; TCP connection timeout period (0.19s per tick) ; *** HTTP Constants *** ; States for parsing HTTP headers HTTP_PORT_MSB = 0 ; local tcp port number for HTTP server. HTTP_PORT_LSB = 80 ; " HTTP_SEG_SIZE = 1400 ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ ;################################################################################################################ URI1 = $FF ; NOTHING RIGHT NOW URI2 = $2A ; hash of "INDEX.HTML" URI3 = $21 ; hash of "postctrl.htm" ; *** EEPROM Constants *** E2_CMD_RD = $A1 ; most-significant 7-bits is the I2C slave addr E2_CMD_WR = $A0 ; most-significant 7-bits is the I2C slave addr E2_SDA_MASK = (1 << E2SDA) ; a '1' in the SDA bit, '0' everywhere else E2_DDR_SDA_IN = (RA_DIR | E2_SDA_MASK) ; direction of SDA port when SDA is input E2_DDR_SDA_OUT = (RA_DIR & (~E2_SDA_MASK)) ; direction of SDA port when SDA is output ; ************** ; *** MACROS *** ; ************** _bank MACRO 1 ; sets FSR[7:4] bank \1 IF \1 & %10000000 ; SX48BD and SX52BD (production release) ; BANK instruction setb fsr.7 ; modifies FSR bits 4,5 and 6. FSR.7 needs ; to be set by sw. ELSE clrb fsr.7 ENDIF ENDM _banky MACRO 1 ; set FSR[7] ~only~ IF \1 & %10000000 ; SX48BD and SX52BD (production release) ; bank instruction setb fsr.7 ; modifies FSR bits 4,5 and 6. FSR.7 needs to ; be set by sw. ELSE clrb fsr.7 ENDIF ENDM _mode MACRO 1 mov w, #\1 ; loads the M register correctly for the SX48BD ; and SX52BD mov m, w ENDM _pc_check MACRO 0 IF ($ & $100) ERROR 'ERROR!! ADD PC,W instruction at invalid addr' ENDIF ENDM ; *********** ; *** ISR *** ; *********** ORG 0 ; Page0 ISR ;THIS IS THE BEGINING OF THE INTERRUPTS ROUTINES. ; ******************** ; *** RS-232 @ 2400 BPS ; ******************** ;TIM A LITTLE REMINDER, GROUND THE DARN THING AND IT WILL WORK. OKAY!!!!!!!! LOL _BANK SERIAL MOVB C,/RX_PIN ;SERIAL RECEIVE WAS MOVB C,/RX_PIN TEST RX_COUNT JNZ :RXBIT ;IF NOT, :BIT MOV W,#9 ;IN CASE START READY 9 SC ;IF START, SET RX_COUNT MOV RX_COUNT,W MOV RX_DIVIDE,#BAUD15 ;READY 1.5 BIT PERIODS :RXBIT DJNZ RX_DIVIDE,RXDONE ;8TH TIME THROUGH ? MOV RX_DIVIDE,#BAUD DEC RX_COUNT ;LAST BIT ? SZ ;IF NOT, SAVE BIT RR RX_BYTE ;ROTATE THE INFO RIGHT SNZ ;IF SO, SET FLAG SETB RX_FLAG.0 RXDONE Timer ; implement various SW timers ; lowest-common-denominator timer _bank TIMER_BANK incsz baseTimer ; inc at 2.9us per tick with 50MHz clk jmp :timerEnd :tcp1Timer ; TCP1-timer (used for TCP1 re-transmission timeouts) incsz tcp1TimerLSB ; inc at 742.4us per tick with 50MHz clk jmp :tcp2Timer inc tcp1TimerMSB ; inc at 190.0544ms per tick with 50MHz clk :tcp2Timer ; TCP2-timer (used for TCP2 re-transmission timeouts) incsz tcp2TimerLSB ; inc at 742.4us per tick with 50MHz clk jmp :conn1Timer inc tcp2TimerMSB ; inc at 190.0544ms per tick with 50MHz clk :conn1Timer ; Connection-timer (used for TCP1 connection timeouts) incsz conn1TimerLSB jmp :conn2Timer inc conn1TimerMSB :conn2Timer ; Connection-timer (used for TCP2 connection timeouts) incsz conn2TimerLSB jmp :arpTimer inc conn2TimerMSB :arpTimer ; ARP-timer (used for ARP response timeouts) incsz arpTimerLSB jmp :dhcpTimer inc arpTimerMSB :dhcpTimer ;TOOK THE DHCP CRAP OUT OF HERE TO FREE UP MORE ROOM. :timerEnd ;AFTER THE ABOVE IS DONE THEN HERE IS THE FUN PART OF PUTTING DATA WHERE IT BELONGS CORRESPONDING TO THE SILO #. GET_BYTE ;ATTEMPT TO GET A BYTE OF INFO _BANK SERIAL JNB RX_FLAG.0,RXDONE1 MOV W,RX_BYTE _BANK SILO_BANK MOV ASCII,W SETB FSR.4 ;NEXT SILO BANK MOV M_ASCII,W ;SET THE HIGHTER ASCII IN ALSO. _BANK SILO_BANK INC ASCII_INC ;YOU ARE LOOKING FOR ONLY 9-11 & 2,3 FOR SILO # CJE ASCII_INC,#5,@GET_SILO_NUMBER CJE ASCII_INC,#11,@TEST1 ;11 CJE ASCII_INC,#12,@TEST2 ;12 CJE ASCII_INC,#13,@TEST3 JMP RXDONE1 ;DUH, DUH, DUH LOL RXDONE1 _BANK SILO_BANK CSNE ASCII,#10 ;IF NOT LINE FEED SKIP OR #10 CLR ASCII_INC CLR ASCII _BANK SERIAL CLRB RX_FLAG.0 ISRExit MOV W, #-INT_PERIOD retiw ;THIS IS THE END OF THE INTERUPT PERIOD. ; ******************** ; *** MAIN PROGRAM *** ; ******************** Init jmp _Init ARPInit jmp _ARPInit TCPIPInit jmp _TCPIPInit StartupDelay jmp _StartupDelay CopyRemoteIPSocket1 jmp _CopyRemoteIPSocket1 CopyRemoteIPSocket2 jmp _CopyRemoteIPSocket2 CheckRemotePortTCB1 jmp _CheckRemotePortTCB1 CheckRemotePortTCB2 jmp _CheckRemotePortTCB2 IF HTTP E2Init jmp _E2Init ENDIF Main _BANK SILO_BANK CLR SILO CLR SILOINC MAIN_NEXT call @Init call @UDPAppInit ; initialise UDP application _bank MISC_BANK ; main program loop :mainLoop call @NICCheckRxFrame ; check if we received a frame jz :noRxFrame ; no call @NICWaitRxFrame ; no waiting cus we've already ; checked call @ARPCheckIfIs ; check and process if ARP jb flags.RX_IS_ARP, :mainLoop call @CheckIPDatagram ; not ARP, check if IP jb flags.RX_IS_ICMP, :icmp jb flags.RX_IS_UDP, :udp jb flags.RX_IS_TCP, :tcp jmp :mainLoop :icmp call @ICMPProcPktIn ; process incoming ICMP packet jmp :mainLoop :udp call @UDPProcPktIn ; process incoming UDP packet jmp :mainLoop :tcp call @TCPProcPktIn ; process incoming TCP packet jmp :mainLoop :noRxFrame call @ARPSendStPacket ; send ARP stalled packets if any bank TCP_BANK cje tcp2State, #TCP_ST_CLOSED, :tcp2Closed ; check if tcp2 ; in listen cje tcp2State, #TCP_ST_LISTEN, :tcp2Listen ; check if tcp2 ; closed ; tcp2 is in another state, check if hanging connection bank TIMER_BANK cjae conn2TimerMSB, #TCP_CONN_EXP, :resetTCP2 jmp :tcpTx ; connection timer not timed out :tcp2Closed call @TCPApp2Init ; initialise tcp2 application _bank TIMER_BANK clr conn2TimerMSB ; clear the connection timer jmp :tcp1Check :tcp2Listen bank TIMER_BANK clr conn2TimerMSB ; tcp2 in listen, clr conn timer jmp :tcp1Check :tcp1Check _bank TCP_BANK cje tcp1State, #TCP_ST_CLOSED, :tcp1Closed ; check if tcp1 ; in listen cje tcp1State, #TCP_ST_LISTEN, :tcp1Listen ; check if tcp1 ; closed ; tcp1 is in another state, check if hanging connection bank TIMER_BANK cjae conn1TimerMSB, #TCP_CONN_EXP, :resetTCP1 jmp :tcpTx ; connection timer not timed out :tcp1Closed call @TCPApp1Init ; initialise tcp1 application _bank TIMER_BANK clr conn1TimerMSB ; clear the connection timer jmp :mainLoop :tcp1Listen bank TIMER_BANK clr conn1TimerMSB ; tcp2 in listen, clr conn timer jmp :mainLoop :resetTCP2 ; reset hung TCP2 connection bank TCP_BANK clr tcp2UnAckMSB ; clear bytes to still send on tcp2 clr tcp2UnAckLSB mov tcp2State, #TCP_ST_CLOSED IF HTTP bank HTTP_BANK ; reset HTTP webserver state clr httpParseState ENDIF jmp :mainLoop :resetTCP1 ; reset hung TCP1 connection bank TCP_BANK clr tcp1UnAckMSB ; clear bytes to still send on tcp1 clr tcp1UnAckLSB mov tcp1State, #TCP_ST_CLOSED jmp :mainLoop ; repeat cycle by returning to entry ; do not allow new tx if waiting for ARP response :tcpTx jb flags3.ARP_REQ_SENT, :mainLoop mov w, #(1<<TCP_TXSEMA) xor flags2, w ; toggle TCP_TXSEMA to give other tcp ; connection a time-slice to transmit call @TCPTransmit ; check if app has anything to transmit jmp :mainLoop ; repeat cycle by returning to entry ; ******************* ; *** SUBROUTINES *** ; ******************* ORG $D0 ; Page0 ; ****************************************************************************** _Init ; Main program initialization code ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _mode LVL_W mov !ra, #RA_LVL mov !rb, #RB_LVL mov !rc, #RC_LVL ;mov !rd, #RD_LVL mov !re, #RE_LVL _mode PLP_W mov !ra, #RA_PLP mov !rb, #RB_PLP mov !rc, #RC_PLP ;mov !rd, #RD_PLP mov !re, #RE_PLP _mode DIR_W mov !ra, #RA_DIR mov !rb, #RB_DIR mov !rc, #RC_DIR ;mov !rd, #RD_DIR mov !re, #RE_DIR mov ra, #RA_OUT mov rb, #RB_OUT mov rc, #RC_OUT ;mov rd, #RD_OUT mov re, #RE_OUT MOV !RD,#$FF ;YOU CHANGED THIS TO ALL INPUTS clr flags clr flags2 clr flags3 call @NICInit call @ARPInit call @TCPIPInit IF HTTP call @E2Init ENDIF OPT mov w, #(RTCC_PS_OFF) ; setup option register mov !option, w retp ; ****************************************************************************** _ARPInit ; ARP initialization code ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank ARP_BANK clr host1IP0 ; clear the cache clr host1IP1 ; " clr host1IP2 ; " clr host1IP3 ; " retp ; ****************************************************************************** _TCPIPInit ; TCP/IP stack initialization code ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank IP_BANK ; initialize SX's IP addr setb flags.GOT_IP_ADDR mov myIP3, #SX_IP_ADDR3 mov myIP2, #SX_IP_ADDR2 mov myIP1, #SX_IP_ADDR1 mov myIP0, #SX_IP_ADDR0 ; initialize IP Identifier sequence number clr ipIdentMSB clr ipIdentLSB ; initialise the TCP variables bank TCP_BANK clr tcp1UnAckMSB clr tcp1UnAckLSB clr tcp2UnAckMSB clr tcp2UnAckLSB mov tcp1State, #TCP_ST_CLOSED mov tcp2State, #TCP_ST_CLOSED ; clear the tcp socket local ports (used for listening on). bank TCB1_BANK clr tcb1LocalPortLSB clr tcb1LocalPortMSB bank TCB2_BANK clr tcb2LocalPortLSB clr tcb2LocalPortMSB ; clear the tcp sockets remote IP addresses _bank TCPSOCKET_BANK clr sock1RemoteIP3 clr sock2RemoteIP3 retp IF HTTP ; ****************************************************************************** _E2Init ; EEPROM initialization code ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; get the I2C Device into a known state call @E2SDAInput :e2InitLoop clrb E2SCL_PIN call @E2Delay1300ns setb E2SCL_PIN call @E2Delay900ns jnb E2SDA_PIN, :e2InitLoop retp ENDIF ; ****************************************************************************** _StartupDelay ; Delay for ?ms @ 50MHz ; INPUT: none ; OUTPUT: none ; ****************************************************************************** mov globTemp2, #10 :loop3 clr globTemp1 :loop2 clr w :loop1 decsz wreg jmp :loop1 decsz globTemp1 jmp :loop2 decsz globTemp2 jmp :loop3 retp ; ****************************************************************************** _CopyRemoteIPSocket1 ; Copies remoteIP3-0 into sock1RemoteIP3 ; INPUT: remoteIP3-0 ; OUTPUT: sock1RemoteIP3 ; ****************************************************************************** mov globTemp1, #sock1RemoteIP3 mov globTemp3, #remoteIP3 call @Copy4Inc retp ; ****************************************************************************** _CopyRemoteIPSocket2 ; Copies remoteIP3-0 into sock2RemoteIP3 ; INPUT: remoteIP3-0 ; OUTPUT: sock2RemoteIP3 ; ****************************************************************************** mov globTemp1, #sock2RemoteIP3 mov globTemp3, #remoteIP3 call @Copy4Inc retp ; ****************************************************************************** _CheckRemotePortTCB1 ; Checks if the remote port in the TCP packet is in TCB1_BANK ; INPUT: tcpRemotePortLSB, tcpRemotePortMSB, tcb1RemotePortLSB, ; tcb1RemotePortMSB ; OUTPUT: Z set if in there ; ****************************************************************************** _bank TCPPORT_BANK mov w, tcpRemotePortMSB bank TCB1_BANK xor w, tcb1RemotePortMSB sz retp mov w, tcb1RemotePortLSB bank TCPPORT_BANK xor w, tcpRemotePortLSB retp ; ****************************************************************************** _CheckRemotePortTCB2 ; Checks if the remote port in the TCP packet is in TCB2_BANK ; INPUT: tcpRemotePortLSB, tcpRemotePortMSB, tcb2RemotePortLSB, ; tcb2RemotePortMSB ; OUTPUT: Z set if in there ; ****************************************************************************** _bank TCPPORT_BANK mov w, tcpRemotePortMSB bank TCB2_BANK xor w, tcb2RemotePortMSB sz retp mov w, tcb2RemotePortLSB bank TCPPORT_BANK xor w, tcpRemotePortLSB retp ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ; YOU SHOULD HAVE 151 WORDS LEFT HERE FROM ; $168 TO $1FF ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ORG $168 TEST3 _BANK SILO_BANK CJE SILO,#1,SB1 CJE SILO,#2,SB2 CJE SILO,#3,SB3 CJE SILO,#4,SB4 CJE SILO,#5,SB5 CJE SILO,#6,SB6 CJE SILO,#7,SB7 CJE SILO,#8,SB8 CJE SILO,#9,SB9 JMP @RXDONE1 ;IF NONE THEN JUMP BACK SB1 MOV SILO1+2,ASCII JMP @RXDONE1 SB2 MOV SILO2+2,ASCII JMP @RXDONE1 SB3 MOV SILO3+2,ASCII JMP @RXDONE1 SB4 MOV SILO4+2,ASCII JMP @RXDONE1 SB5 SETB FSR.4 MOV SILO5+2,M_ASCII JMP @RXDONE1 SB6 SETB FSR.4 MOV SILO6+2,M_ASCII JMP @RXDONE1 SB7 SETB FSR.4 MOV SILO7+2,M_ASCII JMP @RXDONE1 SB8 SETB FSR.4 MOV SILO8+2,M_ASCII JMP @RXDONE1 SB9 SETB FSR.4 MOV SILO9+2,M_ASCII JMP @RXDONE1 ORG $200 ; Page1 NICBufCopy jmp _NICBufCopy NICBufWrite jmp _NICBufWrite NICBufRead jmp _NICBufRead NICBufIPAddrWr jmp _NICBufIPAddrWr NICWriteSrcIP jmp _NICWriteSrcIP NICWriteDestIP jmp _NICWriteDestIP NICWriteSrcEth jmp _NICWriteSrcEth NICWriteDestEth jmp _NICWriteDestEth NICDMAInit jmp _NICDMAInit ; ****************************************************************************** NICInit ; Initializes and configures Realtek RTL8019AS NIC ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank NIC_BANK mov nicIOAddr, #$1F ; write to reset port mov w, #0 call NICWrite call @StartupDelay ; give it a little time to reset ; --- Page3 Registers --- clr nicIOAddr ; CR mov w, #%11000001 ; Page3, Stop call NICWrite mov nicIOAddr, #$01 ; 9346CR mov w, #%11000000 ; config register write enable call NICWrite mov nicIOAddr, #$05 ; CONFIG2 mov w, #%00000000 ; link test enable call NICWrite ; --- Page1 Registers --- clr nicIOAddr ; CR mov w, #%01000001 ; Page1, Stop call NICWrite inc nicIOAddr ; ($01) PAR0 mov w, #SX_ETH_ADDR0 call NICWrite inc nicIOAddr ; ($02) PAR1 mov w, #SX_ETH_ADDR1 call NICWrite inc nicIOAddr ; ($03) PAR2 mov w, #SX_ETH_ADDR2 call NICWrite inc nicIOAddr ; ($04) PAR3 mov w, #SX_ETH_ADDR3 call NICWrite inc nicIOAddr ; ($05) PAR4 mov w, #SX_ETH_ADDR4 call NICWrite inc nicIOAddr ; ($06) PAR5 mov w, #SX_ETH_ADDR5 call NICWrite inc nicIOAddr ; ($07) CURR mov w, #RXBUF_START call NICWrite ; --- Page0 Registers --- clr nicIOAddr ; CR mov w, #%00000001 ; Page0, Stop call NICWrite inc nicIOAddr ; ($01) PSTART mov w, #RXBUF_START call NICWrite inc nicIOAddr ; ($02) PSTOP mov w, #RXBUF_END call NICWrite inc nicIOAddr ; ($03) BNRY mov w, #RXBUF_START call NICWrite mov nicIOAddr, #$07 ; ISR mov w, #$FF call NICWrite mov nicIOAddr, #$0C ; RCR mov w, #%11000110 call NICWrite inc nicIOAddr ; ($0D) TCR mov w, #%11100000 call NICWrite inc nicIOAddr ; ($0E) DCR mov w, #%10111000 call NICWrite clr nicIOAddr ; CR mov w, #%00000010 ; Page0, Start call NICWrite retp ; ****************************************************************************** NICWrite ; Does an I/O Write of a byte on the ISA host bus to the NIC ; INPUT: w = byte to be written ; nicIOAddr = I/O address (most-significant 3 bits must be zero) ; OUTPUT: none ; ****************************************************************************** bank NIC_BANK ; put Data out on Data bus mov NIC_DATA_PORT, w _mode DIR_W mov w, #0 ; output mov !NIC_DATA_PORT, w ; put addr out on addr bus mov w, NIC_CTRL_PORT and w, #%11100000 or w, nicIOAddr mov NIC_CTRL_PORT, w ; strobe IOWB pin jmp $+1 clrb IOWB_PIN jmp $+1 jnb IOCH_PIN, $ setb IOWB_PIN retp ; ****************************************************************************** NICWriteAgain ; Write to the same nicIOAddr as the previous call to NICWrite() ; INPUT: w = byte to be written ; OUTPUT: none ; ****************************************************************************** ; put Data out on Data bus mov NIC_DATA_PORT, w ; strobe IOWB pin jmp $+1 clrb IOWB_PIN jmp $+1 jnb IOCH_PIN, $ setb IOWB_PIN retp ; ****************************************************************************** NICRead ; Does an I/O Read of a byte on the ISA host bus from the NIC ; INPUT: nicIOAddr = I/O address (most-significant 3 bits must be zero) ; OUTPUT: w = byte read ; ****************************************************************************** bank NIC_BANK ; configure Data bus for input _mode DIR_W mov w, #$FF ; input mov !NIC_DATA_PORT, w ; put addr out on addr bus mov w, NIC_CTRL_PORT and w, #%11100000 or w, nicIOAddr mov NIC_CTRL_PORT, w ; strobe IORB pin and latch Data jmp $+1 clrb IORB_PIN jmp $+1 jnb IOCH_PIN, $ mov w, NIC_DATA_PORT setb IORB_PIN retp ; ****************************************************************************** NICReadAgain ; Read the NIC using the same nicIOAddr as the previous call to NICRead() ; INPUT: none ; OUTPUT: w = byte read ; ****************************************************************************** ; strobe IORB pin and latch Data jmp $+1 clrb IORB_PIN jmp $+1 jnb IOCH_PIN, $ mov w, NIC_DATA_PORT setb IORB_PIN retp ; ****************************************************************************** NICPseudoRead ; 'Read' the NIC, but ignore Data. Must have called NICRead() or NICReadAgain() ; priorly ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; strobe IORB pin jmp $+1 clrb IORB_PIN jmp $+1 jnb IOCH_PIN, $ setb IORB_PIN retp ; ****************************************************************************** NICPseudoRead6 ; 'Read' the NIC (6) times, but ignore Data. Must have called NICRead() or ; NICReadAgain() priorly ; INPUT: none ; OUTPUT: none ; ****************************************************************************** mov w, #6 :loop call NICPseudoRead decsz wreg jmp :loop retp ; ****************************************************************************** NICCheckRxFrame ; Checks to see if an ethernet frame has been received ; INPUT: none ; OUTPUT: z is cleared if there's a frame waiting, otherwise z is set ; ****************************************************************************** _bank NIC_BANK clr nicIOAddr ; CR mov w, #%01100010 ; Page1, abort DMA call NICWrite mov nicIOAddr, #$07 ; CURR call NICRead mov globTemp1, w clr nicIOAddr ; CR mov w, #%00000010 ; Page0 call NICWrite mov nicIOAddr, #$03 ; BNRY call NICRead xor w, globTemp1 ; CURR = BNRY => no packets retp ; ****************************************************************************** NICWaitRxFrame ; Wait for an ethernet frame to be received. ; INPUT: none ; OUTPUT: nicCurrPktPtr = points to beginning of packet just received ; nicNextPktPtr = points to beginnig of next packet ; nicRemoteEth0-5 = source (remote) ethernet address ; ****************************************************************************** clrb flags2.GOT_RX_FRAME ; clear indication of prev. ; rcvd frame _bank NIC_BANK :loop clr nicIOAddr ; CR mov w, #%01100010 ; Page1, abort DMA call NICWrite mov nicIOAddr, #$07 ; CURR call NICRead mov globTemp1, w clr nicIOAddr ; CR mov w, #%00000010 ; Page0 call NICWrite mov nicIOAddr, #$03 ; BNRY call NICRead xor w, globTemp1 snz ; CURR = BNRY => no packets retp ; Return immediately setb flags2.GOT_RX_FRAME ; indicate we got something clr nicIOAddr ; CR mov w, #%00011010 ; Page0, packet send call NICWrite ; store current-packet pointer mov nicIOAddr, #$03 ; BNRY call NICRead mov nicCurrPktPtr, w mov nicIOAddr, #$10 ; RDMA ; ignore receive status call NICRead ; store next-packet pointer call NICReadAgain mov nicNextPktPtr, w ; ignore ethernet frame size call NICPseudoRead call NICPseudoRead ; ignore the <destination> ethernet addr call NICPseudoRead6 ; record the sender's <source> ethernet addr call NICReadAgain mov nicRemoteEth0, w call NICReadAgain mov nicRemoteEth1, w call NICReadAgain mov nicRemoteEth2, w call NICReadAgain mov nicRemoteEth3, w call NICReadAgain mov nicRemoteEth4, w call NICReadAgain mov nicRemoteEth5, w clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA call NICWrite retp ; ****************************************************************************** NICDumpRxFrame ; Discard the current received frame by advancing the receive circular buffer ; tail pointer ; INPUT: nicNextPktPtr = next packet page ; OUTPUT: none ; ****************************************************************************** bank NIC_BANK clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA call NICWrite mov nicIOAddr, #$03 ; BNRY mov w, nicNextPktPtr ; advance tail pointer call NICWrite retp ; ****************************************************************************** NICInitTxFrame ; i. initialize NIC for remote-DMA writes ; ii. fills in ethernet <destination> and <source> ; INPUT: w = starting page number of tx buffer ; nicRemoteEth0-5 = Destination ethernet address ; OUTPUT: none ; ****************************************************************************** mov globTemp1, w bank NIC_BANK ; wait for prior transmission to complete clr nicIOAddr ; CR :wait call NICRead jb wreg.2, :wait mov w, #%00100010 ; Page0, abort DMA call NICWrite mov nicIOAddr, #$04 ; TPSR mov w, globTemp1 call NICWrite mov nicIOAddr, #$08 ; RSAR0 mov w, #$00 call NICWrite inc nicIOAddr ; ($09) RSAR1 mov w, globTemp1 call NICWrite mov nicIOAddr, #$0A ; RBCR0 mov w, #$EA ; max ethernet packet size call NICWrite inc nicIOAddr ; ($0B) RBCR1 mov w, #$05 call NICWrite clr nicIOAddr ; CR mov w, #%00010010 ; Page0, remote write call NICWrite mov nicIOAddr, #$10 ; RDMA ; <destination> call NICWriteDestEth ; <source> call NICWriteSrcEth retp ; ****************************************************************************** NICSendTxFrame ; Once the transmit buffer on the NIC is filled, call this to tell the NIC to ; start sending ; INPUT: {ipLengthMSB,ipLengthLSB} = length of IP frame to be transmitted ; OUTPUT: none ; ****************************************************************************** call @ARPCheckCache ; start ARP routine snb flags3.ARP_REQ_SENT ; Continue if an ARP request ; was not sent retp ; exit, ARP request was sent ; or we are still waiting ; for a response ; an entry point into the function to skip the ARP routines ; no code space left in this bank to elegantly check a bit NICSendTxFrameNow bank NIC_BANK clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA call NICWrite bank IP_BANK mov w, #(64-6-6-2) mov w, ipLengthLSB-w jc :notRunt mov w, #1 mov w, ipLengthMSB-w jc :notRunt bank NIC_BANK mov nicIOAddr, #$05 ; TBCR0 mov w, #64 ; min ethernet frame size call NICWrite inc nicIOAddr ; ($06) TBCR1 mov w, #0 call NICWrite jmp :transmit :notRunt bank NIC_BANK mov nicIOAddr, #$05 ; TBCR0 bank IP_BANK mov w, #(6+6+2) add w, ipLengthLSB call NICWrite ; should not affect carry flag inc nicIOAddr ; ($06) TBCR1 bank IP_BANK mov w, ipLengthMSB snc inc wreg call NICWrite :transmit clr nicIOAddr ; CR mov w, #%00000110 ; Page0, transmit call NICWrite retp ; ****************************************************************************** _NICBufCopy ; Copy one part of the NIC's SRAM buffer to another part ; INPUT: {nicCopySrcMSB,nicCopySrcLSB} = source address in NIC's SRAM ; {nicCopyDestMSB,nicCopyDestLSB} = Destination address in NIC's SRAM ; {nicCopyLenMSB,nicCopyLenLSB} = length of buffer to copy ; OUTPUT: none ; ****************************************************************************** bank NIC_BANK clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA call NICWrite mov nicIOAddr, #$0B ; RBCR1 mov w, #0 ; MSB is always zero call NICWrite ; initialize RDMA to get source byte :loop clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA call NICWrite mov nicIOAddr, #$08 ; RSAR0 mov w, nicCopySrcLSB call NICWrite inc nicIOAddr ; ($09) RSAR1 mov w, nicCopySrcMSB call NICWrite mov nicIOAddr, #$0A ; RBCR0 mov w, #1 ; one-byte DMA call NICWrite clr nicIOAddr ; CR mov w, #%00001010 ; Page0, remote read call NICWrite mov nicIOAddr, #$10 ; RDMA call NICRead mov nicCopyTemp, w ; store source byte temporarily ; initialize RDMA to write byte to Destination mov nicIOAddr, #$08 ; RSAR0 mov w, nicCopyDestLSB call NICWrite inc nicIOAddr ; ($09) RSAR1 mov w, nicCopyDestMSB call NICWrite inc nicIOAddr ; ($0A) RBCR0 mov w, #1 ; one-byte DMA call NICWrite clr nicIOAddr ; CR mov w, #%00010010 ; Page0, remote write call NICWrite mov nicIOAddr, #$10 ; RDMA mov w, nicCopyTemp call NICWrite ; increment source and Destination pointers inc nicCopySrcLSB snz inc nicCopySrcMSB inc nicCopyDestLSB snz inc nicCopyDestMSB ; check if source page pointer hit receive buffer ceiling mov w, nicCopySrcMSB xor w, #RXBUF_END jnz :here mov nicCopySrcMSB, #RXBUF_START ; loop as many times as there are bytes to copy :here decsz nicCopyLenLSB jmp :loop test nicCopyLenMSB snz retp dec nicCopyLenMSB jmp :loop ; ****************************************************************************** _NICBufWrite ; Writes a byte to the SRAM buffer in the NIC ; INPUT: {nicCopySrcMSB,nicCopySrcLSB} = address in buffer memory to write to ; w = byte to write ; OUTPUT: none ; ****************************************************************************** bank NIC_BANK mov nicCopyTemp, w clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA mov nicIOAddr, #$08 ; RSAR0 mov w, nicCopySrcLSB call NICWrite inc nicIOAddr ; ($09) RSAR1 mov w, nicCopySrcMSB call NICWrite inc nicIOAddr ; ($0A) RBCR0 mov w, #1 ; one-byte DMA call NICWrite inc nicIOAddr ; ($0B) RBCR1 mov w, #0 ; MSB is always zero call NICWrite clr nicIOAddr ; CR mov w, #%00010010 ; Page0, remote write call NICWrite mov nicIOAddr, #$10 ; RDMA mov w, nicCopyTemp call NICWrite retp ; ****************************************************************************** _NICBufRead ; Reads a byte from the SRAM buffer in the NIC ; INPUT: {nicCopySrcMSB,nicCopySrcLSB} = address in buffer memory to read from ; OUTPUT: w = byte read ; ****************************************************************************** bank NIC_BANK clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA mov nicIOAddr, #$08 ; RSAR0 mov w, nicCopySrcLSB call NICWrite inc nicIOAddr ; ($09) RSAR1 mov w, nicCopySrcMSB call NICWrite inc nicIOAddr ; ($0A) RBCR0 mov w, #1 ; one-byte DMA call NICWrite inc nicIOAddr ; ($0B) RBCR1 mov w, #0 ; MSB is always zero call NICWrite clr nicIOAddr ; CR mov w, #%00001010 ; Page0, remote read call NICWrite mov nicIOAddr, #$10 ; RDMA call NICRead retp ; ****************************************************************************** _NICBufIPAddrWr ; Writes the source and destination IP addresses to the SRAM buffer in the NIC ; INPUT: {nicCopySrcMSB,nicCopySrcLSB} = address in buffer memory to write to ; myIP3-0 = <source_IP> ; remoteIP3-0 = <destination_IP> ; OUTPUT: none ; ****************************************************************************** bank NIC_BANK clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA mov nicIOAddr, #$08 ; RSAR0 mov w, nicCopySrcLSB call NICWrite inc nicIOAddr ; ($09) RSAR1 mov w, nicCopySrcMSB call NICWrite inc nicIOAddr ; ($0A) RBCR0 mov w, #(4+4) ; 8-byte DMA call NICWrite inc nicIOAddr ; ($0B) RBCR1 mov w, #0 ; MSB is always zero call NICWrite clr nicIOAddr ; CR mov w, #%00010010 ; Page0, remote write call NICWrite mov nicIOAddr, #$10 ; RDMA ; <source_IP> call NICWriteSrcIP ; <destination_IP> call NICWriteDestIP retp ; ****************************************************************************** _NICWriteSrcIP ; Write Source IP address to NIC's buffer using remote DMA. NIC must be pre- ; initialized for this. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** jnb flags.GOT_IP_ADDR, :noIP ; use IP address at noIP if bank IP_BANK ; we got none from DHCP mov w, myIP3 call NICWrite bank IP_BANK mov w, myIP2 call NICWriteAgain mov w, myIP1 call NICWriteAgain mov w, myIP0 call NICWriteAgain retp :noIP mov w, #0 ; 0.0.0.0 call NICWrite mov w, #0 call NICWriteAgain call NICWriteAgain call NICWriteAgain retp ; ****************************************************************************** _NICWriteDestIP ; Write Destination IP address to NIC's buffer using remote DMA. NIC must be ; pre-initialized for this. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** bank IP_BANK mov w, remoteIP3 call NICWrite bank IP_BANK mov w, remoteIP2 call NICWriteAgain bank IP_BANK mov w, remoteIP1 call NICWriteAgain bank IP_BANK mov w, remoteIP0 call NICWriteAgain retp ; ****************************************************************************** _NICWriteSrcEth ; Write Source Ethernet address to NIC's buffer using remote DMA. NIC must be ; pre-initialized for this. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** mov w, #SX_ETH_ADDR0 call NICWrite mov w, #SX_ETH_ADDR1 call NICWriteAgain mov w, #SX_ETH_ADDR2 call NICWriteAgain mov w, #SX_ETH_ADDR3 call NICWriteAgain mov w, #SX_ETH_ADDR4 call NICWriteAgain mov w, #SX_ETH_ADDR5 call NICWriteAgain retp ; ****************************************************************************** _NICWriteDestEth ; Write Destination Ethernet address to NIC's buffer using remote DMA. NIC must ; be pre-initialized for this. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** mov w, nicRemoteEth0 call NICWrite mov w, nicRemoteEth1 call NICWriteAgain mov w, nicRemoteEth2 call NICWriteAgain mov w, nicRemoteEth3 call NICWriteAgain mov w, nicRemoteEth4 call NICWriteAgain mov w, nicRemoteEth5 call NICWriteAgain retp ; ****************************************************************************** _NICDMAInit ; Setup the NIC's RSAR and RBCR register in preparation for remote DMA. ; INPUT: nicCurrPktPtr = beginning of packet ; OUTPUT: none ; ****************************************************************************** bank NIC_BANK clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA call NICWrite ; initialize DMA to <type> field in ethernet frame mov nicIOAddr, #$08 ; RSAR0 mov w, #(4+6+6) ; point to <type> field call NICWrite inc nicIOAddr ; ($09) RSAR1 mov w, nicCurrPktPtr call NICWrite inc nicIOAddr ; ($0A) RBCR0 mov w, #$FF call NICWrite inc nicIOAddr ; ($0B) RBCR1 mov w, #$0F call NICWrite retp ORG $400 ; Page2 ARPSendResponse jmp _ARPSendResponse ARPSendStPacket jmp _ARPSendStPacket CheckIPDatagram jmp _CheckIPDatagram CheckIPDestAddr jmp _CheckIPDestAddr ICMPProcPktIn jmp _ICMPProcPktIn Copy4Inc jmp _Copy4Inc ; ****************************************************************************** NICRead_2 ; Shortform for calling NICRead(), which is in Page1 (This is in Page2) ; ****************************************************************************** jmp @NICRead ; ****************************************************************************** NICReadAgain_2 ; Shortform for calling NICReadAgain(), which is in Page1 (This is in Page2) ; ****************************************************************************** jmp @NICReadAgain ; ****************************************************************************** NICPseudoRead_2 ; Shortform for calling NICPseudoRead(), which is in Page1 (This is in Page2) ; ****************************************************************************** jmp @NICPseudoRead ; ****************************************************************************** NICPseudoRead6_2 ; Shortform for calling NICPseudoRead(), which is in Page1 (This is in Page2) ; ****************************************************************************** jmp @NICPseudoRead6 ; ****************************************************************************** NICWrite_2 ; Shortform for calling NICWrite(), which is in Page1 (This is in Page2) ; ****************************************************************************** jmp @NICWrite ; ****************************************************************************** NICWriteAgain_2 ; Shortform for calling NICWriteAgain(), which is in Page1 (This is in Page2) ; ****************************************************************************** jmp @NICWriteAgain ; ****************************************************************************** NICDumpRxFrame_2 ; Shortform for calling NICDumpRxFrame(), which is in Page1 (This is in Page2) ; ****************************************************************************** jmp @NICDumpRxFrame ; ****************************************************************************** ARPCheckCache ; Checks if remote(destination) host IP address is in cache. If so, update ; packet Ethernet address in NIC with cache entry, else send ARP request. ; INPUT: remoteIP0-3, host1IP0-3 ; OUTPUT: none ; ****************************************************************************** jnb flags3.ARP_STL_TX, :cacheGo ; do not check cache ; if stalled packet ; to be txed call ARPUpdateEthAddr ; update stalled packet's ethernet address mov w, #%11111000 and flags3, w ; reset ARP retp :cacheGo ; check if remote host IP is in cache bank IP_BANK mov w, remoteIP0 bank ARP_BANK xor w, host1IP0 jnz :cacheNoMatch ; no match mov w, host1IP1 bank IP_BANK xor w, remoteIP1 jnz :cacheNoMatch ; no match mov w, remoteIP2 bank ARP_BANK xor w, host1IP2 jnz :cacheNoMatch ; no match mov w, host1IP3 bank IP_BANK xor w, remoteIP3 jz :cacheMatch ; match! remoteIP0-3 = host1IP0-3 :cacheNoMatch setb flags3.ARP_REQ_SENT ; indicate an ARP request is sent jmp ARPSendRequest ; do an ARP request to get the ; remote Eth address :cacheMatch mov w, #%11111000 and flags3, w ; reset ARP jmp ARPUpdateEthAddr ; update remote Eth address of ; pending packet ; ****************************************************************************** ARPUpdateEthAddr ; Updates Eth Address of pending packet to be txed in NIC's buffer with that in ; ARP cache ; INPUT: host1Eth0-5, stPktTxBufStart ; OUTPUT: none ; ****************************************************************************** bank NIC_BANK clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA call NICWrite_2 mov nicIOAddr, #$08 ; RSAR0 mov w, #0 call NICWrite_2 inc nicIOAddr ; ($09) RSAR1 bank ARP_BANK mov w, stPktTxBufStart ; store page no of stalled pkt call NICWrite_2 bank NIC_BANK inc nicIOAddr ; ($0A) RBCR0 mov w, #(6+6) ; 12-byte DMA call NICWrite_2 inc nicIOAddr ; ($0B) RBCR1 mov w, #0 ; MSB is always zero call NICWrite_2 clr nicIOAddr ; CR mov w, #%00010010 ; Page0, remote write call NICWrite_2 mov nicIOAddr, #$10 ; RDMA ; <destination_Eth> bank ARP_BANK mov w, host1Eth0 call NICWrite_2 bank ARP_BANK mov w, host1Eth1 call NICWriteAgain_2 mov w, host1Eth2 call NICWriteAgain_2 mov w, host1Eth3 call NICWriteAgain_2 mov w, host1Eth4 call NICWriteAgain_2 mov w, host1Eth5 jmp NICWriteAgain_2 ; ****************************************************************************** ARPCheckIfIs ; Checks received packet to see if it is ARP. ; Sends an ARP response if its a request. ; Updates cache if it's an ARP response. ; INPUT: nicCurrPktPtr = points to beginning of received packet ; OUTPUT: remoteIP0-3 (:rcvdARPRequest), host1Eth0-5 (:rcvdARPResponse) ; ****************************************************************************** clrb flags.RX_IS_ARP call @NICDMAInit clr nicIOAddr ; CR mov w, #%00001010 ; Page0, remote read call NICWrite_2 mov nicIOAddr, #$10 ; RDMA ; check if ethernet <type> field ; contains ARP identifier (0x0806) call NICRead_2 xor w, #$08 jnz :outtaHere call NICReadAgain_2 xor w, #$06 jnz :outtaHere setb flags.RX_IS_ARP ; yes, it's ARP, indicate that for ; main loop ; ignore <hardware_type>,<protocol_type>,<HLEN>,<PLEN> call NICPseudoRead6_2 ; checks if the ARP packet received is a request or a response call NICReadAgain_2 xor w, #$00 jnz :outtaHere ; not ARP at all call NICReadAgain_2 mov globTemp1, w ; store ARP opcode xor w, #$01 ; check if ARP Request (0x0001) jz :rcvdARPRequest ; yes, process ARP request mov w, globTemp1 xor w, #$02 ; check if ARP Response (0x0002) jz :rcvdARPResponse ; yes, process ARP response jmp :outtaHere ; no, not ARP at all ; ignore <sender_HA> :rcvdARPRequest call NICPseudoRead6_2 ; record the sender's IP addr (<sender_IP>) ; will be used to reply to sender :senderIP bank IP_BANK call NICReadAgain_2 mov remoteIP3, w call NICReadAgain_2 mov remoteIP2, w call NICReadAgain_2 mov remoteIP1, w call NICReadAgain_2 mov remoteIP0, w ; ignore <target_HA> :targetHA call NICPseudoRead6_2 ; check if <target_IP> is me mov fsr, #myIP3 call ARPCompare4 jnz :outtaHere ; so it's for me! call ARPSendResponse jmp NICDumpRxFrame_2 ; we're done with this packet, dump it :rcvdARPResponse ; <sender_HA> ; record sender's Eth address in ARP cache mov fsr, #host1Eth0 mov globTemp1, #6 :ethLoop call NICReadAgain_2 mov indf, w inc fsr decsz globTemp1 jmp :ethLoop ; <sender_IP> ; check if sender's IP corrresponds to IP address in ARP cache mov fsr, #host1IP3 call ARPCompare4 jz :ipAddrResolved ; whoops, sender doesn't correspond to who we're trying to resolve! ; if we're waiting for an ARP response (no problem here) jb flags3.ARP_REQ_SENT, :outtaHere ; otherwise, we need to invalidate the now corrupted ARP cache clr host1IP3 clr host1IP1 clr host1IP2 clr host1IP0 jmp :outtaHere :ipAddrResolved setb flags3.ARP_RSP_RCVD ; indicate we got a successfull ARP response setb flags3.ARP_STL_TX ; transmit the stalled packet now :outtaHere snb flags.RX_IS_ARP ; check if packet was ARP call NICDumpRxFrame_2 ; if it was ARP, we dump it; otherwise, don't touch it retp ; ****************************************************************************** ARPCompare4 ; Compares Data from NICReadAgain() against a 4-byte word store consequtively ; in the SX's Data memory ; INPUT: fsr = points to beginning of 4-byte word to compare against ; OUTPUT: z: 1 = match, 0 = not match ; ****************************************************************************** mov globTemp1, #4 :loop call NICReadAgain_2 xor w, indf sz retp ; mis-match inc fsr decsz globTemp1 jmp :loop stz retp ; ****************************************************************************** ARPSendCommon1 ; Helper function for ARPSendRequest and ARPSendResponse ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; <type> = 0x0806 mov w, #$08 call NICWriteAgain_2 mov w, #$06 call NICWriteAgain_2 ; <hardware_type> = 0x0001 mov w, #$00 call NICWriteAgain_2 mov w, #$01 call NICWriteAgain_2 ; <protocol_type> = 0x0800 mov w, #$08 call NICWriteAgain_2 mov w, #$00 call NICWriteAgain_2 ; <HLEN> = 0x06 mov w, #$06 call NICWriteAgain_2 ; <PLEN> = 0x04 mov w, #$04 jmp NICWriteAgain_2 ; ****************************************************************************** ARPSendCommon2 ; Helper function for ARPSendRequest and ARPSendResponse ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; <sender_HA> call @NICWriteSrcEth ; <sender_IP> call @NICWriteSrcIP ; <target_HA> call @NICWriteDestEth ; <target_IP> call @NICWriteDestIP ; whew! the ethernet frame is now complete, get ready to send .. bank NIC_BANK ; NICWriteDestIP changes bank clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA call NICWrite_2 mov nicIOAddr, #$05 ; TBCR0 mov w, #$40 ; min ethernet packet size call NICWrite_2 inc nicIOAddr ; ($06) TBCR1 mov w, #$00 call NICWrite_2 clr nicIOAddr ; CR mov w, #%00000110 ; transmit jmp NICWrite_2 ; ****************************************************************************** ARPSendRequest ; Stores remote IP address for which pending packet is intended in ARP cache and ; sends an ARP Request ; INPUT: none ; OUTPUT: none ; ****************************************************************************** bank IP_BANK mov w, remoteIP3 ; store IP address of target in ARP cache bank ARP_BANK mov host1IP3, w bank IP_BANK mov w, remoteIP2 bank ARP_BANK mov host1IP2, w bank IP_BANK mov w, remoteIP1 bank ARP_BANK mov host1IP1, w bank IP_BANK mov w, remoteIP0 bank ARP_BANK mov host1IP0, w bank NIC_BANK mov w, #$FF mov nicRemoteEth0, w ; setup broadcast Ethernet address mov nicRemoteEth1, w mov nicRemoteEth2, w mov nicRemoteEth3, w mov nicRemoteEth4, w mov nicRemoteEth5, w mov w, #TXBUF4_START ; point to ARP transmit buffer call @NICInitTxFrame call ARPSendCommon1 ; <operation> = 0x0001 , ARP request opcode mov w, #$00 call NICWriteAgain_2 mov w, #$01 call NICWriteAgain_2 call ARPSendCommon2 bank TIMER_BANK ; initialise the APR timeout timer clr arpTimerMSB clr arpTimerLSB retp ; ****************************************************************************** _ARPSendResponse ; Send an ARP Response in reply to a ARP request. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** mov w, #TXBUF4_START ; point to ARP transmit buffer call @NICInitTxFrame call ARPSendCommon1 ; <operation> = 0x0002 mov w, #$00 call NICWriteAgain_2 mov w, #$02 call NICWriteAgain_2 jmp ARPSendCommon2 ; ****************************************************************************** _ARPSendStPacket ; Sends the ARP stalled packet if any and also check if a timeout on waiting for ; an ARP response occured. If timeout, clear ARP cache ; INPUT: none ; OUTPUT: none ; ****************************************************************************** sb flags3.ARP_REQ_SENT ; check if we are waiting for ; an ARP response retp ; no, nothing to Do here ; if no ARP response rcvd, check if timed out on waiting for it jnb flags3.ARP_STL_TX, :checkARPTimeout ; yes we have rcvd a response we've been waiting for ; now we can send the stalled packet mov w, #%11111000 and flags3, w ; reset ARP ; re-initialize the NIC's TPSR bank NIC_BANK clr nicIOAddr ; CR :wait call NICRead_2 jb wreg.2, :wait ; wait for prior transmission ; to complete mov w, #%00100010 ; Page0, abort DMA call NICWrite_2 mov nicIOAddr, #$04 ; TPSR bank ARP_BANK mov w, stPktTxBufStart ; load stalled packet's ; address pointer call NICWrite_2 ; read the NIC's transmit buffer to find out the IP <length> ; so that we can re-initialize the NIC's TBCR bank ARP_BANK mov w, stPktTxBufStart bank NIC_BANK 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 ; transmit the stalled ethernet frame :checkARPTimeout bank TIMER_BANK csae arpTimerMSB, #ARP_TIMEOUT ; has the timer expired? retp ; no, just return mov w, #%11111000 and flags3, w ; yes, reset ARP flags ; Clear the ARP cache, since it acted as a temporary storage ; of the requested IP address. If we Do not clear the cache now, ; the next re-transmit routine will find a false match in the ; ARP cache. bank ARP_BANK clr host1IP3 clr host1IP2 clr host1IP1 clr host1IP0 retp ; ****************************************************************************** _CheckIPDatagram ; Checks to see if received ethernet frame contains an IP Datagram. If not, the ; frame will be discarded since this stack Doesn't Deal with any other kinds of ; Data-link layer protocol. ; INPUT: nicCurrPktPtr = points to beginning of received packet ; OUTPUT: none ; ****************************************************************************** clrb flags.RX_IS_IP_BCST ; clear broadcast IP indication CHKIP_MASK = ~((1<<RX_IS_ICMP)|(1<<RX_IS_UDP)|(1<<RX_IS_TCP)|(1<<RX_IS_IP_BCST)) mov w, #CHKIP_MASK and flags, w call @NICDMAInit clr nicIOAddr ; CR mov w, #%00001010 ; Page0, remote read call NICWrite_2 mov nicIOAddr, #$10 ; RDMA ; check if ethernet <type> field contains IP identifier (0x0800) call NICRead_2 xor w, #$08 jnz :outtaHere call NICReadAgain_2 xor w, #$00 jnz :outtaHere ; check <version> and <HLEN> call NICReadAgain_2 xor w, #$45 ; version = 4, header length = 5 jnz :outtaHere ; ignore <service_type> call NICPseudoRead_2 ; record <total_length> call NICReadAgain_2 bank IP_BANK mov ipLengthMSB, w call NICReadAgain_2 mov ipLengthLSB, w ; adjust {ipLengthMSB,ipLengthLSB} to reflect number of ; Data bytes sub ipLengthLSB, #20 sc dec ipLengthMSB ; ignore <identification> REPT 2 call NICPseudoRead_2 ENDR ; check against IP packet fragmentation call NICReadAgain_2 jb wreg.5, :outtaHere ; <flags> call NICReadAgain_2 xor w, #0 ; <fragment_offset> jnz :outtaHere ; ignore <time_to_live> call NICPseudoRead_2 ; record <protocol> call NICReadAgain_2 mov ipProtocol, w ; ignore <header_checksum> REPT 2 call NICPseudoRead_2 ENDR ; record <source_IP> :srcIP bank IP_BANK call NICReadAgain_2 mov remoteIP3, w call NICReadAgain_2 mov remoteIP2, w call NICReadAgain_2 mov remoteIP1, w call NICReadAgain_2 mov remoteIP0, w ; check <destination_IP> :destIP clr globTemp2 mov w, myIP3 call CheckIPDestAddr jnz :outtaHere mov w, myIP2 call CheckIPDestAddr jnz :outtaHere mov w, myIP1 call CheckIPDestAddr jnz :outtaHere mov w, myIP0 call CheckIPDestAddr jnz :outtaHere xor globTemp2, #4 snz setb flags.RX_IS_IP_BCST ; IP broadcast addr Detected ; ok! Determine which higher-level protocol mov w, #1 ; ICMP xor w, ipProtocol snz setb flags.RX_IS_ICMP mov w, #17 ; UDP xor w, ipProtocol snz setb flags.RX_IS_UDP mov w, #6 ; TCP xor w, ipProtocol snz setb flags.RX_IS_TCP retp :outtaHere jmp NICDumpRxFrame_2 ; if it ain't IP, forget it! ; ****************************************************************************** _CheckIPDestAddr ; Helper function for CheckIPDatagram ; Check for a match of the IP <destination_IP> field ; INPUT: w = byte of IP to check against ; OUTPUT: z = set if match ; globTemp2 = incremented if matched against 0xFF ; ****************************************************************************** mov globTemp1, w call NICReadAgain_2 xor globTemp1, w snz retp xor w, #$FF ; IP broadcast addr sz retp inc globTemp2 stz retp ; ****************************************************************************** _ICMPProcPktIn ; Process ICMP message. Only Echo Request ICMP messages are handled. All others ; are ignored. If Echo Request message is Detected, this will generate the echo ; reply. ; INPUT: nicCurrPktPtr = points to beginning of received packet ; OUTPUT: none ; ****************************************************************************** ; check <type> call NICReadAgain_2 xor w, #$08 ; echo-request jnz :outtaHere bank IP_BANK add ipLengthLSB, #(2+20) snc inc ipLengthMSB bank NIC_BANK mov nicCopySrcMSB, nicCurrPktPtr ; point to receive ; buffer mov nicCopySrcLSB, #(4+6+6) ; don't copy NIC header ; , eth src & Destn mov nicCopyDestMSB, #TXBUF1_START ; point to transmit ; buffer mov nicCopyDestLSB, #(6+6) bank IP_BANK mov w, ipLengthMSB bank NIC_BANK mov nicCopyLenMSB, w bank IP_BANK mov w, ipLengthLSB bank NIC_BANK mov nicCopyLenLSB, w mov w, #TXBUF1_START ; point to transmit buffer bank ARP_BANK mov stPktTxBufStart, w ; Store ICMP packet start address bank NIC_BANK call @NICInitTxFrame call @NICBufCopy ; change ICMP <type> to echo reply (0) mov nicCopySrcMSB, #TXBUF1_START ; point to transmit ; buffer mov nicCopySrcLSB, #(6+6+2+20) ; point to ICMP <type> mov w, #$00 call @NICBufWrite ; generate ICMP <checksum> mov nicCopySrcMSB, #TXBUF1_START ; point to transmit ; buffer bank IP_BANK mov w, ipLengthMSB bank NIC_BANK mov nicCopyLenMSB, w bank IP_BANK mov w, ipLengthLSB bank NIC_BANK mov nicCopyLenLSB, w sub nicCopyLenLSB, #(2+20+4) sc dec nicCopyLenMSB call @ICMPGenCheckSum ; adjust IP <source_IP> and <destination_IP> mov nicCopySrcMSB, #TXBUF1_START ; point to transmit ; buffer mov nicCopySrcLSB, #(6+6+2+12) ; point to IP <source_IP> call @NICBufIPAddrWr bank IP_BANK sub ipLengthLSB, #2 sc dec ipLengthMSB call @NICSendTxFrame :outtaHere jmp NICDumpRxFrame_2 ; ****************************************************************************** _Copy4Inc ; Copies 4 variables incrementally by copying from var pointed to by globTemp3 ; to variable pointed to by globTemp1 ; INPUT: globTemp1,3 points to variables ; OUTPUT: none ; ****************************************************************************** _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 glob mov fsr, globTemp1 ; move tcb pointer to fsr mov indf, globTemp2 ; overwrite tcb var with tcp var inc globTemp1 ; increment pointer inc globTemp3 ; increment pointer _bank IP_BANK ; check loop counter until finished dec counter1 sz jmp :loop retp ;WE ARE STARTING TO FIT THINGS ANYWHERE THAT WE CAN RIGHT NOW! LOL GET_SILO_NUMBER STC ;SAID TO ADD IT TO THE CODE TO AVOID STRANGE RESULT. SUB ASCII,#48 ;MAKE AN ACTUAL NUMBER OUT OF THIS. MOV SILO,ASCII ;MAKE SILOINC EQUAL THE ACTUAL NUMBER. JMP @RXDONE1 ORG $600 ; Page3 ; ****************************************************************************** NICWrite_3 ; Shortform for calling NICWrite(), which is in Page1 (This is in Page3) ; ****************************************************************************** jmp @NICWrite ; ****************************************************************************** NICWriteAgain_3 ; Shortform for calling NICWriteAgain(), which is in Page1 (This is in Page3) ; ****************************************************************************** jmp @NICWriteAgain ; ****************************************************************************** ICMPGenCheckSum ; Goes through the ICMP message stored in the NIC's SRAM buffer and computes ; the ICMP message checksum. ; INPUT: nicCopySrcMSB = transmit buffer page ; {nicCopyLenMSB,nicCopyLenLSB} = (length of ICMP message - 4) ; OUTPUT: {ipCheckSumMSB,ipCheckSumLSB} = new checksum value ; ****************************************************************************** call IPCheckSumInit bank NIC_BANK mov nicCopyTemp, nicCopySrcMSB clr nicIOAddr ; CR mov w, #%00100010 ; Page0, abort DMA mov nicIOAddr, #$08 ; RSAR0 mov w, #(6+6+2+20+4) ; point to ICMP <identifier> call NICWrite_3 inc nicIOAddr ; ($09) RSAR1 mov w, nicCopySrcMSB call NICWrite_3 inc nicIOAddr ; ($0A) RBCR0 mov w, nicCopyLenLSB call NICWrite_3 inc nicIOAddr ; ($0B) RBCR1 mov w, nicCopyLenMSB call NICWrite_3 clr nicIOAddr ; CR mov w, #%00001010 ; Page0, remote read call NICWrite_3 mov nicIOAddr, #$10 ; RDMA ; configure Data bus for input _mode DIR_W mov w, #$FF ; input mov !NIC_DATA_PORT, w ; put addr out on addr bus mov w, NIC_CTRL_PORT and w, #%11100000 or w, nicIOAddr mov NIC_CTRL_PORT, w inc nicCopyLenMSB ; in order to loop easier later :loop call @NICReadAgain call IPCheckSumAcc bank NIC_BANK decsz nicCopyLenLSB jmp :loop decsz nicCopyLenMSB jmp :loop mov nicCopySrcMSB, nicCopyTemp mov nicCopySrcLSB, #(6+6+2+20+2) bank IP_BANK mov w, /ipCheckSumMSB call @NICBufWrite inc nicCopySrcLSB bank IP_BANK mov w, /ipCheckSumLSB call @NICBufWrite retp ; ****************************************************************************** IPCheckSumInit ; Initializes the IP checksum routine. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** bank IP_BANK clr ipCheckSumMSB clr ipCheckSumLSB clrb flags.IP_CHKSUM_LSB ; next byte is MSB retp ; ****************************************************************************** IPCheckSumAcc ; Accumulate the IP checksum value by adding the next 16-bit number ; IP header checksum (also used to compute ICMP checksum) is computed by Doing ; the one's complement of the one's complement sum of the 16-bit numbers in the ; header. ; INPUT: w = byte to accumulate ; flags.IP_CHKSUM_LSB = set if processing LSB, clear if processing MSB ; OUTPUT: {ipCheckSumMSB,ipCheckSumLSB} = new checksum value ; ****************************************************************************** bank IP_BANK jnb flags.IP_CHKSUM_LSB, :msb ; are we processing an MSB? :lsb add ipCheckSumLSB, w ; add it to the checksum sc ; was there a carry? jmp :done inc ipCheckSumMSB ; yes snz inc ipCheckSumLSB jmp :done :msb add ipCheckSumMSB, w ; add it to the checksum sc ; was there a carry? jmp :done inc ipCheckSumLSB ; yes, this time it is added ; to the LSB snz inc ipCheckSumMSB :done xor flags, #(1<<IP_CHKSUM_LSB) retp ; ****************************************************************************** IPGenCheckSum ; Generate the IP header checksum ; INPUT: {ipLengthMSB,ipLengthLSB} = IP <total_length> ; {ipIdentMSB,ipIdentLSB} = IP <identification> ; ipProtocol = 1(ICMP)/ 6(TCP)/ 17(UDP) ; OUTPUT: {ipCheckSumMSB,ipCheckSumLSB} = new checksum value ; ****************************************************************************** bank IP_BANK call IPCheckSumInit mov w, #$45 ; Version 4, 5x 32 bit words in IP header call IPCheckSumAcc mov w, #$00 call IPCheckSumAcc mov w, ipLengthMSB call IPCheckSumAcc mov w, ipLengthLSB call IPCheckSumAcc mov w, ipIdentMSB call IPCheckSumAcc mov w, ipIdentLSB call IPCheckSumAcc mov w, #%01000000 ; don't fragment call IPCheckSumAcc mov w, #0 call IPCheckSumAcc mov w, #IP_TTL call IPCheckSumAcc mov w, ipProtocol call IPCheckSumAcc jnb flags.GOT_IP_ADDR, :remoteIP ; IP = 0.0.0.0 if no IP mov w, myIP3 call IPCheckSumAcc mov w, myIP2 call IPCheckSumAcc mov w, myIP1 call IPCheckSumAcc mov w, myIP0 call IPCheckSumAcc ; check if this is a tcp packet being constructed and use ; the remoteIP address of the correct socket. ; we can only respond to hosts Defined in the tcp sockets ; foreign incoming packets are not responded to by sending ; a reset since this will need another TCB, they are flat-out ; ignored. The foreign remote host will eventually give up . :remoteIP mov w, ipProtocol xor w, #6 ; is it tcp? jnz :skipSocketCpy ; no, Don't use remoteIP in tcp sockets ; check which is the current tcp connection mov globTemp1, #remoteIP3 ; set source pointer sb flags2.TCP_SOCK mov globTemp3, #sock1RemoteIP3 ; destination pointer snb flags2.TCP_SOCK mov globTemp3, #sock2RemoteIP3 ; destination pointer call @Copy4Inc ; copy sockRemoteIP into remoteIP :skipSocketCpy _bank IP_BANK ; accumulate checksum with remoteIP mov w, remoteIP3 call IPCheckSumAcc mov w, remoteIP2 call IPCheckSumAcc mov w, remoteIP1 call IPCheckSumAcc mov w, remoteIP0 call IPCheckSumAcc retp ; ****************************************************************************** IPStartPktOut ; Starts an outgoing IP packet by constructing the IP packet header ; INPUT: {ipLengthMSB,ipLengthLSB} = IP <total_length> ; {ipIdentMSB,ipIdentLSB} = IP <identification> ; ipProtocol = 1(ICMP)/ 6(TCP)/ 17(UDP) ; {ipCheckSumMSB,ipCheckSumLSB} = IP <header_checksum> ; OUTPUT: none ; ****************************************************************************** bank IP_BANK mov w, #6 ; is it tcp? xor w, ipProtocol jz :useTcpBuf ; yes mov w, #TXBUF1_START ; no, Default tx buffer is TXBUF1 jmp :contIpStartP :useTcpBuf sb flags2.TCP_SOCK ; point to correct tcp conn. ; tx buffer mov w, #TXBUF2_START ; tcp connection1 tx buffer snb flags2.TCP_SOCK mov w, #TXBUF3_START ; tcp connection2 tx buffer :contIpStartP bank ARP_BANK sb flags3.ARP_REQ_SENT ; check if a prev packet ; is stalled mov stPktTxBufStart, w ; no, store new address pointer ; to new packet call @NICInitTxFrame ; <type> = 0x0800 mov w, #$08 call NICWrite_3 mov w, #$00 call NICWriteAgain_3 ; <version> = 4, <HLEN> = 5 mov w, #$45 call NICWriteAgain_3 ; <service_type> mov w, #$00 ; normal precedence, D=T=R=0 call NICWriteAgain_3 ; <total_length> bank IP_BANK mov w, ipLengthMSB call NICWriteAgain_3 mov w, ipLengthLSB call NICWriteAgain_3 ; <identification> mov w, ipIdentMSB call NICWriteAgain_3 mov w, ipIdentLSB call NICWriteAgain_3 ; <flags>, <fragment_offset> mov w, #%01000000 ; do not fragment call NICWriteAgain_3 mov w, #0 ; offset = 0 call NICWriteAgain_3 ; <time_to_live> mov w, #IP_TTL call NICWriteAgain_3 ; <protocol> mov w, ipProtocol call NICWriteAgain_3 ; <header_checksum> mov w, /ipCheckSumMSB call NICWriteAgain_3 mov w, /ipCheckSumLSB call NICWriteAgain_3 ; <source_IP> call @NICWriteSrcIP ; <destination_IP> call @NICWriteDestIP retp ; ****************************************************************************** TCPAppPassiveOpen ; Do a passive open. i.e. listen for connections on a given port. ; [TCP API Function] ; INPUT: {tcb1LocalPortMSB,tcb1LocalPortLSB} = TCP port to listen on ; OUTPUT: none ; ****************************************************************************** _bank TCP_BANK mov tcp2State, #TCP_ST_LISTEN clr tcp2UnAckMSB clr tcp2UnAckLSB retp ; ****************************************************************************** TCPAppActiveOpen ; Do a active open. i.e. initiate a connect to a remote TCP. ; [TCP API Function] ; INPUT: {remoteIP0-3} = Destination IP addr ; {tcbLocalPortMSB,tcbLocalPortLSB} = local TCP port ; {tcbRemotePortMSB,tcbRemotePortLSB} = remote TCP port ; OUTPUT: none ; ****************************************************************************** _bank TCP_BANK clr tcp1UnAckMSB clr tcp1UnAckLSB mov tcp1State, #TCP_ST_SYNSENT bank TCB1_BANK mov tcb1Flags, #(1<<TCP_FLAG_SYN) jmp @TCPSendSyn ; ****************************************************************************** TCPAppClose ; Force the current connection to close ; [TCP API Function] ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; check which tcp connection to close _bank TCP_BANK jb flags2.TCP_SOCK, :finwaitSock2 ; close tcp connection1 mov tcp1State, #TCP_ST_FINWAIT1 clr tcp1UnAckMSB clr tcp1UnAckLSB jmp :contAppClose ; close tcp connection2 :finwaitSock2 mov tcp2State, #TCP_ST_FINWAIT1 clr tcp2UnAckMSB clr tcp2UnAckLSB ; common tcp close code :contAppClose mov globTemp1, #(tcb1Flags-TCB1_BANK) call @SetTCBPointer mov indf, #((1<<TCP_FLAG_FIN)|(1<<TCP_FLAG_ACK)) jmp @TCPSendEmptyPkt ; ****************************************************************************** TCPProcPktIn ; Process a received TCP packet. This function implements the TCP state machine ; INPUT: none ; OUTPUT: none ; ****************************************************************************** call @TCPRxHeader ; receive the header snz ; is the packet OK? retp ; no, return ; check if incoming packet is for tcp conn. 1 or 2 bank TCP_BANK jb flags2.TCP_SOCK, :isTcp2 ; check the special states for tcp connection1 cje tcp1State, #TCP_ST_CLOSED, :CLOSED cje tcp1State, #TCP_ST_LISTEN, :LISTEN cje tcp1State, #TCP_ST_SYNSENT, :SYNSENT cje tcp1State, #TCP_ST_FINWAIT1, :FINWAIT1 cje tcp1State, #TCP_ST_FINWAIT2, :FINWAIT2 cje tcp1State, #TCP_ST_LASTACK, :LASTACK jmp :contProc ; check the special states for tcp connection2 :isTcp2 cje tcp2State, #TCP_ST_CLOSED, :CLOSED cje tcp2State, #TCP_ST_LISTEN, :LISTEN cje tcp2State, #TCP_ST_SYNSENT, :SYNSENT cje tcp2State, #TCP_ST_FINWAIT1, :FINWAIT1 cje tcp2State, #TCP_ST_FINWAIT2, :FINWAIT2 cje tcp2State, #TCP_ST_LASTACK, :LASTACK :contProc call @TCPCmpNxtSeq ; check if RCV.NXT == SEG.SEQ sz ; are they equal? jmp @TCPSendAck ; no, send an ACK and Drop packet ; check the flags mov globTemp1, #(tcb1Flags-TCB1_BANK) call @SetTCBPointer ; point to tcp conn's TCB snb indf.TCP_FLAG_RST ; is the reset flag set? jmp :gotoClosed ; yes, Drop packet and ; close the connection snb indf.TCP_FLAG_SYN ; is the SYN bit set? jmp @TCPSendReset ; yes, Drop the packet and ; send a reset sb indf.TCP_FLAG_ACK ; is the ACK bit set? jmp @NICDumpRxFrame ; no, Drop the packet ; we only accept ACKs of complete packets. ; Assume the ACK is for our last packet mov w, #TCP_ST_ESTABED ; indicate tcp conn established bank TCP_BANK sb flags2.TCP_SOCK ; indicate tcp state to correct mov tcp1State, w ; tcp conn. state variable snb flags2.TCP_SOCK mov tcp2State, w ; if we were in Syn-received then need to send an ACK ; check if for tcp1 or 2 jb flags2.TCP_SOCK, :tcp2AckCheck ;tcp1 test tcp1UnAckLSB sz jmp :outstanding test tcp1UnAckMSB snz jmp :noOutstanding jmp :outstanding ; tcp2 :tcp2AckCheck test tcp2UnAckLSB sz jmp :outstanding test tcp2UnAckMSB snz jmp :noOutstanding jmp :outstanding :outstanding call @TCPAppTxDone ; tell the application it was ACKed _bank TCP_BANK ; _bank cus we called TCPAppTxDone priorly ; check if for tcp1 or 2 jb flags2.TCP_SOCK, :clrTcpUnack2 clr tcp1UnAckLSB ; there should be no Data outstanding now clr tcp1UnAckMSB jmp :noOutstanding :clrTcpUnack2 clr tcp2UnAckLSB ; there should be no Data outstanding now clr tcp2UnAckMSB :noOutstanding ; Does the packet contain Data? (Determine this from the length) test tcpLengthMSB jnz :packetHasData ; MSB is not zero test tcpLengthLSB ; MSB is zero jz :noData ; MSB = LSB = 0 :packetHasData call @TCPAppRxBytes ; inform app how many bytes available _bank TCP_BANK inc tcpLengthMSB :processData call @NICReadAgain ; receive a byte call @TCPAppRxData ; pass the byte to the application _bank TCP_BANK ; _bank cus we called TCPAppRxData ; priorly decsz tcpLengthLSB jmp :processData decsz tcpLengthMSB jmp :processData inc tcpLengthLSB ; indicate for later there was Data ; received :noData call @TCPAckUpdate ; send an ACK packet bank TCP_BANK test tcpLengthLSB ; was Data received? jz :checkFIN ; no, it was an ACK packet. Just return call @TCPAppRxDone ; indicate the packet was OK to the app _bank TCP_BANK ; _bank cus we called TCPAppRxDone ; priorly jb tcpRxFlags.TCP_FLAG_FIN, :doClose ; if FIN bit set, ; close the conn. call @NICDumpRxFrame jmp @TCPSendAck :checkFIN bank TCP_BANK jb tcpRxFlags.TCP_FLAG_FIN, :doClose ; is the FIN bit set? jmp @NICDumpRxFrame :doClose call @NICDumpRxFrame call @TCPIncRcvNxt ; ACK the FIN mov w, #TCP_ST_LASTACK ; change state bank TCP_BANK sb flags2.TCP_SOCK mov tcp1State, w ; indicate tcp conn state to tcp conn snb flags2.TCP_SOCK ; state variable mov tcp2State, w jmp @TCPSendFin :gotoClosed mov w, #TCP_ST_CLOSED ; go to the closed state bank TCP_BANK ; indicate tcp closed conn state to sb flags2.TCP_SOCK ; correct tcp conn state variable mov tcp1State, w snb flags2.TCP_SOCK mov tcp2State, w jmp @NICDumpRxFrame ; discard received packet :FINWAIT1 call @NICDumpRxFrame bank TCP_BANK sb tcpRxFlags.TCP_FLAG_ACK ; check for ACK of FIN retp mov w, #TCP_ST_FINWAIT2 ; rcved ACK of FIN sb flags2.TCP_SOCK ; indicate tcp finwait2 conn state to mov tcp1State, w ; correct tcp conn state variable snb flags2.TCP_SOCK mov tcp2State, w retp :FINWAIT2 call @NICDumpRxFrame bank TCP_BANK sb tcpRxFlags.TCP_FLAG_FIN ; check for FIN retp mov w, #TCP_ST_CLOSED ; rcved FIN sb flags2.TCP_SOCK mov tcp1State, w snb flags2.TCP_SOCK mov tcp2State, w call @TCPIncRcvNxt ; ACK the FIN jmp @TCPSendAck :LASTACK ; ignore the packet ; should check the packet is actually an ACK mov w, #TCP_ST_CLOSED ; go to the closed state 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 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 ; 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 retp ; tcp2 ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ;THIS IS TO SEE IF YOU NEED TO LOOK FOR DYNAMIC INFORMATION :TCPAppTxData2 IF HTTP bank HTTP_BANK cje httpURIHash, #URI1, :specialFile ; NOTHING HERE cje httpURIHash, #URI2, :specialFile ; INDEX.HTML 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 jmp :here1 :here _BANK SILO_BANK CSB SILOINC,#10 ;SKIP IF BELOW 10 CLR SILOINC INC SILOINC ;INCREMENT THE SILO NUMBERS FROM 1 TO 9 CJE SILOINC,#1,:SILO1 CJE SILOINC,#2,:SILO2 CJE SILOINC,#3,:SILO3 CJE SILOINC,#4,:SILO4 CJE SILOINC,#5,:SILO5 CJE SILOINC,#6,:SILO6 CJE SILOINC,#7,@SILO7W CJE SILOINC,#8,@SILO8W CJE SILOINC,#9,@SILO9W ;CLR AFTER 9 OKAY ;THIS IS SILO 1 :SILO1 _BANK SILO_BANK ;THIS IS THE WAY TO MOV THINGS ABOUT MOV W,SILO1 BANK MISC_BANK MOV BCD3,W _BANK SILO_BANK MOV W,SILO1+1 BANK MISC_BANK MOV BCD3+1,W _BANK SILO_BANK MOV W,SILO1+2 BANK MISC_BANK MOV BCD3+2,W JMP :HERE1 :SILO2 _BANK SILO_BANK ;THIS IS THE WAY TO MOV THINGS ABOUT MOV W,SILO2 BANK MISC_BANK MOV BCD3,W _BANK SILO_BANK MOV W,SILO2+1 BANK MISC_BANK MOV BCD3+1,W _BANK SILO_BANK MOV W,SILO2+2 BANK MISC_BANK MOV BCD3+2,W JMP :HERE1 :SILO3 _BANK SILO_BANK MOV W,SILO3 BANK MISC_BANK MOV BCD3,W _BANK SILO_BANK MOV W,SILO3+1 BANK MISC_BANK MOV BCD3+1,W _BANK SILO_BANK MOV W,SILO3+2 BANK MISC_BANK MOV BCD3+2,W JMP :HERE1 :SILO4 _BANK SILO_BANK MOV W,SILO4 BANK MISC_BANK MOV BCD3,W _BANK SILO_BANK MOV W,SILO4+1 BANK MISC_BANK MOV BCD3+1,W _BANK SILO_BANK MOV W,SILO4+2 BANK MISC_BANK MOV BCD3+2,W JMP :HERE1 :SILO5 _BANK SILO_BANK SETB FSR.4 MOV W,SILO5 BANK MISC_BANK MOV BCD3,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO5+1 BANK MISC_BANK MOV BCD3+1,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO5+2 BANK MISC_BANK MOV BCD3+2,W JMP :HERE1 :SILO6 _BANK SILO_BANK SETB FSR.4 MOV W,SILO6 BANK MISC_BANK MOV BCD3,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO6+1 BANK MISC_BANK MOV BCD3+1,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO6+2 BANK MISC_BANK MOV BCD3+2,W JMP :HERE1 :here1 BANK MISC_BANK ;YOU HAVE TO HAVE THIS. MOV W, bcd3+0 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 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 ORG $C00 ; Page6 TCPTransmit jmp _TCPTransmit TCPAppRxDone jmp _TCPAppRxDone TCPApp1Init jmp _TCPApp1Init ; ****************************************************************************** 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 ; ****************************************************************************** _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 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 ; ****************************************************************************** retp ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ; YOU SHOULD HAVE 199 WORDS LEFT HERE FROM ; $D3B TO $DFF ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ;#################################################### ORG $D3B ;############################################################# ;THIS IS JUMPED TO FROM THE ISR ;############################################################# TEST1 ;NOT GOING TO WORK. _BANK SILO_BANK CJE SILO,#1,S1 CJE SILO,#2,S2 CJE SILO,#3,S3 CJE SILO,#4,S4 CJE SILO,#5,S5 CJE SILO,#6,S6 CJE SILO,#7,S7 CJE SILO,#8,S8 CJE SILO,#9,S9 JMP @RXDONE1 ;IF NONE THEN JUMP BACK S1 MOV SILO1,ASCII JMP @RXDONE1 S2 MOV SILO2,ASCII JMP @RXDONE1 S3 MOV SILO3,ASCII JMP @RXDONE1 S4 MOV SILO4,ASCII JMP @RXDONE1 S5 SETB FSR.4 MOV SILO5,M_ASCII JMP @RXDONE1 S6 SETB FSR.4 MOV SILO6,M_ASCII JMP @RXDONE1 S7 SETB FSR.4 MOV SILO7,M_ASCII JMP @RXDONE1 S8 SETB FSR.4 MOV SILO8,M_ASCII JMP @RXDONE1 S9 SETB FSR.4 MOV SILO9,M_ASCII JMP @RXDONE1 TEST2 _BANK SILO_BANK CJE SILO,#1,SA1 CJE SILO,#2,SA2 CJE SILO,#3,SA3 CJE SILO,#4,SA4 CJE SILO,#5,SA5 CJE SILO,#6,SA6 CJE SILO,#7,SA7 CJE SILO,#8,SA8 CJE SILO,#9,SA9 JMP @RXDONE1 ;IF NONE THEN JUMP BACK SA1 MOV SILO1+1,ASCII JMP @RXDONE1 SA2 MOV SILO2+1,ASCII JMP @RXDONE1 SA3 MOV SILO3+1,ASCII JMP @RXDONE1 SA4 MOV SILO4+1,ASCII JMP @RXDONE1 SA5 SETB FSR.4 MOV SILO5+1,M_ASCII JMP @RXDONE1 SA6 SETB FSR.4 MOV SILO6+1,M_ASCII JMP @RXDONE1 SA7 SETB FSR.4 MOV SILO7+1,M_ASCII JMP @RXDONE1 SA8 SETB FSR.4 MOV SILO8+1,M_ASCII JMP @RXDONE1 SA9 SETB FSR.4 MOV SILO9+1,M_ASCII JMP @RXDONE1 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 ; ****************************************************************************** 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> sb flags.RX_IS_IP_BCST call UDPAppProcPktIn :outtaHere _bank IP_BANK jmp NICDumpRxFrame_7 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 SILO7W _BANK SILO_BANK SETB FSR.4 MOV W,SILO7 BANK MISC_BANK MOV BCD3,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO7+1 BANK MISC_BANK MOV BCD3+1,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO7+2 BANK MISC_BANK MOV BCD3+2,W JMP @HERE1 SILO8W _BANK SILO_BANK SETB FSR.4 MOV W,SILO8 BANK MISC_BANK MOV BCD3,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO8+1 BANK MISC_BANK MOV BCD3+1,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO8+2 BANK MISC_BANK MOV BCD3+2,W JMP @HERE1 SILO9W _BANK SILO_BANK SETB FSR.4 MOV W,SILO9 BANK MISC_BANK MOV BCD3,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO9+1 BANK MISC_BANK MOV BCD3+1,W _BANK SILO_BANK SETB FSR.4 MOV W,SILO9+2 BANK MISC_BANK MOV BCD3+2,W _BANK SILO_BANK CLR SILOINC ;CLEAR THE SILOINC SO IT CAN START OVER FROM 1 HERE1 BANK MISC_BANK ;YOU HAVE TO HAVE THIS. MOV W, bcd3+0 retp ; ;TIM FOR THIS TO BE MOVED INTO :HERE1 THEN YOU MIGHT WANT TO TRY AND MOV TO IT USING THE JMP WITH A ;MOV M,$B THIS WILL TAKE YOU TO IT I THINK. ; *********** ; *** END *** ; *********** END
file: /Techref/scenix/bindicator/silo1.1.src, 158KB, , updated: 2002/1/7 13:22, local time: 2024/8/31 18:25,
3.148.145.130:LOG IN
|
©2024 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://massmind.org/techref/scenix/bindicator/silo1.1.src"> scenix bindicator silo1</A> |
Did you find what you needed? |
Welcome to massmind.org! |
Welcome to massmind.org! |
.