; sx-x10.src ; ; SX-Stack Ethernet Evaluation Board to X10 Controller ; (c) Andrew G. Miller 2001 ; ; Wing Poon, Chris Waters, Deon Roelofse . V1.6.8 . 3/27/01 . (C) Scenix, Inc. ; SX Ethernet TCP/IP Stack. Protocols implemented: ARP, DHCP, IP/ICMP, UDP, TCP, ; HTTP. ; ************** ; *** DEVICE *** ; ************** ; Parallax -- uncomment the following 2 lines if, and only if, using Parallax's SX-Key DEVICE SX52, OSCHS2, DRT60MS FREQ 48_000_000 ; have to debug at freq != resonant freq ; SASM -- uncomment the following line if, and only if, using Advance Transdata's SX-ISD ; DEVICE SX52BD, OSCHS2, WDRT60 FFF- A60 RESET Main ID 'SX-X10' NOEXPAND NOCASE =00000000 PGM_VERSION EQU 0 =0000000A PGM_RELEASE EQU 10 ; 001.000 - Version promoted for release. October - 2001 ; 000.010 - Added push button to switch one Unit. ; 000.009 - Clean up dynamic codes X10 Unit Code. ; 000.008 - I never did like how the LED flashed... ; 000.007 - Added Hex switch to configure House Code. ; 000.006 - Minor cleanup - ready for public release. ; 000.005 - Working CM17A code. ; 000.004 - Working version of IP Default Routing. ; - Added old CM17A code, but commented out at compile time. ; 000.003 - Working version of X10 status monitoring code, and dynamic HTML values. ; 000.002 - Working version of new GET method HTTP code. ; 000.001 - Moved API coded Web server to the 1.6.8 version of Wing et al's example program. ; ****************************************************************************** ; NOTES: 1. Will work only on SX48/52 Production Release silicon! ; 2. If using SX-Key, you need SXKEY52.EXE V1.19 or greater. Pls go to ; line 150 for important information! ; 3. If using SX-ISD, you need SASM.EXE V1.45.5 and SXIDE.EXE V1.07.03 or ; greater. Pls go to line 150 for important information! ; 4. The schematics for the board that runs this code is available, pls ; contact sales@scenix.com . ; 5. There is a Java application program available to demonstrate the ; use of the UDP protocol to allow the user to control the iSX, pls ; contact sales@scenix.com . You'll need the Microsoft Java Virtual ; Machine Build 3240, or greater (installed by default with IE5). ; ****************************************************************************** ; Program Memory Usage Summary (/w DHCP): ; Page | Usage ; ----------------------------- ; 0: 000-0AF, 190-1F1 (53%) ; 1: 200-3FB (100%) ; 2: 400-5FD (100%) ; 3: 600-7FD (100%) ; 4: 800-96D (71%) ; 5: A00-B5B (68%) ; 6: C00-D38 (61%) ; 7: E00-E25 (7%) ; Data Memory Usage Summary (/w DHCP): ; Bank | Usage ; ----------------------------- ; 0: - (0%) ; 1: 0-F (100%) ; 2: 0-E (94%) ; 3: 0-F (100%) ; 4: 0-F (100%) ; 5: 0-F (100%) ; 6: 0-A (73%) ; 7: 0-C (81%) ; 8: 0-A (73%) ; 9: - (0%) ; A: - (0%) ; B: - (0%) ; C: - (0%) ; D: - (0%) ; E: - (0%) ; F: - (0%) ; This program implements an embedded web-server. The server will respond to ; HTTP requests and surfs up the specified web resource stored on an external ; serial EEPROM. The IP address of the webserver is http://10.1.1.20, if ; the DHCP option is disabled (default). In addition, the iSX can be pinged ; ("ping 10.1.1.20") using the standard PC/Unix ping utility. Finally, the iSX ; can also be controlled, using UDP, by the user, using a Java program, ; udpsx.class, available from Scenix. ; How to Setup your PC to talk with the iSX Board ; ----------------------------------------------- ; 1. Open a DOS Command Prompt Window ; 2. Type "route print" ; 3. If you see a line like the one below, skip step [4] and [5] ; Network Address Netmask Gateway Address Interface Metric ; 10.1.1.0 255.255.255.0 w.x.y.z w.x.y.z 1 ; (in the above, "w.x.y.z" is any non-zero IP address) ; 4. Find out the IP address of the PC's Ethernet Interface. Type the following ; command: "ipconfig" ; Look for the line "IP Address. . .", given under a section called "Ethernet ; adapter :". This is the Ethernet IP address of the PC. ; The IP address must not be 0.0.0.0 ; If you don't find a non-zero Ethernet IP address, follow the instructions ; Given in the section "How to give your PC a Static IP Address" and restart ; your computer. ; 5. Update the PC's routing table: Issue the following command: ; "route add 10.1.1.0 mask 255.255.255.0 " ; Be sure to substitute the IP address found in step [4] for the field ; ; 6. Power-up the iSX board and connect it to the PC using the supplied cross- ; over cable. ; 7. Ping the iSX to see if it the connection is alive: "ping 10.1.1.20" ; If you get a "Request timed out" message, the connection was unsucessful; ; try typing "arp -s 10.1.1.20 00-00-00-00-00-01 " at the ; DOS prompt and try pinging the iSX again. ; If you get a "Reply from 10.1.1.20: ..." message, the connection is alive. ; 8. Start your web-browser (IE5 works best). Type in the following URL: ; http://10.1.1.20 ; 9. If you successfully pinged the iSX board in step [7] but failed to load the ; web page in step [8], do the following: ; In IE, go to Tools->Internet Options. Click on the "Use Blank" button, then ; hit "OK". Exit and restart IE. ; In Netscape, go to Edit->Preferences. Click on the "Blank Page" radio button, ; then hit "OK". Exit and restart Netscape. ; Repeat step [8]. ; ; How to give your PC a Static IP Address (optional) ; -------------------------------------------------- ; 1. Right-click on the "Network Neighborhood" icon on the Windows Desktop. ; Select Properties. ; 2. Select the "TCP/IP -> " entry from the scroll-box. ; Click the Properties button. ; 3. Click on the "IP Address" tab. Select "Specify an IP Address". Enter ; "10.1.1.1" for the "IP Address" (This will be the Ethernet IP address of ; the PC). Enter "255.255.255.0" for the "Subnet Mask". Click on OK and ; restart the computer. ; INCLUDE "SX52.inc" ; SX52.inc ;********************************************************************************* ; 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 =00000000 TCPL_R = $00 ; Read Timer Capture register low byte =00000001 TCPH_R = $01 ; Read Timer Capture register high byte =00000002 TR2CML_R = $02 ; Read Timer R2 low byte =00000003 TR2CMH_R = $03 ; Read Timer R2 high byte =00000004 TR1CML_R = $04 ; Read Timer R1 low byte =00000005 TR1CMH_R = $05 ; Read Timer R1 high byte =00000006 TCNTB_R = $06 ; Read Timer control register B =00000007 TCNTA_R = $07 ; Read Timer control register A ; Exchange addresses ; CMP = $08 ; Exchange Comparator enable/status register with W =00000009 WKPND = $09 ; Exchange MIWU/RB Interrupts pending with W ; Port setup (read) addresses =0000000A WKED_R = $0A ; Read MIWU/RB Interrupt edge setup, 0 = falling, 1 = rising =0000000B WKEN_R = $0B ; Read MIWU/RB Interrupt edge setup, 0 = enabled, 1 = disabled =0000000C ST_R = $0C ; Read Port Schmitt Trigger setup, 0 = enabled, 1 = disabled =0000000D LVL_R = $0D ; Read Port Level setup, 0 = CMOS, 1 = TTL =0000000E PLP_R = $0E ; Read Port Pull-up setup, 0 = enabled, 1 = disabled =0000000F DIR_R = $0F ; Read Port Direction ; Timer (write) addresses =00000012 TR2CML_W = $12 ; Write Timer R2 low byte =00000013 TR2CMH_W = $13 ; Write Timer R2 high byte =00000014 TR1CML_W = $14 ; Write Timer R1 low byte =00000015 TR1CMH_W = $15 ; Write Timer R1 high byte =00000016 TCNTB_W = $16 ; Write Timer control register B =00000017 TCNTA_W = $17 ; Write Timer control register A ; Port setup (write) addresses =0000001A WKED_W = $1A ; Write MIWU/RB Interrupt edge setup, 0 = falling, 1 = rising =0000001B WKEN_W = $1B ; Write MIWU/RB Interrupt edge setup, 0 = enabled, 1 = disabled =0000001C ST_W = $1C ; Write Port Schmitt Trigger setup, 0 = enabled, 1 = disabled =0000001D LVL_W = $1D ; Write Port Level setup, 0 = CMOS, 1 = TTL =0000001E PLP_W = $1E ; Write Port Pull-up setup, 0 = enabled, 1 = disabled =0000001F DIR_W = $1F ; Write Port Direction ;********************************************************************************* ; Setup and enable RTCC interrupt, WREG register, RTCC/WDT prescaler ;********************************************************************************* =00000080 RTCC_ON = %10000000 ; Enables RTCC at address $01 (RTW hi) ; WREG at address $01 (RTW lo) by default =00000040 RTCC_ID = %01000000 ; Disables RTCC edge interrupt (RTE_IE hi) ; RTCC edge interrupt (RTE_IE lo) enabled by default =00000020 RTCC_INC_EXT = %00100000 ; Sets RTCC increment on RTCC pin transition (RTS hi) ; RTCC increment on internal instruction (RTS lo) is defalut =00000010 RTCC_FE = %00010000 ; Sets RTCC to increment on falling edge (RTE_ES hi) ; RTCC to increment on rising edge (RTE_ES lo) is default =00000008 RTCC_PS_OFF = %00001000 ; Assigns prescaler to Watchdog (PSA hi) =00000000 PS_000 = %00000000 ; RTCC = 1:2, WDT = 1:1 =00000001 PS_001 = %00000001 ; RTCC = 1:4, WDT = 1:2 =00000002 PS_010 = %00000010 ; RTCC = 1:8, WDT = 1:4 =00000003 PS_011 = %00000011 ; RTCC = 1:16, WDT = 1:8 =00000004 PS_100 = %00000100 ; RTCC = 1:32, WDT = 1:16 =00000005 PS_101 = %00000101 ; RTCC = 1:64, WDT = 1:32 =00000006 PS_110 = %00000110 ; RTCC = 1:128, WDT = 1:64 =00000007 PS_111 = %00000111 ; RTCC = 1:256, WDT = 1:128 ; *************************** ; *** CONDITIONAL DEFINES *** ; *************************** =00000000 UDP = 0 ; 1 = UDP application. =00000000 DHCP = 0 ; 1 = DHCP enabled, Requires UDP. =00000000 CREDENCE = 0 ; 1 = Credence board, 0 = Scenix board =00000001 TCP = 1 ; 1 = TCP =00000001 HTTP = 1 ; 1 = HTTP. Requires TCP. =00000001 X10 = 1 ; 1 = X10 State and Cmd parser. =00000001 CM17A = 1 ; 1 = CM17A IRQ and API =00000001 ROUTE = 1 ; 1 = IP Default Routing. =00000001 BUTTON = 1 ; 1 = X10 Unit #1 push switch. ; ***************** ; *** VARIABLES *** ; ***************** ; *** Bank 0 *** ; (Don't use this bank -- it's bad for your mental health) 000- ORG $00 000- INDF DS 1 ; *** Global *** =0000000A GLOBAL_ORG = $0A =0000000A flags EQU GLOBAL_ORG+0 ; various flags used by TCP/IP stack =0000000B arpFlags EQU GLOBAL_ORG+1 ; ARP status flags =0000000C globTemp1 EQU GLOBAL_ORG+2 ; not preserved across any function =0000000D globTemp2 EQU GLOBAL_ORG+3 ; not preserved across any function =0000000E globTemp3 EQU GLOBAL_ORG+4 ; preserved across some functions ; *** Bank 1 *** 010- ORG $10 =00000010 NIC_BANK = $ 010- nicIOAddr DS 1 ; points to currently addressed register on NIC 011- nicNextPktPtr DS 1 ; points to next packet in NIC's rx queue 012- nicCurrPktPtr DS 1 ; points to current packet in NIC's rx queue 013- nicRemoteEth0 DS 1 ; ethernet addr used for outgoing packet, overwritten by incoming packet 014- nicRemoteEth1 DS 1 ; " 015- nicRemoteEth2 DS 1 ; " 016- nicRemoteEth3 DS 1 ; " 017- nicRemoteEth4 DS 1 ; " 018- nicRemoteEth5 DS 1 ; " 019- nicCopySrcMSB DS 1 ; used by NICBufferCopy() 01A- nicCopySrcLSB DS 1 ; " 01B- nicCopyDestMSB DS 1 ; " 01C- nicCopyDestLSB DS 1 ; " 01D- nicCopyLenMSB DS 1 ; " 01E- nicCopyLenLSB DS 1 ; " 01F- nicCopyTemp DS 1 ; " ; *** Bank 2 *** 020- ORG $20 =00000020 IP_BANK = $ ; make sure IP_BANK[7] = NIC_BANK[7] 020- remoteIP3 DS 1 ; IP addr used for outgoing packet, overwritten by incoming packet 021- remoteIP2 DS 1 ; " 022- remoteIP1 DS 1 ; " 023- remoteIP0 DS 1 ; " 024- myIP3 DS 1 ; filter value for incoming IP packets, also used in outgoing packet 025- myIP2 DS 1 ; " 026- myIP1 DS 1 ; " 027- myIP0 DS 1 ; " 028- ipCheckSumMSB DS 1 ; IP 029- ipCheckSumLSB DS 1 ; " 02A- ipLengthMSB DS 1 ; IP 02B- ipLengthLSB DS 1 ; " 02C- ipProtocol DS 1 ; IP 02D- ipIdentMSB DS 1 ; IP , incremented each outgoing packet 02E- ipIdentLSB DS 1 ; " ; *** Bank 3 *** 030- ORG $30 IF UDP UDP_BANK = $ ; make sure UDP_BANK[7] = NIC_BANK[7] udpRxSrcPortMSB DS 1 udpRxSrcPortLSB DS 1 udpRxDestPortMSB DS 1 ; filter value for incoming UDP packets udpRxDestPortLSB DS 1 ; " udpRxDataLenMSB DS 1 ; length of 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 field of outgoing UDP packet udpTxDataLenLSB DS 1 ; " ENDIF ; UDP IF DHCP DHCP_BANK = $ dhcpServerId3 DS 1 ; DHCP = IP addr of DHCP server dhcpServerId2 DS 1 ; " dhcpServerId1 DS 1 ; " dhcpServerId0 DS 1 ; " ENDIF ; DHCP ; *** Bank 4 *** 040- ORG $40 =00000040 TCP_BANK = $ ; make sure TCP_BANK[7] = NIC_BANK[7] 040- tcpState DS 1 ; state-machine state 041- tcpTmpSeq4 DS 1 ; TMP.SEQ. 1=LSB, 4=MSB 042- tcpTmpSeq3 DS 1 ; temporary information from the received packet 043- tcpTmpSeq2 DS 1 044- tcpTmpSeq1 DS 1 045- tcpTmpAck4 DS 1 ; TMP.ACK 046- tcpTmpAck3 DS 1 ; temporary information from the received packet 047- tcpTmpAck2 DS 1 048- tcpTmpAck1 DS 1 049- tcpUnAckMSB DS 1 ; number of unacknowledged bytes 04A- tcpUnAckLSB DS 1 ; " 04B- tcpRxFlags DS 1 ; copy of the received flags field 04C- tcpCheckSumMSB DS 1 04D- tcpCheckSumLSB DS 1 04E- tcpLengthMSB DS 1 04F- tcpLengthLSB DS 1 =00000041 tcpTmpMSB = tcpTmpSeq4 =00000042 tcpTmpLSB = tcpTmpSeq3 =00000049 tcpAppTxBytesMSB = tcpUnAckMSB ; number of bytes app wants to transmit =0000004A tcpAppTxBytesLSB = tcpUnAckLSB ; " =0000004E tcpAppRxBytesMSB = tcpLengthMSB ; number of bytes app will be receiving =0000004F tcpAppRxBytesLSB = tcpLengthLSB ; " ; *** Bank 5 *** 050- ORG $50 =00000050 TCB_BANK = $ ; make sure TCB_BANK[7] = NIC_BANK[7] ; The ordering of these variables is significant. It is the same as the TCP ; header. This simpifies the send-packet code 050- tcbLocalPortMSB DS 1 ; source port 051- tcbLocalPortLSB DS 1 ; " 052- tcbRemotePortMSB DS 1 ; destination port 053- tcbRemotePortLSB DS 1 ; " 054- tcbSndUna4 DS 1 ; SND.UNA: oldest unacknowledged byte 055- tcbSndUna3 DS 1 ; " 056- tcbSndUna2 DS 1 ; " 057- tcbSndUna1 DS 1 ; " 058- tcbRcvNxt4 DS 1 ; RCV.NXT: next byte to receive 059- tcbRcvNxt3 DS 1 ; " 05A- tcbRcvNxt2 DS 1 ; " 05B- tcbRcvNxt1 DS 1 ; " 05C- tcbOffset DS 1 ; length of the TCP options 05D- tcbFlags DS 1 ; flags field 05E- tcbSendWinMSB DS 1 ; send window 05F- tcbSendWinLSB DS 1 ; " =00000060 TCB_END = $ ; *** Bank 6 *** 060- ORG $60 =00000060 ARP_BANK = $ ; make sure ARP_BANK[7] = NIC_BANK[7] ; order of fields is important to match ARP packet. 060- host1Eth0 DS 1 ; remote host1 Ethernet address 061- host1Eth1 DS 1 ; " 062- host1Eth2 DS 1 ; " 063- host1Eth3 DS 1 ; " 064- host1Eth4 DS 1 ; " 065- host1Eth5 DS 1 ; " 066- host1IP3 DS 1 ; remote host1 IP address 067- host1IP2 DS 1 ; " 068- host1IP1 DS 1 ; " 069- host1IP0 DS 1 ; " 06A- stPktTxBufStart DS 1 ; start address of stalled packet in NIC tx buffer 06B- ARPRequestIP3 DS 1 ; IP address to search for ether addr. 06C- ARPRequestIP2 DS 1 06D- ARPRequestIP1 DS 1 06E- ARPRequestIP0 DS 1 ; *** Bank 7 *** 070- ORG $70 =00000070 TIMER_BANK = $ ; make sure TIMER_BANK[7] = NIC_BANK[7] 070- baseTimer DS 1 ; lowest/common cog in timer chain 071- arpTimerMSB DS 1 ; ARP-timer count 072- arpTimerLSB DS 1 ; " 073- tcpTimerMSB DS 1 ; TCP-timer count 074- tcpTimerLSB DS 1 ; " 075- connTimerMSB DS 1 ; Connection-timer count 076- connTimerLSB DS 1 ; " =00000077 HTTP_BANK = $ ; make sure HTTP_BANK[7] = NIC_BANK[7] 077- httpParseState DS 1 ; state of the HTTP header parser ; States for parsing HTTP headers =00000000 HTTP_PARSE_IDLE = 0 =00000000 HTTP_PARSE_METHOD = 0 =00000001 HTTP_PARSE_URI = 1 IF X10 =00000002 HTTP_PARSE_HOUSE = 2 =00000003 HTTP_PARSE_UNIT = 3 =00000004 HTTP_PARSE_EQUALS = 4 =00000005 HTTP_PARSE_CMD = 5 ENDIF ; X10 =00000006 HTTP_PARSE_EOL = 6 =00000007 HTTP_PARSE_SENDING = 7 =00000008 HTTP_PARSE_SENTLAST = 8 =00000008 HTTP_PARSE_CLOSING = 8 =00000009 HTTP_PARSE_CLOSED = 9 078- httpURIHash DS 1 ; hash of the current URI =0000002F HTTP_URI_HASH_ROOT = '/' =0000002F HTTP_URI_HASH_ROOT_TOO = ( ( '/' + 'a' + 'b' + 'c' + 'c' + '.' + 'h' + 't' + 'm') & $FF ) =00000032 HTTP_URI_HASH_DEFAULT = ( ( '/' + 'r' + 'e' + 'm' + 'o' + 't' + 'e' + '.' + 'h' + 't' + 'm' ) & $FF ) ; /index.htm =0000003E HTTP_URI_HASH_404 = ( ( '/' + '4' + '0' + '4' + '.' + 'h' + 't' + 'm' ) & $FF ) ; /404.htm 079- httpExtHash DS 1 ; hash of URI file type extension. =00000049 HTTP_EXT_HASH_DEFAULT = ( ( 'h' + 't' + 'm' ) & $FF ) =00000049 HTTP_EXT_HASH_404 = ( ( 'h' + 't' + 'm' ) & $FF ) =00000036 HTTP_EXT_HASH_GIF = ( ( 'g' + 'i' + 'f' ) & $FF ) =00000041 HTTP_EXT_HASH_JPG = ( ( 'j' + 'p' + 'g' ) & $FF ) =0000003A HTTP_EXT_HASH_PDF = ( ( 'p' + 'd' + 'f' ) & $FF ) 07A- httpPageCount DS 1 ; num times page has been accessed. ; *** HTTP Constants *** =00001F90 HTTP_PORT = 8080 =0000001F HTTP_PORT_MSB = (HTTP_PORT / 256) ; port number for HTTP server. =00000090 HTTP_PORT_LSB = (HTTP_PORT & 255) ; " =00000578 HTTP_SEG_SIZE = 1400 =00000081 URI1 = $81 ; hash of "resource.htm" =00000054 URI2 = $54 ; hash of "temperature.htm" =0000007B EEPROM_BANK = $ ; make sure EEPROM_BANK[7] = NIC_BANK[7] 07B- e2AddrMSB DS 1 ; address in EEPROM to start reading from 07C- e2AddrLSB DS 1 ; " 07D- e2FileLenMSB DS 1 ; length of the file being read 07E- e2FileLenLSB DS 1 ; " ; *** Bank 8 *** 080- ORG $80 =00000080 MISC_BANK = $ 080- buttonCounter DS 1 ; de-bounce counter for push switch =00000005 BUTTON_PORT = RA =00000007 BUTTON = 7 =00000705 BUTTON_PIN = BUTTON_PORT.BUTTON =00000000 BUTTON_UNIT = 0 ; Which X10 unit switches on/off. 081- bcd3 DS 3 ; buffer for binary-to-ascii conversion =00000084 ADC_BANK = $ ; must be same bank as bcd3 084- adc DS 1 ; averaged ADC value 085- adcAcc DS 1 086- adcCount DS 1 087- adcMSB DS 1 ; for averaging 256 samples 088- adcLSB DS 1 ; " 089- adcSampleCount DS 1 ; count number of averaged samples ; *** Bank 9 *** 090- ORG $90 ; *** Bank A *** 0A0- ORG $A0 ; *** Bank B *** 0B0- ORG $B0 ; *** Bank C *** 0C0- ORG $C0 ; X10 begin IF X10 ; ; Storage defines for X10 Home Automation ; =000000C0 X10_BANK = $ 0C0- x10HouseCode DS 1 ; values 0-15 = codes 'A'-'P' ; Record changes to this House code. =00000009 X10_HOUSE_PORT = RE ; Hex encoded switch on Pins 0-3, to common GND. 0C1- x10House DS 1 ; values 0-15 = codes 'A'-'P' 0C2- x10Unit DS 1 ; values 0-15 = codes 1-16 0C3- x10Cmd DS 1 =00000001 X10_CMD_ON = 1 =00000002 X10_CMD_OFF = 2 =00000003 X10_CMD_DIM = 3 =00000004 X10_CMD_BRIGHT = 4 =00000005 X10_CMD_ALL_ON = 5 =00000006 X10_CMD_ALL_OFF = 6 =00000007 X10_CMD_LIGHTS_ON = 7 =00000008 X10_CMD_LIGHTS_OFF = 8 ENDIF ; X10 ; X10 end ; CM17A begin IF CM17A ; ; Storage and defines for CM17A virtual peripheral ; =000000C4 CM17A_BANK = $ =00000005 CM17A_PORT = RA ; DCE interface wired ... =00000000 CM17A_PIN_DTR = 0 ; out ...to DTE's RTS =00000002 CM17A_PIN_RTS = 2 ; out ...to DTE's DTR ; Remember that the logic is inverted too. =000000D5 CM17A_HEADER1 = %11010101 =000000AA CM17A_HEADER2 = %10101010 0C4- cm17aX10Data1 DS 1 ; Actual data bytes to send. 0C5- cm17aX10Data2 DS 1 =000000AD CM17A_FOOTER = %10101101 0C6- cm17aBitData DS 1 ; Data to shift out 0C7- cm17aBitCount DS 1 ; Count of Bits to send 0C8- cm17aBitTimer DS 1 ; Counter for minimum signal rate =000000FA CM17A_BIT_TIME = 250 ; 1000/4 = 1.0ms =000000FF CM17A_RESET_TIME = 255 ; max ENDIF ; CM17A ; CM17A end ; *** Bank D *** 0D0- ORG $D0 ; X10 begin IF X10 =000000D0 X10_HOUSE_BANK = $ 0D0- x10HouseState DS 16 ENDIF ; X10 end ; *** Bank E *** 0E0- ORG $E0 ; *** Bank F *** 0F0- ORG $F0 ; *************** ; *** EQUATES *** ; *************** =000000C8 INT_PERIOD = 200 ; RTCC interrupt periodicity (345kHz) ; change this if you're not clocking ; the SX at 50MHz ; *** Pin Definitions *** IF CREDENCE RA_DIR = %11110011 RA_OUT = %00000000 RA_LVL = %11111111 RA_PLP = %11111111 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 = %00000010 RD_OUT = %00000011 RD_LVL = %11111111 RD_PLP = %11111100 RE_DIR = %00000000 RE_OUT = %00000000 RE_LVL = %11111111 RE_PLP = %11111111 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 = rd E2SCL = 0 E2SDA = 1 E2SCL_PIN = E2_PORT.E2SCL E2SDA_PIN = E2_PORT.E2SDA LED_PORT = re LED = 0 LED_PIN = LED_PORT.LED ELSE ; CREDENCE =000000AA RA_DIR = %10101010 =00000070 RA_OUT = %01110000 =000000FF RA_LVL = %11111111 =0000007F RA_PLP = %01111111 =00000080 RB_DIR = %10000000 =00000060 RB_OUT = %01100000 =000000FF RB_LVL = %11111111 =0000007F RB_PLP = %01111111 =000000FF RC_DIR = %11111111 =00000000 RC_OUT = %00000000 =000000FF RC_LVL = %11111111 =000000FF RC_PLP = %11111111 =000000F0 RD_DIR = %11110000 =00000000 RD_OUT = %00000000 =000000FF RD_LVL = %11111111 =00000000 RD_PLP = %00000000 =0000007F RE_DIR = %01111111 =00000000 RE_OUT = %00000000 =0000003F RE_LVL = %00111111 =000000C0 RE_PLP = %11000000 =00000007 NIC_DATA_PORT = RC =00000006 NIC_CTRL_PORT = RB =00000506 IOWB_PIN = NIC_CTRL_PORT.5 =00000606 IORB_PIN = NIC_CTRL_PORT.6 =00000706 IOCH_PIN = NIC_CTRL_PORT.7 =00000005 E2_PORT = RA =00000004 E2SCL = 4 =00000005 E2SDA = 5 =00000405 E2SCL_PIN = E2_PORT.E2SCL =00000505 E2SDA_PIN = E2_PORT.E2SDA =00000005 LED_PORT = RA =00000006 LED = 6 =00000605 LED_PIN = LED_PORT.LED ENDIF ; *** flags *** =00000000 RX_IS_ARP = 0 ; incoming packet is an ARP packet =00000001 RX_IS_ICMP = 1 ; incoming packet is an ICMP packet =00000002 RX_IS_UDP = 2 ; incoming packet is a UDP packet =00000003 RX_IS_TCP = 3 ; incoming packet is a TCP packet =00000004 RX_IS_IP_BCST = 4 ; incoming packet is an IP Broadcast packet =00000005 GOT_DHCP_OFFER = 5 ; received DHCP IP address offer =00000006 GOT_IP_ADDR = 6 ; received an IP address assignment (recv'ed DHCP ACK) =00000007 IP_CHKSUM_LSB = 7 ; next byte to accumulate IP checksum is LSB =00000005 TCP_CHKSUM_LSB = 5 ; next byte to accumulate TCP checksum is LSB ; *** arpFlags *** =00000000 ARP_REQ_SENT = 0 ; indicates that an ARP request has been sent =00000001 ARP_RSP_RCVD = 1 ; indicates that an ARP response has been received =00000002 ARP_STL_TX = 2 ; indicates that the stalled packet is to be transmitted =00000003 ARP_BYPASS = 3 ; indicates that the outgoing packet should not be checked ; *** NIC Constants *** =00000040 RXBUF_START = $40 ; 4608 byte receive buffer (3 max-size packets) =00000053 RXBUF_END = $53 ; " =00000053 TXBUF1_START = $53 ; 1536 byte transmit buffer for ICMP/UDP =00000059 TXBUF2_START = $59 ; 1536 byte transmit buffer for TCP =0000005F TXBUF3_START = $5F ; 256 byte transmit buffer for ARP ; *** Ethernet Constants *** =00000000 SX_ETH_ADDR0 = 0 ; SX's Ethernet Phy MAC Address =00000001 SX_ETH_ADDR1 = 1 ; " =00000002 SX_ETH_ADDR2 = 2 ; " =00000003 SX_ETH_ADDR3 = 3 ; " =00000004 SX_ETH_ADDR4 = 4 ; " =00000005 SX_ETH_ADDR5 = 5 ; " ; *** ARP Constants *** =00000005 ARP_TIMEOUT = 5 ; ARP response timeout period. Must be smaller than other timeouts! ; *** IP Constants *** =0000000A SX_IP_ADDR3 = 10 ; SX's static IP address (if DHCP disabled) =00000000 SX_IP_ADDR2 = 0 ; " =00000000 SX_IP_ADDR1 = 0 ; " =00000001 SX_IP_ADDR0 = 1 ; " IF ROUTE =000000FF SX_IP_NETMASK3 = 255 ; SX's local netmask. =000000FF SX_IP_NETMASK2 = 255 =000000FF SX_IP_NETMASK1 = 255 =00000000 SX_IP_NETMASK0 = 0 =0000000A SX_IP_ROUTER3 = 10 ; SX's Default IP Router. =00000000 SX_IP_ROUTER2 = 0 =00000000 SX_IP_ROUTER1 = 0 =00000002 SX_IP_ROUTER0 = 2 ENDIF ; ROUTE =00000020 IP_TTL = 32 ; *** UDP Constants *** IF UDP UDP_RX_DEST_MSB = $04 ; user UDP RX Port: 1025 UDP_RX_DEST_LSB = $01 ; " ENDIF ; UDP ; *** TCP Constants *** ; TCP state-machine states (numbering order is signifcant) =00000000 TCP_ST_CLOSED = 0 =00000001 TCP_ST_LISTEN = 1 =00000002 TCP_ST_SYNSENT = 2 =00000003 TCP_ST_SYNRCVED = 3 =00000004 TCP_ST_ESTABED = 4 =00000005 TCP_ST_FINWAIT1 = 5 =00000006 TCP_ST_FINWAIT2 = 6 =00000007 TCP_ST_CLOSEWAIT = 7 =00000008 TCP_ST_CLOSING = 8 =00000009 TCP_ST_LASTACK = 9 =0000000A TCP_ST_TIMEWAIT = 10 ; Bit positions in the TCP byte. =00000004 TCP_FLAG_ACK = 4 =00000003 TCP_FLAG_PSH = 3 =00000002 TCP_FLAG_RST = 2 =00000001 TCP_FLAG_SYN = 1 =00000000 TCP_FLAG_FIN = 0 ; TCP Options =00000000 TCP_OPTION_END = 0 =00000001 TCP_OPTION_NOP = 1 =00000002 TCP_OPTION_MSS = 2 ; max segment size =00000005 TCP_HDR_LENGTH = 5 ; normal TCP header length. =000000F0 TCP_OFFSET_MASK = $F0 =00000578 TCP_WINDOW_SIZE = 1400 ; max # of data bytes we will accept =00000578 TCP_SEG_SIZE = 1400 ; max # of data bytes TCP will transmit per segment =00000008 TCP_RESTART_EXP = 8 ; TCP re-transmission timeout period =00000050 TCP_CONN_EXP = 80 ; TCP connection timeout period ; *** EEPROM Constants *** =000000A1 E2_CMD_RD = $A1 ; most-significant 7-bits is the I2C slave addr =000000A0 E2_CMD_WR = $A0 ; most-significant 7-bits is the I2C slave addr =00000020 E2_SDA_MASK = (1 << E2SDA) ; a '1' in the SDA bit, '0' everywhere else IF CREDENCE E2_DDR_SDA_IN = (RD_DIR | E2_SDA_MASK) ; direction of SDA port when SDA is input E2_DDR_SDA_OUT = (RD_DIR & (~E2_SDA_MASK)) ; direction of SDA port when SDA is output ELSE =000000AA E2_DDR_SDA_IN = (RA_DIR | E2_SDA_MASK) ; direction of SDA port when SDA is input =0000008A E2_DDR_SDA_OUT = (RA_DIR & (~E2_SDA_MASK)) ; direction of SDA port when SDA is output ENDIF ; *** ADC Constants *** =00000009 ADC_PORT = RE =00000007 ADC_OUT = 7 =00000006 ADC_IN = 6 =00000709 ADC_OUT_PIN = ADC_PORT.ADC_OUT =00000609 ADC_IN_PIN = ADC_PORT.ADC_IN ; ************** ; *** 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 software. 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 software. 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 _retw_check MACRO 0 if (( $ & $1ff ) > $101 ) ERROR 'RETW data table not at top of code page.' ENDIF ENDM ; *********** ; *** ISR *** ; *********** 000- ORG 0 ; Page0 000- ISR 000- Timer ; implement various SW timers ; lowest-common-denominator timer 000- _bank TIMER_BANK 000- 01F 001- 4E4 002- 3F0 incsz baseTimer 003- A0D jmp :timerEnd 004- :tcpTimer ; TCP-timer (used for TCP re-transmission timeouts) 004- 3F4 incsz tcpTimerLSB 005- A07 jmp :connTimer 006- 2B3 inc tcpTimerMSB 007- :connTimer ; Connection-timer (used for TCP connection timeouts) 007- 3F6 incsz connTimerLSB 008- A0A jmp :arpTimer 009- 2B5 inc connTimerMSB 00A- :arpTimer ; ARP-timer (used for ARP response timeouts) 00A- 3F2 incsz arpTimerLSB 00B- A0D jmp :timerEnd 00C- 2B1 inc arpTimerMSB 00D- :timerEnd 00D- ADCTempSensor ; SW A-to-D for measuring current board temperature to be then ; displayed on a dynamic web page ; ADC(out) = !ADC(in) (balancing the yin and the yang) 00D- 209 mov w, ADC_PORT 00E- 7C1 sb wreg.ADC_IN 00F- 5E9 setb ADC_OUT_PIN 010- 6C1 snb wreg.ADC_IN 011- 4E9 clrb ADC_OUT_PIN ; decision time 012- _bank ADC_BANK 012- 018 013- 5E4 014- 7E1 sb wreg.ADC_OUT 015- 3F5 incsz adcAcc 016- 2B5 inc adcAcc 017- 0F5 dec adcAcc 018- 2B6 inc adcCount 019- 743 A26 jnz :adcTempSensorEnd ; accumulate for averaging (256 samples) 01B- 215 mov w, adcAcc 01C- 075 clr adcAcc 01D- 1F8 add adcLSB, w 01E- 603 snc 01F- 2B7 inc adcMSB ; check if averaging is done 020- 3F9 incsz adcSampleCount 021- A26 jmp :adcTempSensorEnd ; averaging done -- save results 022- 217 034 mov adc, adcMSB ; divide by 256 (clever huh?) 024- 077 clr adcMSB 025- 078 clr adcLSB 026- :adcTempSensorEnd ; ****************************************************************************** 026- :LedBlinker ; blinks auxilliary LED, but don't intefere if E2 access in ; in progress because LED and E2 may share same port 026- _bank HTTP_BANK 026- 01F 027- 4E4 028- 237 test httpParseState 029- 743 A33 jnz :ledBlinkerEnd 02B- _bank TIMER_BANK 02B- 01F 02C- 4E4 02D- 213 mov w, tcpTimerMSB 02E- E07 and w, #%00000111 02F- 743 sz 030- 5C5 setb LED_PORT.LED 031- 643 snz 032- 4C5 clrb LED_PORT.LED 033- :ledBlinkerEnd IF BUTTON ; ****************************************************************************** 033- :button _bank MISC_BANK ; debounce button press. 033- 018 034- 5E4 035- 6E5 A3B jb BUTTON_PIN, :buttonOff 037- 290 :buttonOn mov w, ++buttonCounter 038- 743 sz 039- 2B0 inc buttonCounter 03A- A3E jmp :buttonEnd 03B- 230 :buttonOff test buttonCounter 03C- 743 sz 03D- 0F0 dec buttonCounter 03E- :buttonEnd ENDIF; BUTTON IF CM17A ; ****************************************************************************** ; CM17A Interupt Service routine ; ****************************************************************************** 03E- :cm17aISR 03E- _bank CM17A_BANK 03E- 01C 03F- 5E4 040- C00 098 cje cm17aBitTimer, #0, :morebits ; anything going on? 042- 643 A4C 044- C7D 098 cjne cm17aBitTimer, #(CM17A_BIT_TIME/2), :countdown ; mid-way? 046- 743 A4A 048- 405 clrb CM17A_PORT.CM17A_PIN_DTR ; both lines back up. 049- 445 clrb CM17A_PORT.CM17A_PIN_RTS ; go idle. 04A- 0F8 :countdown dec cm17aBitTimer ; count down bit time. 04B- A59 jmp :cm17aExit 04C- C00 097 :moreBits cje cm17aBitCount, #0, :cm17aExit ; more to send? 04E- 643 A59 050- 0F7 dec cm17aBitCount 051- 403 clc 052- 376 rl cm17aBitData ; next bit. 053- 703 sc 054- 545 setb CM17A_PORT.CM17A_PIN_RTS ; set RTS line low. 055- 603 snc 056- 505 setb CM17A_PORT.CM17A_PIN_DTR ; set DTR line low. 057- CFA 038 mov cm17aBitTimer, #CM17A_BIT_TIME ; Set bit timer. 059- :cm17aExit ; ****************************************************************************** ENDIF ; CM17A 059- C38 mov w, #-INT_PERIOD 05A- 00F retiw ; ******************** ; *** MAIN PROGRAM *** ; ******************** 05B- B00 Init jmp _Init 05C- B44 ARPInit jmp _ARPInit 05D- B4C TCPIPInit jmp _TCPIPInit 05E- B5F E2Init jmp _E2Init 05F- B6A StartupDelay jmp _StartupDelay 060- Main 060- 010 95B call @Init ; DHCP Dynamic IP Address solicitation IF DHCP ; initialize UDP receive port for DHCP _bank UDP_BANK mov udpRxDestPortMSB, #0 ; DHCP(BOOTP) Client mov udpRxDestPortLSB, #68 ; ; send DHCPDISCOVER message to find DHCP server(s) call @DHCPDISCOVERSend ; wait for DHCPOFFER :dhcpWaitOffer call @NICWaitRxFrame call @CheckIPDatagram jnb flags.RX_IS_UDP, :dhcpWaitOffer call @UDPProcPktIn sb flags.GOT_DHCP_OFFER jmp :dhcpWaitOffer ; send DHCPREQUEST message call @DHCPREQUESTSend ; wait for DHCPACK :dhcpGotOffer call @NICWaitRxFrame call @CheckIPDatagram jnb flags.RX_IS_UDP, :dhcpGotOffer call @UDPProcPktIn sb flags.GOT_IP_ADDR jmp :dhcpGotOffer :dhcpGotAck ; hallelujah! ENDIF IF UDP call @UDPAppInit ENDIF ; UDP ; main program loop 062- 011 991 :mainLoop call @NICCheckRxFrame 064- 643 A7B jz :noRxFrame 066- 011 9AB call @NICWaitRxFrame ; no waiting cus we've already checked 068- 012 980 call @ARPCheckIfIs ; check and process if ARP 06A- 60A A62 jb flags.RX_IS_ARP, :mainLoop 06C- 012 903 call @CheckIPDatagram ; not ARP, check if IP 06E- 62A A75 jb flags.RX_IS_ICMP, :icmp IF UDP jb flags.RX_IS_UDP, :udp ENDIF ; UDP 070- 66A A78 jb flags.RX_IS_TCP, :tcp 072- 011 9DB call @NICDumpRxFrame ; not something we recognize, so dump it 074- A62 jmp :mainLoop 075- 013 901 :icmp call @ICMPProcPktIn ; process incoming ICMP packet 077- A62 jmp :mainLoop IF UDP :udp call @UDPProcPktIn ; process incoming UDP packet jmp :mainLoop ENDIF ; UDP 078- 013 9F6 :tcp call @TCPProcPktIn ; process incoming TCP packet 07A- A62 jmp :mainLoop 07B- 012 902 :noRxFrame call @ARPSendStPacket ; send ARP stalled packets if any IF BUTTON 07D- 99F call buttonCheck ; debounced switch press. ENDIF ; BUTTON 07E- _bank TCP_BANK 07E- 01C 07F- 4E4 080- C00 090 cje TCPState, #TCP_ST_CLOSED, :tcpClosed 082- 643 A91 084- C01 090 cje TCPState, #TCP_ST_LISTEN, :tcpListen 086- 643 A94 088- 01F bank TIMER_BANK 089- C50 095 cjae connTimerMSB, #TCP_CONN_EXP, :resetTCP 08B- 603 A97 08D- 70B sb arpFlags.ARP_REQ_SENT ; do not allow new tx if waiting for ARP response 08E- 013 900 call @TCPTransmit ; check if app has anything to transmit 090- A62 jmp :mainLoop 091- 015 901 :tcpClosed call @TCPAppInit 093- A62 jmp :mainLoop 094- 01F :tcpListen bank TIMER_BANK 095- 075 clr connTimerMSB 096- A62 jmp :mainLoop 097- :resetTCP ; reset hung TCP connection 097- 01C bank TCP_BANK 098- 079 clr tcpUnAckMSB 099- 07A clr tcpUnAckLSB 09A- C00 030 mov tcpState, #TCP_ST_CLOSED 09C- 01F bank HTTP_BANK 09D- 077 clr httpParseState 09E- A62 jmp :mainLoop IF BUTTON ; ****************************************************************************** 09F- buttonCheck 09F- _bank MISC_BANK ; debounce button press. 09F- 018 0A0- 5E4 0A1- CFF 090 cse buttonCounter, #$FF 0A3- 743 0A4- 00D retp 0A5- :buttonPress IF X10 0A5- _bank X10_HOUSE_BANK 0A5- 01D 0A6- 5E4 0A7- 210 mov w, ( x10HouseState + BUTTON_UNIT ) 0A8- 643 AAC jz :buttonON 0AA- C02 :buttonOff mov w, #X10_CMD_OFF 0AB- 602 skip 0AC- C01 :buttonOn mov w, #X10_CMD_ON 0AD- :buttonSend _bank X10_BANK 0AD- 01C 0AE- 5E4 0AF- 033 mov x10Cmd, w 0B0- 210 031 mov x10house, x10HouseCode 0B2- C00 032 mov x10Unit, #BUTTON_UNIT 0B4- 017 901 call @X10Send ENDIF ; X10 0B6- _bank MISC_BANK ; debounce button press. 0B6- 018 0B7- 5E4 0B8- 230 :buttonWait test buttonCounter ; wait for un-pressed key. 0B9- 743 AB8 jnz :buttonWait 0BB- 00D retp ; ****************************************************************************** ENDIF ; BUTTON ; ******************* ; *** SUBROUTINES *** ; ******************* 100- ORG $100 ; Page0 ; ****************************************************************************** 100- _Init ; Main program initialization code ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 100- _mode LVL_W 100- C1D 101- 043 102- CFF 005 mov !ra, #RA_LVL 104- CFF 006 mov !rb, #RB_LVL 106- CFF 007 mov !rc, #RC_LVL 108- CFF 008 mov !rd, #RD_LVL 10A- C3F 009 mov !re, #RE_LVL 10C- _mode PLP_W 10C- C1E 10D- 043 10E- C7F 005 mov !ra, #RA_PLP 110- C7F 006 mov !rb, #RB_PLP 112- CFF 007 mov !rc, #RC_PLP 114- C00 008 mov !rd, #RD_PLP 116- CC0 009 mov !re, #RE_PLP 118- _mode DIR_W 118- C1F 119- 043 11A- CAA 005 mov !ra, #RA_DIR 11C- C80 006 mov !rb, #RB_DIR 11E- CFF 007 mov !rc, #RC_DIR 120- CF0 008 mov !rd, #RD_DIR 122- C7F 009 mov !re, #RE_DIR 124- C70 025 mov ra, #RA_OUT 126- C60 026 mov rb, #RB_OUT 128- C00 027 mov rc, #RC_OUT 12A- C00 028 mov rd, #RD_OUT 12C- C00 029 mov re, #RE_OUT 12E- 06A clr flags 12F- 011 90A call @NICInit 131- 010 95C call @ARPInit 133- 010 95D call @TCPIPInit 135- 010 95E call @E2Init IF X10 137- 017 900 call @X10Init ENDIF ; X10 IF CM17A 139- 017 963 call @cm17aInit ENDIF ; CM17A IF HTTP 13B- _bank HTTP_BANK 13B- 01F 13C- 4E4 13D- 07A clr httpPageCount ; clear page counter (dynamic data) ENDIF ; HTTP IF BUTTON 13E- _bank MISC_BANK ; debounce button press. 13E- 018 13F- 5E4 140- 070 clr buttonCounter ENDIF ; BUTTON 141- C08 mov w, #(RTCC_PS_OFF) ; setup option register 142- 002 mov !option, w 143- 00D retp ; ****************************************************************************** 144- _ARPInit ; ARP initialization code ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 144- 06B clr arpFlags 145- _bank ARP_BANK 145- 01E 146- 4E4 147- 079 clr host1IP0 ; clear the cache 148- 078 clr host1IP1 ; " 149- 077 clr host1IP2 ; " 14A- 076 clr host1IP3 ; " 14B- 00D retp ; ****************************************************************************** 14C- _TCPIPInit ; TCP/IP stack initialization code ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 14C- _bank IP_BANK 14C- 01A 14D- 4E4 IF DHCP clr myIP3 clr myIP2 clr myIP1 clr myIP0 ELSE ; initialize SX's IP addr 14E- 5CA setb flags.GOT_IP_ADDR 14F- C0A 034 mov myIP3, #SX_IP_ADDR3 151- C00 035 mov myIP2, #SX_IP_ADDR2 153- C00 036 mov myIP1, #SX_IP_ADDR1 155- C01 037 mov myIP0, #SX_IP_ADDR0 ENDIF ; initialize IP Identifier sequence number 157- 07D clr ipIdentMSB 158- 07E clr ipIdentLSB ; initialise the TCP variables 159- 01C bank TCP_BANK 15A- 079 clr tcpUnAckMSB 15B- 07A clr tcpUnAckLSB 15C- C00 030 mov tcpState, #TCP_ST_CLOSED 15E- 00D retp ; ****************************************************************************** 15F- _E2Init ; EEPROM initialization code ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; get the I2C device into a known state 15F- 016 90C call @E2SDAInput 161- 485 :e2InitLoop clrb E2SCL_PIN 162- 016 908 call @E2Delay1300ns 164- 585 setb E2SCL_PIN 165- 016 904 call @E2Delay900ns 167- 7A5 B61 jnb E2SDA_PIN, :e2InitLoop 169- 00D retp ; ****************************************************************************** 16A- _StartupDelay ; Delay for ?ms @ 50MHz ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 16A- C0A 02D mov globTemp2, #10 16C- 06C :loop3 clr globTemp1 16D- 040 :loop2 clr w 16E- 2E1 :loop1 decsz wreg 16F- B6E jmp :loop1 170- 2EC decsz globTemp1 171- B6D jmp :loop2 172- 2ED decsz globTemp2 173- B6C jmp :loop3 174- 00D retp 200- ORG $200 ; Page1 200- B04 NICSendTxFrame jmp _NICSendTxFrame 201- B30 NICBufCopy jmp _NICBufCopy 202- B71 NICBufWrite jmp _NICBufWrite 203- B89 NICBufRead jmp _NICBufRead 204- B9F NICBufIPAddrWr jmp _NICBufIPAddrWr 205- BB6 NICWriteSrcIP jmp _NICWriteSrcIP 206- BC8 NICWriteDestIP jmp _NICWriteDestIP 207- BD4 NICWriteSrcEth jmp _NICWriteSrcEth 208- BE0 NICWriteDestEth jmp _NICWriteDestEth 209- BEC NICDMAInit jmp _NICDMAInit ; ****************************************************************************** 20A- NICInit ; Initializes and configures Realtek RTL8019AS NIC ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 20A- _bank NIC_BANK 20A- 019 20B- 4E4 20C- 010 95F call @StartupDelay ; give it a little time to come out of POR 20E- C1F 030 mov nicIOAddr, #$1F ; write to reset port 210- 953 call NICWrite 211- 010 95F call @StartupDelay ; give it a little time to reset ; --- Page3 Registers --- 213- 070 clr nicIOAddr ; CR 214- CC1 mov w, #%11000001 ; Page3, Stop 215- 953 call NICWrite 216- C01 030 mov nicIOAddr, #$01 ; 9346CR 218- CC0 mov w, #%11000000 ; config register write enable 219- 953 call NICWrite 21A- C05 030 mov nicIOAddr, #$05 ; CONFIG2 21C- C00 mov w, #%00000000 ; link test enable 21D- 953 call NICWrite ; --- Page1 Registers --- 21E- 070 clr nicIOAddr ; CR 21F- C41 mov w, #%01000001 ; Page1, Stop 220- 953 call NICWrite 221- 2B0 inc nicIOAddr ; ($01) PAR0 222- C00 mov w, #SX_ETH_ADDR0 223- 953 call NICWrite 224- 2B0 inc nicIOAddr ; ($02) PAR1 225- C01 mov w, #SX_ETH_ADDR1 226- 953 call NICWrite 227- 2B0 inc nicIOAddr ; ($03) PAR2 228- C02 mov w, #SX_ETH_ADDR2 229- 953 call NICWrite 22A- 2B0 inc nicIOAddr ; ($04) PAR3 22B- C03 mov w, #SX_ETH_ADDR3 22C- 953 call NICWrite 22D- 2B0 inc nicIOAddr ; ($05) PAR4 22E- C04 mov w, #SX_ETH_ADDR4 22F- 953 call NICWrite 230- 2B0 inc nicIOAddr ; ($06) PAR5 231- C05 mov w, #SX_ETH_ADDR5 232- 953 call NICWrite 233- 2B0 inc nicIOAddr ; ($07) CURR 234- C40 mov w, #RXBUF_START 235- 953 call NICWrite ; --- Page0 Registers --- 236- 070 clr nicIOAddr ; CR 237- C01 mov w, #%00000001 ; Page0, Stop 238- 953 call NICWrite 239- 2B0 inc nicIOAddr ; ($01) PSTART 23A- C40 mov w, #RXBUF_START 23B- 953 call NICWrite 23C- 2B0 inc nicIOAddr ; ($02) PSTOP 23D- C53 mov w, #RXBUF_END 23E- 953 call NICWrite 23F- 2B0 inc nicIOAddr ; ($03) BNRY 240- C40 mov w, #RXBUF_START 241- 953 call NICWrite 242- C07 030 mov nicIOAddr, #$07 ; ISR 244- CFF mov w, #$FF 245- 953 call NICWrite 246- C0C 030 mov nicIOAddr, #$0C ; RCR 248- CC4 mov w, #%11000100 249- 953 call NICWrite 24A- 2B0 inc nicIOAddr ; ($0D) TCR 24B- CE0 mov w, #%11100000 24C- 953 call NICWrite 24D- 2B0 inc nicIOAddr ; ($0E) DCR 24E- CB8 mov w, #%10111000 24F- 953 call NICWrite 250- 070 clr nicIOAddr ; CR 251- C02 mov w, #%00000010 ; Page0, Start 252- A53 jmp NICWrite ; ****************************************************************************** 253- 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 ; ****************************************************************************** 253- 019 bank NIC_BANK ; put data out on data bus 254- 027 mov NIC_DATA_PORT, w 255- _mode DIR_W 255- C1F 256- 043 257- C00 mov w, #0 ; output 258- 007 mov !NIC_DATA_PORT, w ; put addr out on addr bus 259- 206 mov w, NIC_CTRL_PORT 25A- EE0 and w, #%11100000 25B- 110 or w, nicIOAddr 25C- 026 mov NIC_CTRL_PORT, w ; strobe IOWB pin 25D- A5E jmp $+1 25E- 4A6 clrb IOWB_PIN 25F- A60 jmp $+1 260- 7E6 A60 jnb IOCH_PIN, $ 262- 5A6 setb IOWB_PIN 263- 00D retp ; ****************************************************************************** 264- 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 264- 027 mov NIC_DATA_PORT, w ; strobe IOWB pin 265- A66 jmp $+1 266- 4A6 clrb IOWB_PIN 267- A68 jmp $+1 268- 7E6 A68 jnb IOCH_PIN, $ 26A- 5A6 setb IOWB_PIN 26B- 00D retp ; ****************************************************************************** 26C- 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 ; ****************************************************************************** 26C- 019 bank NIC_BANK ; configure data bus for input 26D- _mode DIR_W 26D- C1F 26E- 043 26F- CFF mov w, #$FF ; input 270- 007 mov !NIC_DATA_PORT, w ; put addr out on addr bus 271- 206 mov w, NIC_CTRL_PORT 272- EE0 and w, #%11100000 273- 110 or w, nicIOAddr 274- 026 mov NIC_CTRL_PORT, w ; strobe IORB pin and latch data 275- A76 jmp $+1 276- 4C6 clrb IORB_PIN 277- A78 jmp $+1 278- 7E6 A78 jnb IOCH_PIN, $ 27A- 207 mov w, NIC_DATA_PORT 27B- 5C6 setb IORB_PIN 27C- 00D retp ; ****************************************************************************** 27D- 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 27D- A7E jmp $+1 27E- 4C6 clrb IORB_PIN 27F- A80 jmp $+1 280- 7E6 A80 jnb IOCH_PIN, $ 282- 207 mov w, NIC_DATA_PORT 283- 5C6 setb IORB_PIN 284- 00D retp ; ****************************************************************************** 285- NICPseudoRead ; 'Read' the NIC, but ignore data. Must have called NICRead() or NICReadAgain() ; priorly ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; strobe IORB pin 285- A86 jmp $+1 286- 4C6 clrb IORB_PIN 287- A88 jmp $+1 288- 7E6 A88 jnb IOCH_PIN, $ 28A- 5C6 setb IORB_PIN 28B- 00D retp ; ****************************************************************************** 28C- NICPseudoRead6 ; 'Read' the NIC (6) times, but ignore data. Must have called NICRead() or ; NICReadAgain() priorly ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 28C- C06 mov w, #6 28D- 985 :loop call NICPseudoRead 28E- 2E1 decsz wreg 28F- A8D jmp :loop 290- 00D retp ; ****************************************************************************** 291- 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 ; ****************************************************************************** 291- _bank NIC_BANK 291- 019 292- 4E4 293- 070 clr nicIOAddr ; CR 294- C22 mov w, #%00100010 ; Page0, abort DMA 295- 953 call NICWrite 296- C07 030 mov nicIOAddr, #$07 ; ISR 298- 96C call NICRead ;jb wreg.4, :overflowed ; OVW (bit set when rx buffer overflowed) DEBUG 299- 681 010 jb wreg.4, @Main ; OVW (bit set when rx buffer overflowed)-> reset 29B- A60 29C- 070 clr nicIOAddr ; CR 29D- C42 mov w, #%01000010 ; Page1 29E- 953 call NICWrite 29F- C07 030 mov nicIOAddr, #$07 ; CURR 2A1- 96C call NICRead 2A2- 02C mov globTemp1, w 2A3- 070 clr nicIOAddr ; CR 2A4- C02 mov w, #%00000010 ; Page0 2A5- 953 call NICWrite 2A6- C03 030 mov nicIOAddr, #$03 ; BNRY 2A8- 96C call NICRead 2A9- 18C xor w, globTemp1 ; CURR = BNRY => no packets 2AA- 00D retp ;:overflowed mov w, #(RTCC_ID) ; DEBUG ; mov !option, w ; DEBUG ; clrb LED_PIN ; DEBUG ; jmp $ ; DEBUG ; ****************************************************************************** 2AB- NICWaitRxFrame ; Wait for an ethernet frame to be received. ; INPUT: none ; OUTPUT: nicCurrPktPtr = points to beginning of packet just received ; nicNextPktPtr = points to beginning of next packet ; nicRemoteEth0-5 = source (remote) ethernet address ; ****************************************************************************** 2AB- _bank NIC_BANK 2AB- 019 2AC- 4E4 2AD- 070 :loop clr nicIOAddr ; CR 2AE- C62 mov w, #%01100010 ; Page1, abort DMA 2AF- 953 call NICWrite 2B0- C07 030 mov nicIOAddr, #$07 ; CURR 2B2- 96C call NICRead 2B3- 02C mov globTemp1, w 2B4- 070 clr nicIOAddr ; CR 2B5- C02 mov w, #%00000010 ; Page0 2B6- 953 call NICWrite 2B7- C03 030 mov nicIOAddr, #$03 ; BNRY 2B9- 96C call NICRead 2BA- 18C xor w, globTemp1 2BB- 643 AAD jz :loop ; CURR = BNRY => no packets 2BD- 070 clr nicIOAddr ; CR 2BE- C1A mov w, #%00011010 ; Page0, packet send 2BF- 953 call NICWrite ; store current-packet pointer 2C0- C03 030 mov nicIOAddr, #$03 ; BNRY 2C2- 96C call NICRead 2C3- 032 mov nicCurrPktPtr, w 2C4- C10 030 mov nicIOAddr, #$10 ; RDMA ; ignore receive status 2C6- 96C call NICRead ; store next-packet pointer 2C7- 97D call NICReadAgain 2C8- 031 mov nicNextPktPtr, w ; ignore ethernet frame size 2C9- 985 call NICPseudoRead 2CA- 985 call NICPseudoRead ; ignore the ethernet addr 2CB- 98C call NICPseudoRead6 ; record the sender's ethernet addr 2CC- 97D call NICReadAgain 2CD- 033 mov nicRemoteEth0, w 2CE- 97D call NICReadAgain 2CF- 034 mov nicRemoteEth1, w 2D0- 97D call NICReadAgain 2D1- 035 mov nicRemoteEth2, w 2D2- 97D call NICReadAgain 2D3- 036 mov nicRemoteEth3, w 2D4- 97D call NICReadAgain 2D5- 037 mov nicRemoteEth4, w 2D6- 97D call NICReadAgain 2D7- 038 mov nicRemoteEth5, w 2D8- 070 clr nicIOAddr ; CR 2D9- C22 mov w, #%00100010 ; Page0, abort DMA 2DA- A53 jmp NICWrite ; ****************************************************************************** 2DB- NICDumpRxFrame ; Discard the current received frame by advancing the receive circular buffer ; tail pointer ; INPUT: nicNextPktPtr = next packet page ; OUTPUT: none ; ****************************************************************************** 2DB- 019 bank NIC_BANK 2DC- 070 clr nicIOAddr ; CR 2DD- C22 mov w, #%00100010 ; Page0, abort DMA 2DE- 953 call NICWrite 2DF- C03 030 mov nicIOAddr, #$03 ; BNRY 2E1- 211 mov w, nicNextPktPtr ; advance tail pointer 2E2- A53 jmp NICWrite ; ****************************************************************************** 2E3- NICInitTxFrame ; i. initialize NIC for remote-DMA writes ; ii. fills in ethernet and ; INPUT: w = starting page number of tx buffer ; nicRemoteEth0-5 = destination ethernet address ; OUTPUT: none ; ****************************************************************************** 2E3- 02C mov globTemp1, w 2E4- 019 bank NIC_BANK ; wait for prior transmission to complete 2E5- 070 clr nicIOAddr ; CR 2E6- 96C :wait call NICRead 2E7- 641 AE6 jb wreg.2, :wait 2E9- C22 mov w, #%00100010 ; Page0, abort DMA 2EA- 953 call NICWrite 2EB- C04 030 mov nicIOAddr, #$04 ; TPSR 2ED- 20C mov w, globTemp1 2EE- 953 call NICWrite 2EF- C08 030 mov nicIOAddr, #$08 ; RSAR0 2F1- C00 mov w, #$00 2F2- 953 call NICWrite 2F3- 2B0 inc nicIOAddr ; ($09) RSAR1 2F4- 20C mov w, globTemp1 2F5- 953 call NICWrite 2F6- C0A 030 mov nicIOAddr, #$0A ; RBCR0 2F8- CEA mov w, #$EA ; max ethernet packet size 2F9- 953 call NICWrite 2FA- 2B0 inc nicIOAddr ; ($0B) RBCR1 2FB- C05 mov w, #$05 2FC- 953 call NICWrite 2FD- 070 clr nicIOAddr ; CR 2FE- C12 mov w, #%00010010 ; Page0, remote write 2FF- 953 call NICWrite 300- C10 030 mov nicIOAddr, #$10 ; RDMA ; 302- 908 call NICWriteDestEth ; 303- A07 jmp NICWriteSrcEth ; ****************************************************************************** 304- _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 ; ****************************************************************************** ; sometimes we need to bypass ARP (e.g. broadcast IP addr) 304- 66B B0A jb arpFlags.ARP_BYPASS, :here ; otherwise we need to check if we know the MAC mapping for the IP addr 306- 012 913 call @ARPCheckCache ; Start ARP 308- 60B snb arpFlags.ARP_REQ_SENT ; Continue if an ARP request was not sent ; or if a stalled packet is to be sent 309- 00D retp ; exit, ARP request was sent. packet to be stalled 30A- 019 :here bank NIC_BANK 30B- 070 clr nicIOAddr ; CR 30C- C22 mov w, #%00100010 ; Page0, abort DMA 30D- 953 call NICWrite 30E- 01A bank IP_BANK 30F- C32 mov w, #(64-6-6-2) 310- 09B mov w, ipLengthLSB-w 311- 603 B20 jc :notRunt 313- C01 mov w, #1 314- 09A mov w, ipLengthMSB-w 315- 603 B20 jc :notRunt 317- 019 bank NIC_BANK 318- C05 030 mov nicIOAddr, #$05 ; TBCR0 31A- C40 mov w, #64 ; min ethernet frame size 31B- 953 call NICWrite 31C- 2B0 inc nicIOAddr ; ($06) TBCR1 31D- C00 mov w, #0 31E- 953 call NICWrite 31F- B2D jmp :transmit 320- 019 :notRunt bank NIC_BANK 321- C05 030 mov nicIOAddr, #$05 ; TBCR0 323- 01A bank IP_BANK 324- C0E mov w, #(6+6+2) 325- 1DB add w, ipLengthLSB 326- 953 call NICWrite ; should not affect carry flag 327- 2B0 inc nicIOAddr ; ($06) TBCR1 328- 01A bank IP_BANK 329- 21A mov w, ipLengthMSB 32A- 603 snc 32B- 2A1 inc wreg 32C- 953 call NICWrite 32D- 070 :transmit clr nicIOAddr ; CR 32E- C06 mov w, #%00000110 ; Page0, transmit 32F- A53 jmp NICWrite ; ****************************************************************************** 330- _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 ; ****************************************************************************** 330- 019 bank NIC_BANK 331- 070 clr nicIOAddr ; CR 332- C22 mov w, #%00100010 ; Page0, abort DMA 333- 953 call NICWrite 334- C0B 030 mov nicIOAddr, #$0B ; RBCR1 336- C00 mov w, #0 ; MSB is always zero 337- 953 call NICWrite ; initialize RDMA to get source byte 338- 070 :loop clr nicIOAddr ; CR 339- C22 mov w, #%00100010 ; Page0, abort DMA 33A- 953 call NICWrite 33B- C08 030 mov nicIOAddr, #$08 ; RSAR0 33D- 21A mov w, nicCopySrcLSB 33E- 953 call NICWrite 33F- 2B0 inc nicIOAddr ; ($09) RSAR1 340- 219 mov w, nicCopySrcMSB 341- 953 call NICWrite 342- C0A 030 mov nicIOAddr, #$0A ; RBCR0 344- C01 mov w, #1 ; one-byte DMA 345- 953 call NICWrite 346- 070 clr nicIOAddr ; CR 347- C0A mov w, #%00001010 ; Page0, remote read 348- 953 call NICWrite 349- C10 030 mov nicIOAddr, #$10 ; RDMA 34B- 96C call NICRead 34C- 03F mov nicCopyTemp, w ; store source byte temporarily ; initialize RDMA to write byte to destination 34D- C08 030 mov nicIOAddr, #$08 ; RSAR0 34F- 21C mov w, nicCopyDestLSB 350- 953 call NICWrite 351- 2B0 inc nicIOAddr ; ($09) RSAR1 352- 21B mov w, nicCopyDestMSB 353- 953 call NICWrite 354- 2B0 inc nicIOAddr ; ($0A) RBCR0 355- C01 mov w, #1 ; one-byte DMA 356- 953 call NICWrite 357- 070 clr nicIOAddr ; CR 358- C12 mov w, #%00010010 ; Page0, remote write 359- 953 call NICWrite 35A- C10 030 mov nicIOAddr, #$10 ; RDMA 35C- 21F mov w, nicCopyTemp 35D- 953 call NICWrite ; increment source and destination pointers 35E- 2BA inc nicCopySrcLSB 35F- 643 snz 360- 2B9 inc nicCopySrcMSB 361- 2BC inc nicCopyDestLSB 362- 643 snz 363- 2BB inc nicCopyDestMSB ; check if source page pointer hit receive buffer ceiling 364- 219 mov w, nicCopySrcMSB 365- F53 xor w, #RXBUF_END 366- 743 B6A jnz :here 368- C40 039 mov nicCopySrcMSB, #RXBUF_START ; loop as many times as there are bytes to copy 36A- 2FE :here decsz nicCopyLenLSB 36B- B38 jmp :loop 36C- 23D test nicCopyLenMSB 36D- 643 snz 36E- 00D retp 36F- 0FD dec nicCopyLenMSB 370- B38 jmp :loop ; ****************************************************************************** 371- _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 ; ****************************************************************************** 371- 019 bank NIC_BANK 372- 03F mov nicCopyTemp, w 373- 070 clr nicIOAddr ; CR 374- C22 mov w, #%00100010 ; Page0, abort DMA 375- C08 030 mov nicIOAddr, #$08 ; RSAR0 377- 21A mov w, nicCopySrcLSB 378- 953 call NICWrite 379- 2B0 inc nicIOAddr ; ($09) RSAR1 37A- 219 mov w, nicCopySrcMSB 37B- 953 call NICWrite 37C- 2B0 inc nicIOAddr ; ($0A) RBCR0 37D- C01 mov w, #1 ; one-byte DMA 37E- 953 call NICWrite 37F- 2B0 inc nicIOAddr ; ($0B) RBCR1 380- C00 mov w, #0 ; MSB is always zero 381- 953 call NICWrite 382- 070 clr nicIOAddr ; CR 383- C12 mov w, #%00010010 ; Page0, remote write 384- 953 call NICWrite 385- C10 030 mov nicIOAddr, #$10 ; RDMA 387- 21F mov w, nicCopyTemp 388- A53 jmp NICWrite ; ****************************************************************************** 389- _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 ; ****************************************************************************** 389- 019 bank NIC_BANK 38A- 070 clr nicIOAddr ; CR 38B- C22 mov w, #%00100010 ; Page0, abort DMA 38C- C08 030 mov nicIOAddr, #$08 ; RSAR0 38E- 21A mov w, nicCopySrcLSB 38F- 953 call NICWrite 390- 2B0 inc nicIOAddr ; ($09) RSAR1 391- 219 mov w, nicCopySrcMSB 392- 953 call NICWrite 393- 2B0 inc nicIOAddr ; ($0A) RBCR0 394- C01 mov w, #1 ; one-byte DMA 395- 953 call NICWrite 396- 2B0 inc nicIOAddr ; ($0B) RBCR1 397- C00 mov w, #0 ; MSB is always zero 398- 953 call NICWrite 399- 070 clr nicIOAddr ; CR 39A- C0A mov w, #%00001010 ; Page0, remote read 39B- 953 call NICWrite 39C- C10 030 mov nicIOAddr, #$10 ; RDMA 39E- A6C jmp NICRead ; ****************************************************************************** 39F- _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 = ; remoteIP3-0 = ; OUTPUT: none ; ****************************************************************************** 39F- 019 bank NIC_BANK 3A0- 070 clr nicIOAddr ; CR 3A1- C22 mov w, #%00100010 ; Page0, abort DMA 3A2- C08 030 mov nicIOAddr, #$08 ; RSAR0 3A4- 21A mov w, nicCopySrcLSB 3A5- 953 call NICWrite 3A6- 2B0 inc nicIOAddr ; ($09) RSAR1 3A7- 219 mov w, nicCopySrcMSB 3A8- 953 call NICWrite 3A9- 2B0 inc nicIOAddr ; ($0A) RBCR0 3AA- C08 mov w, #(4+4) ; 8-byte DMA 3AB- 953 call NICWrite 3AC- 2B0 inc nicIOAddr ; ($0B) RBCR1 3AD- C00 mov w, #0 ; MSB is always zero 3AE- 953 call NICWrite 3AF- 070 clr nicIOAddr ; CR 3B0- C12 mov w, #%00010010 ; Page0, remote write 3B1- 953 call NICWrite 3B2- C10 030 mov nicIOAddr, #$10 ; RDMA ; 3B4- 905 call NICWriteSrcIP ; 3B5- A06 jmp NICWriteDestIP ; ****************************************************************************** 3B6- _NICWriteSrcIP ; Write Source IP address to NIC's buffer using remote DMA. NIC must be pre- ; initialized for this. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 3B6- 7CA BC2 jnb flags.GOT_IP_ADDR, :noIP 3B8- 01A bank IP_BANK 3B9- 214 mov w, myIP3 3BA- 953 call NICWrite 3BB- 01A bank IP_BANK 3BC- 215 mov w, myIP2 3BD- 964 call NICWriteAgain 3BE- 216 mov w, myIP1 3BF- 964 call NICWriteAgain 3C0- 217 mov w, myIP0 3C1- A64 jmp NICWriteAgain 3C2- C00 :noIP mov w, #0 ; 0.0.0.0 3C3- 953 call NICWrite 3C4- C00 mov w, #0 3C5- 964 call NICWriteAgain 3C6- 964 call NICWriteAgain 3C7- A64 jmp NICWriteAgain ; ****************************************************************************** 3C8- _NICWriteDestIP ; Write Destination IP address to NIC's buffer using remote DMA. NIC must be ; pre-initialized for this. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 3C8- 01A bank IP_BANK 3C9- 210 mov w, remoteIP3 3CA- 953 call NICWrite 3CB- 01A bank IP_BANK 3CC- 211 mov w, remoteIP2 3CD- 964 call NICWriteAgain 3CE- 01A bank IP_BANK 3CF- 212 mov w, remoteIP1 3D0- 964 call NICWriteAgain 3D1- 01A bank IP_BANK 3D2- 213 mov w, remoteIP0 3D3- A64 jmp NICWriteAgain ; ****************************************************************************** 3D4- _NICWriteSrcEth ; Write Source Ethernet address to NIC's buffer using remote DMA. NIC must be ; pre-initialized for this. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 3D4- C00 mov w, #SX_ETH_ADDR0 3D5- 953 call NICWrite 3D6- C01 mov w, #SX_ETH_ADDR1 3D7- 964 call NICWriteAgain 3D8- C02 mov w, #SX_ETH_ADDR2 3D9- 964 call NICWriteAgain 3DA- C03 mov w, #SX_ETH_ADDR3 3DB- 964 call NICWriteAgain 3DC- C04 mov w, #SX_ETH_ADDR4 3DD- 964 call NICWriteAgain 3DE- C05 mov w, #SX_ETH_ADDR5 3DF- A64 jmp NICWriteAgain ; ****************************************************************************** 3E0- _NICWriteDestEth ; Write Destination Ethernet address to NIC's buffer using remote DMA. NIC must ; be pre-initialized for this. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 3E0- 213 mov w, nicRemoteEth0 3E1- 953 call NICWrite 3E2- 214 mov w, nicRemoteEth1 3E3- 964 call NICWriteAgain 3E4- 215 mov w, nicRemoteEth2 3E5- 964 call NICWriteAgain 3E6- 216 mov w, nicRemoteEth3 3E7- 964 call NICWriteAgain 3E8- 217 mov w, nicRemoteEth4 3E9- 964 call NICWriteAgain 3EA- 218 mov w, nicRemoteEth5 3EB- A64 jmp NICWriteAgain ; ****************************************************************************** 3EC- _NICDMAInit ; Setup the NIC's RSAR and RBCR register in preparation for remote DMA. ; INPUT: nicCurrPktPtr = beginning of packet ; OUTPUT: none ; ****************************************************************************** 3EC- 019 bank NIC_BANK 3ED- 070 clr nicIOAddr ; CR 3EE- C22 mov w, #%00100010 ; Page0, abort DMA 3EF- 953 call NICWrite ; initialize DMA to field in ethernet frame 3F0- C08 030 mov nicIOAddr, #$08 ; RSAR0 3F2- C10 mov w, #(4+6+6) ; point to field 3F3- 953 call NICWrite 3F4- 2B0 inc nicIOAddr ; ($09) RSAR1 3F5- 212 mov w, nicCurrPktPtr 3F6- 953 call NICWrite 3F7- 2B0 inc nicIOAddr ; ($0A) RBCR0 3F8- CFF mov w, #$FF 3F9- 953 call NICWrite 3FA- 2B0 inc nicIOAddr ; ($0B) RBCR1 3FB- C0F mov w, #$0F 3FC- A53 jmp NICWrite 400- ORG $400 ; Page2 400- B0C ARPSendRequest jmp _ARPSendRequest 401- B34 ARPSendResponse jmp _ARPSendResponse 402- B3D ARPSendStPacket jmp _ARPSendStPacket 403- B6D CheckIPDatagram jmp _CheckIPDatagram 404- BD9 CheckIPDestAddr jmp _CheckIPDestAddr ; ****************************************************************************** 405- NICRead_2 ; Shortform for calling NICRead(), which is in Page1 (This is in Page2) ; ****************************************************************************** 405- 011 A6C jmp @NICRead ; ****************************************************************************** 407- NICReadAgain_2 ; Shortform for calling NICReadAgain(), which is in Page1 (This is in Page2) ; ****************************************************************************** 407- 011 A7D jmp @NICReadAgain ; ****************************************************************************** 409- NICPseudoRead_2 ; Shortform for calling NICPseudoRead(), which is in Page1 (This is in Page2) ; ****************************************************************************** 409- 011 A85 jmp @NICPseudoRead ; ****************************************************************************** 40B- NICPseudoRead6_2 ; Shortform for calling NICPseudoRead(), which is in Page1 (This is in Page2) ; ****************************************************************************** 40B- 011 A8C jmp @NICPseudoRead6 ; ****************************************************************************** 40D- NICWrite_2 ; Shortform for calling NICWrite(), which is in Page1 (This is in Page2) ; ****************************************************************************** 40D- 011 A53 jmp @NICWrite ; ****************************************************************************** 40F- NICWriteAgain_2 ; Shortform for calling NICWriteAgain(), which is in Page1 (This is in Page2) ; ****************************************************************************** 40F- 011 A64 jmp @NICWriteAgain ; ****************************************************************************** 411- NICDumpRxFrame_2 ; Shortform for calling NICDumpRxFrame(), which is in Page1 (This is in Page2) ; ****************************************************************************** 411- 011 ADB jmp @NICDumpRxFrame ; ****************************************************************************** 413- 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 ; ****************************************************************************** 413- 74B A18 jnb arpFlags.ARP_STL_TX, :cacheGo ; do not check cache if stalled packet to be txed 415- 95B call ARPUpdateEthAddr ; now update stalled packet's ethernet address 416- 06B clr arpFlags ; reset ARP 417- 00D retp 418- :cacheGo ; check if remote host IP is in cache IF ROUTE ; Check if the IP is on local subnet. 418- 01A bank IP_BANK 419- 210 mov w, remoteIP3 41A- 194 xor w, myIP3 41B- EFF and w, #SX_IP_NETMASK3 41C- 743 A3E jnz :wanRoute 41E- 211 mov w, remoteIP2 41F- 195 xor w, myIP2 420- EFF and w, #SX_IP_NETMASK2 421- 743 A3E jnz :wanRoute 423- 212 mov w, remoteIP1 424- 196 xor w, myIP1 425- EFF and w, #SX_IP_NETMASK1 426- 743 A3E jnz :wanRoute 428- 213 mov w, remoteIP0 429- 197 xor w, myIP0 42A- E00 and w, #SX_IP_NETMASK0 42B- 743 A3E jnz :wanRoute ENDIF ; ROUTE 42D- :lanRoute ; the IP is local, or no ROUTE. 42D- 01A bank IP_BANK 42E- 210 mov w, remoteIP3 42F- 01E bank ARP_BANK 430- 03B mov ARPRequestIP3, w 431- 01A bank IP_BANK 432- 211 mov w, remoteIP2 433- 01E bank ARP_BANK 434- 03C mov ARPRequestIP2, w 435- 01A bank IP_BANK 436- 212 mov w, remoteIP1 437- 01E bank ARP_BANK 438- 03D mov ARPRequestIP1, w 439- 01A bank IP_BANK 43A- 213 mov w, remoteIP0 43B- 01E bank ARP_BANK 43C- 03E mov ARPRequestIP0, w IF ROUTE 43D- A47 jmp :cacheCheck 43E- :wanRoute ; the IP is through Router. 43E- 01E bank ARP_BANK 43F- C0A 03B mov ARPRequestIP3, #SX_IP_ROUTER3 441- C00 03C mov ARPRequestIP2, #SX_IP_ROUTER2 443- C00 03D mov ARPRequestIP1, #SX_IP_ROUTER1 445- C02 03E mov ARPRequestIP0, #SX_IP_ROUTER0 ENDIF ; ROUTE 447- 21B :cacheCheck mov w, ARPRequestIP3 448- 196 xor w, host1IP3 449- 743 A59 jnz :cacheNoMatch ; no match 44B- 21C mov w, ARPRequestIP2 44C- 197 xor w, host1IP2 44D- 743 A59 jnz :cacheNoMatch ; no match 44F- 21D mov w, ARPRequestIP1 450- 198 xor w, host1IP1 451- 743 A59 jnz :cacheNoMatch ; no match 453- 21E mov w, ARPRequestIP0 454- 199 xor w, host1IP0 455- 743 A59 jnz :cacheNoMatch ; no match 457- 06B :cacheMatch clr arpFlags ; reset ARP 458- A5B jmp ARPUpdateEthAddr ; check, update remote Eth address of pending packet in NIC 459- 50B :cacheNoMatch setb arpFlags.ARP_REQ_SENT ; indicate an ARP request is sent 45A- A00 jmp ARPSendRequest ; do an ARP request now to get the remote Eth address ; ****************************************************************************** 45B- 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 ; ****************************************************************************** 45B- 019 bank NIC_BANK 45C- 070 clr nicIOAddr ; CR 45D- C22 mov w, #%00100010 ; Page0, abort DMA 45E- 90D call NICWrite_2 45F- C08 030 mov nicIOAddr, #$08 ; RSAR0 461- C00 mov w, #0 462- 90D call NICWrite_2 463- 2B0 inc nicIOAddr ; ($09) RSAR1 464- 01E bank ARP_BANK 465- 21A mov w, stPktTxBufStart ; stPktTxBufStart contains page number of stalled pkt 466- 90D call NICWrite_2 467- 2B0 inc nicIOAddr ; ($0A) RBCR0 468- C0C mov w, #(6+6) ; 12-byte DMA 469- 90D call NICWrite_2 46A- 2B0 inc nicIOAddr ; ($0B) RBCR1 46B- C00 mov w, #0 ; MSB is always zero 46C- 90D call NICWrite_2 46D- 070 clr nicIOAddr ; CR 46E- C12 mov w, #%00010010 ; Page0, remote write 46F- 90D call NICWrite_2 470- C10 030 mov nicIOAddr, #$10 ; RDMA ; 472- 01E bank ARP_BANK 473- 210 mov w, host1Eth0 474- 90D call NICWrite_2 475- 01E bank ARP_BANK 476- 211 mov w, host1Eth1 477- 90F call NICWriteAgain_2 478- 212 mov w, host1Eth2 479- 90F call NICWriteAgain_2 47A- 213 mov w, host1Eth3 47B- 90F call NICWriteAgain_2 47C- 214 mov w, host1Eth4 47D- 90F call NICWriteAgain_2 47E- 215 mov w, host1Eth5 47F- A0F jmp NICWriteAgain_2 ; ****************************************************************************** 480- ARPCheckIfIs ; Checks received packet to see if it is ARP. ; Sends an 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) ; ****************************************************************************** 480- 40A clrb flags.RX_IS_ARP 481- 011 909 call @NICDMAInit 483- 070 clr nicIOAddr ; CR 484- C0A mov w, #%00001010 ; Page0, remote read 485- 90D call NICWrite_2 486- C10 030 mov nicIOAddr, #$10 ; RDMA ; check if ethernet field contains ARP identifier (0x0806) 488- 905 call NICRead_2 489- F08 xor w, #$08 48A- 743 AD8 jnz :outtaHere 48C- 907 call NICReadAgain_2 48D- F06 xor w, #$06 48E- 743 AD8 jnz :outtaHere 490- 50A setb flags.RX_IS_ARP ; yes, it's ARP, indicate that for main loop ; ignore ,,, 491- 90B call NICPseudoRead6_2 ; Checks if the ARP packet received is a request or a response 492- 907 call NICReadAgain_2 493- F00 xor w, #$00 494- 743 AD8 jnz :outtaHere ; not ARP at all 496- 907 call NICReadAgain_2 497- 02C mov globTemp1, w ; store ARP opcode 498- F01 xor w, #$01 ; check if ARP Request (0x0001) 499- 643 AA0 jz :rcvdARPRequest ; yes, process ARP request 49B- 20C mov w, globTemp1 49C- F02 xor w, #$02 ; check if ARP Response (0x0002) 49D- 643 ABD jz :rcvdARPResponse ; yes, process ARP response 49F- AD8 jmp :outtaHere ; no, not ARP at all 4A0- :rcvdARPRequest ; ignore 4A0- 90B call NICPseudoRead6_2 ; if a TCP connection has been established, check to see if remote ; IP is the one we've established connection with, otherwise, make ; sure {remoteIP3-0} isn't clobbered 4A1- 01C bank TCP_BANK 4A2- C04 090 cjne tcpState, #TCP_ST_ESTABED, :senderIP 4A4- 743 AAC ; check 4A6- C20 024 mov fsr, #remoteIP3 4A8- 9DB call ARPCompare4 4A9- 743 AD8 jnz :outtaHere 4AB- AB5 jmp :targetHA ; record the sender's IP addr () 4AC- 01A :senderIP bank IP_BANK 4AD- 907 call NICReadAgain_2 4AE- 030 mov remoteIP3, w 4AF- 907 call NICReadAgain_2 4B0- 031 mov remoteIP2, w 4B1- 907 call NICReadAgain_2 4B2- 032 mov remoteIP1, w 4B3- 907 call NICReadAgain_2 4B4- 033 mov remoteIP0, w ; ignore 4B5- 90B :targetHA call NICPseudoRead6_2 ; check if is me 4B6- C24 024 mov fsr, #myIP3 4B8- 9DB call ARPCompare4 4B9- 743 AD8 jnz :outtaHere ; so it's for me! 4BB- 901 call ARPSendResponse 4BC- A11 jmp NICDumpRxFrame_2 ; we're done with this packet, dump it 4BD- :rcvdARPResponse ; ; record sender's Eth then record IP address in ARP cache ; go ahead and fill the cache, we'll check it later. 4BD- C60 024 mov fsr, #host1Eth0 4BF- C0A 02C mov globTemp1, #(6+4) 4C1- 907 :ethLoop call NICReadAgain_2 4C2- 020 mov indf, w 4C3- 2A4 inc fsr 4C4- 2EC decsz globTemp1 4C5- AC1 jmp :ethLoop ; ; check if sender's IP corrresponds to requested IP address 4C6- 01E bank ARP_BANK 4C7- 21E mov w, ARPRequestIP0 4C8- 199 xor w, host1IP0 4C9- 743 AD8 jnz :outtaHere 4CB- 21D mov w, ARPRequestIP1 4CC- 198 xor w, host1IP1 4CD- 743 AD8 jnz :outtaHere 4CF- 21C mov w, ARPRequestIP2 4D0- 197 xor w, host1IP2 4D1- 743 AD8 jnz :outtaHere 4D3- 21B mov w, ARPRequestIP3 4D4- 196 xor w, host1IP3 4D5- 743 AD8 jnz :outtaHere 4D7- 52B :ipAddrResolved setb arpFlags.ARP_RSP_RCVD ; indicate we got a successfull ARP response 4D8- 60A :outtaHere snb flags.RX_IS_ARP ; check if packet was ARP 4D9- 911 call NICDumpRxFrame_2 ; if it was ARP, we dump it; otherwise, don't touch it 4DA- 00D retp ; ****************************************************************************** 4DB- 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 ; ****************************************************************************** 4DB- C04 02C mov globTemp1, #4 4DD- 907 :loop call NICReadAgain_2 4DE- 180 xor w, indf 4DF- 743 sz 4E0- 00D retp ; mis-match 4E1- 2A4 inc fsr 4E2- 2EC decsz globTemp1 4E3- ADD jmp :loop 4E4- 543 stz 4E5- 00D retp ; ****************************************************************************** 4E6- ARPSendCommon1 ; Helper function for ARPSendRequest and ARPSendResponse ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; = 0x0806 4E6- C08 mov w, #$08 4E7- 90F call NICWriteAgain_2 4E8- C06 mov w, #$06 4E9- 90F call NICWriteAgain_2 ; = 0x0001 4EA- C00 mov w, #$00 4EB- 90F call NICWriteAgain_2 4EC- C01 mov w, #$01 4ED- 90F call NICWriteAgain_2 ; = 0x0800 4EE- C08 mov w, #$08 4EF- 90F call NICWriteAgain_2 4F0- C00 mov w, #$00 4F1- 90F call NICWriteAgain_2 ; = 0x06 4F2- C06 mov w, #$06 4F3- 90F call NICWriteAgain_2 ; = 0x04 4F4- C04 mov w, #$04 4F5- A0F jmp NICWriteAgain_2 ; ****************************************************************************** 4F6- ARPSendCommon2 ; Helper function for ARPSendRequest and ARPSendResponse ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; 4F6- 011 907 call @NICWriteSrcEth ; 4F8- 011 905 call @NICWriteSrcIP ; 4FA- 011 908 call @NICWriteDestEth ; 4FC- 011 906 call @NICWriteDestIP 4FE- ARPSendCommon3 ; Special entry point for Router lookup. ; whew! the ethernet frame is now complete, get ready to send ... 4FE- 019 bank NIC_BANK ; NICWriteDestIP changes bank 4FF- 070 clr nicIOAddr ; CR 500- C22 mov w, #%00100010 ; Page0, abort DMA 501- 90D call NICWrite_2 502- C05 030 mov nicIOAddr, #$05 ; TBCR0 504- C40 mov w, #$40 ; min ethernet packet size 505- 90D call NICWrite_2 506- 2B0 inc nicIOAddr ; ($06) TBCR1 507- C00 mov w, #$00 508- 90D call NICWrite_2 509- 070 clr nicIOAddr ; CR 50A- C06 mov w, #%00000110 ; transmit 50B- A0D jmp NICWrite_2 ; ****************************************************************************** 50C- _ARPSendRequest ; Sends an ARP Request ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 50C- 019 bank NIC_BANK 50D- CFF mov w, #$FF 50E- 033 mov nicRemoteEth0, w ; setup broadcast Ethernet address 50F- 034 mov nicRemoteEth1, w 510- 035 mov nicRemoteEth2, w 511- 036 mov nicRemoteEth3, w 512- 037 mov nicRemoteEth4, w 513- 038 mov nicRemoteEth5, w 514- C5F mov w, #TXBUF3_START ; point to ARP transmit buffer 515- 011 9E3 call @NICInitTxFrame 517- 9E6 call ARPSendCommon1 ; = 0x0001 , ARP request opcode 518- C00 mov w, #$00 519- 90F call NICWriteAgain_2 51A- C01 mov w, #$01 51B- 90F call NICWriteAgain_2 ; 51C- 011 907 call @NICWriteSrcEth ; 51E- 011 905 call @NICWriteSrcIP ; 520- 011 908 call @NICWriteDestEth ; ; call @NICWriteDestIP ; Write ARP Request IP address to NIC's buffer using remote DMA. 522- 01E bank ARP_BANK 523- 21B mov w, ARPRequestIP3 524- 90D call NICWrite_2 525- 01E bank ARP_BANK 526- 21C mov w, ARPRequestIP2 527- 90F call NICWriteAgain_2 528- 01E bank ARP_BANK 529- 21D mov w, ARPRequestIP1 52A- 90F call NICWriteAgain_2 52B- 01E bank ARP_BANK 52C- 21E mov w, ARPRequestIP0 52D- 90F call NICWriteAgain_2 52E- 012 9FE call @ARPSendCommon3 ; the balance of ARPSendCommon2 530- 01F bank TIMER_BANK ; initialise the APR timeout timer 531- 071 clr arpTimerMSB 532- 072 clr arpTimerLSB 533- 00D retp ; ****************************************************************************** 534- _ARPSendResponse ; Send an ARP Response in reply to a ARP request. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 534- C5F mov w, #TXBUF3_START ; point to ARP transmit buffer 535- 011 9E3 call @NICInitTxFrame 537- 9E6 call ARPSendCommon1 ; = 0x0002 538- C00 mov w, #$00 539- 90F call NICWriteAgain_2 53A- C02 mov w, #$02 53B- 90F call NICWriteAgain_2 53C- AF6 jmp ARPSendCommon2 ; ****************************************************************************** 53D- _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 ; ****************************************************************************** 53D- 70B sb arpFlags.ARP_REQ_SENT ; check if we are waiting for an ARP response 53E- 00D retp ; no, nothing to do here 53F- 72B B61 jnb arpFlags.ARP_RSP_RCVD, :checkARPTimeout ; if no ARP response rcvd, check if timeout ; yes we have rcvd a response so now we can send the stalled packet 541- 06B clr arpFlags ; reset ARP 542- 54B setb arpFlags.ARP_STL_TX ; indicate that stalled packet is to be transmitted ; re-initialize the NIC's TPSR 543- 019 bank NIC_BANK 544- 070 clr nicIOAddr ; CR 545- 905 :wait call NICRead_2 546- 641 B45 jb wreg.2, :wait ; wait for prior transmission to complete 548- C22 mov w, #%00100010 ; Page0, abort DMA 549- 90D call NICWrite_2 54A- C04 030 mov nicIOAddr, #$04 ; TPSR 54C- 01E bank ARP_BANK 54D- 21A mov w, stPktTxBufStart ; load stalled packet's address pointer 54E- 90D call NICWrite_2 ; read the NIC's transmit buffer to find out the IP ; so that we can re-initialize the NIC's TBCR 54F- 01E bank ARP_BANK 550- 21A mov w, stPktTxBufStart 551- 019 bank NIC_BANK 552- 039 mov nicCopySrcMSB, w 553- C10 03A mov nicCopySrcLSB, #(6+6+2+2) ; IP (MSB) 555- 011 903 call @NICBufRead 557- 01A bank IP_BANK 558- 03A mov ipLengthMSB, w 559- 019 bank NIC_BANK 55A- 2BA inc nicCopySrcLSB ; IP (LSB) 55B- 011 903 call @NICBufRead 55D- 01A bank IP_BANK 55E- 03B mov ipLengthLSB, w 55F- 011 A00 jmp @NICSendTxFrame ; transmit the stalled ethernet frame 561- :checkARPTimeout 561- 01F bank TIMER_BANK 562- C05 091 csae arpTimerMSB, #ARP_TIMEOUT ; has the timer expired? 564- 703 565- 00D retp ; no, just return 566- 06B clr arpFlags ; yes, reset ARP flags ; Very important now! 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 match in the ARP cache since the original IP is still there! 567- 01E bank ARP_BANK 568- 076 clr host1IP3 569- 077 clr host1IP2 56A- 078 clr host1IP1 56B- 079 clr host1IP0 56C- 00D retp ; ****************************************************************************** 56D- _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 ; ****************************************************************************** 56D- CE5 mov w, #~((1< field contains IP identifier (0x0800) 576- 905 call NICRead_2 577- F08 xor w, #$08 578- 743 BD8 jnz :outtaHere 57A- 907 call NICReadAgain_2 57B- F00 xor w, #$00 57C- 743 BD8 jnz :outtaHere ; check and 57E- 907 call NICReadAgain_2 57F- F45 xor w, #$45 ; version = 4, header length = 5 580- 743 BD8 jnz :outtaHere ; ignore 582- 909 call NICPseudoRead_2 ; record 583- 907 call NICReadAgain_2 584- 01A bank IP_BANK 585- 03A mov ipLengthMSB, w 586- 907 call NICReadAgain_2 587- 03B mov ipLengthLSB, w ; adjust {ipLengthMSB,ipLengthLSB} to reflect number of data bytes 588- C14 0BB sub ipLengthLSB, #20 58A- 703 sc 58B- 0FA dec ipLengthMSB ; ignore REPT 2 58C- 909 call NICPseudoRead_2 58D- 909 call NICPseudoRead_2 ENDR ; check against IP packet fragmentation 58E- 907 call NICReadAgain_2 58F- 6A1 BD8 jb wreg.5, :outtaHere ; 591- 907 call NICReadAgain_2 592- F00 xor w, #0 ; 593- 743 BD8 jnz :outtaHere ; ignore 595- 909 call NICPseudoRead_2 ; record 596- 907 call NICReadAgain_2 597- 03C mov ipProtocol, w ; ignore REPT 2 598- 909 call NICPseudoRead_2 599- 909 call NICPseudoRead_2 ENDR ; if a TCP connection has been established, check to see if remote ; IP is the one we've established connection with, otherwise, make ; sure {remoteIP3-0} isn't clobbered 59A- 01C bank TCP_BANK 59B- C04 090 cjne tcpState, #TCP_ST_ESTABED, :srcIP 59D- 743 BB1 ; check 59F- 01A bank IP_BANK 5A0- 907 call NICReadAgain_2 5A1- 190 xor w, remoteIP3 5A2- 743 BD8 jnz :outtaHere 5A4- 907 call NICReadAgain_2 5A5- 191 xor w, remoteIP2 5A6- 743 BD8 jnz :outtaHere 5A8- 907 call NICReadAgain_2 5A9- 192 xor w, remoteIP1 5AA- 743 BD8 jnz :outtaHere 5AC- 907 call NICReadAgain_2 5AD- 193 xor w, remoteIP0 5AE- 743 BD8 jnz :outtaHere 5B0- BBA jmp :destIP ; record 5B1- 01A :srcIP bank IP_BANK 5B2- 907 call NICReadAgain_2 5B3- 030 mov remoteIP3, w 5B4- 907 call NICReadAgain_2 5B5- 031 mov remoteIP2, w 5B6- 907 call NICReadAgain_2 5B7- 032 mov remoteIP1, w 5B8- 907 call NICReadAgain_2 5B9- 033 mov remoteIP0, w ; check 5BA- 06D :destIP clr globTemp2 5BB- 214 mov w, myIP3 5BC- 904 call CheckIPDestAddr 5BD- 743 BD8 jnz :outtaHere 5BF- 215 mov w, myIP2 5C0- 904 call CheckIPDestAddr 5C1- 743 BD8 jnz :outtaHere 5C3- 216 mov w, myIP1 5C4- 904 call CheckIPDestAddr 5C5- 743 BD8 jnz :outtaHere 5C7- 217 mov w, myIP0 5C8- 904 call CheckIPDestAddr 5C9- 743 BD8 jnz :outtaHere 5CB- C04 1AD xor globTemp2, #4 5CD- 643 snz 5CE- 58A setb flags.RX_IS_IP_BCST ; IP broadcast addr detected ; ok! determine which higher-level protocol 5CF- C01 mov w, #1 ; ICMP 5D0- 19C xor w, ipProtocol 5D1- 643 snz 5D2- 52A setb flags.RX_IS_ICMP IF UDP mov w, #17 ; UDP xor w, ipProtocol snz setb flags.RX_IS_UDP ENDIF ; UDP 5D3- C06 mov w, #6 ; TCP 5D4- 19C xor w, ipProtocol 5D5- 643 snz 5D6- 56A setb flags.RX_IS_TCP 5D7- 00D retp 5D8- A11 :outtaHere jmp NICDumpRxFrame_2 ; if it ain't IP, forget it! ; ****************************************************************************** 5D9- _CheckIPDestAddr ; Helper function for CheckIPDatagram ; Check for a match of the IP field ; INPUT: w = byte of IP to check against ; OUTPUT: z = set if match ; globTemp2 = incremented if matched against 0xFF ; ****************************************************************************** 5D9- 02C mov globTemp1, w 5DA- 907 call NICReadAgain_2 5DB- 1AC xor globTemp1, w 5DC- 643 snz 5DD- 00D retp 5DE- FFF xor w, #$FF ; IP broadcast addr 5DF- 743 sz 5E0- 00D retp 5E1- 2AD inc globTemp2 5E2- 543 stz 5E3- 00D retp 600- ORG $600 ; Page3 600- B8F TCPTransmit jmp _TCPTransmit ; ****************************************************************************** 601- 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 601- 011 97D call @NICReadAgain 603- F08 xor w, #$08 ; echo-request 604- 743 A48 jnz :outtaHere 606- 01A bank IP_BANK 607- C16 1FB add ipLengthLSB, #(2+20) 609- 603 snc 60A- 2BA inc ipLengthMSB 60B- 019 bank NIC_BANK 60C- 212 039 mov nicCopySrcMSB, nicCurrPktPtr ; point to receive buffer 60E- C10 03A mov nicCopySrcLSB, #(4+6+6) ; don't copy NIC header, eth src & destn 610- C53 03B mov nicCopyDestMSB, #TXBUF1_START ; point to transmit buffer 612- C0C 03C mov nicCopyDestLSB, #(6+6) 614- 01A bank IP_BANK 615- 21A mov w, ipLengthMSB 616- 019 bank NIC_BANK 617- 03D mov nicCopyLenMSB, w 618- 01A bank IP_BANK 619- 21B mov w, ipLengthLSB 61A- 019 bank NIC_BANK 61B- 03E mov nicCopyLenLSB, w 61C- C53 mov w, #TXBUF1_START ; point to transmit buffer 61D- 01E bank ARP_BANK 61E- 03A mov stPktTxBufStart ,w ; Store ICMP packet start address 61F- 019 bank NIC_BANK 620- 011 9E3 call @NICInitTxFrame 622- 011 901 call @NICBufCopy ; change ICMP to echo reply (0) 624- C53 039 mov nicCopySrcMSB, #TXBUF1_START ; point to transmit buffer 626- C22 03A mov nicCopySrcLSB, #(6+6+2+20) ; point to ICMP 628- C00 mov w, #$00 629- 011 902 call @NICBufWrite ; generate ICMP 62B- C53 039 mov nicCopySrcMSB, #TXBUF1_START ; point to transmit buffer 62D- 01A bank IP_BANK 62E- 21A mov w, ipLengthMSB 62F- 019 bank NIC_BANK 630- 03D mov nicCopyLenMSB, w 631- 01A bank IP_BANK 632- 21B mov w, ipLengthLSB 633- 019 bank NIC_BANK 634- 03E mov nicCopyLenLSB, w 635- C1A 0BE sub nicCopyLenLSB, #(2+20+4) 637- 703 sc 638- 0FD dec nicCopyLenMSB 639- 013 950 call @ICMPGenCheckSum ; adjust IP and 63B- C53 039 mov nicCopySrcMSB, #TXBUF1_START ; point to transmit buffer 63D- C1A 03A mov nicCopySrcLSB, #(6+6+2+12) ; point to IP 63F- 011 904 call @NICBufIPAddrWr 641- 01A bank IP_BANK 642- C02 0BB sub ipLengthLSB, #2 644- 703 sc 645- 0FA dec ipLengthMSB 646- 011 900 call @NICSendTxFrame 648- 011 ADB :outtaHere jmp @NICDumpRxFrame ; ****************************************************************************** 64A- NICWrite_3 ; Shortform for calling NICWrite(), which is in Page1 (This is in Page3) ; ****************************************************************************** 64A- 011 A53 jmp @NICWrite ; ****************************************************************************** 64C- NICWriteAgain_3 ; Shortform for calling NICWriteAgain(), which is in Page1 (This is in Page3) ; ****************************************************************************** 64C- 011 A64 jmp @NICWriteAgain ; ****************************************************************************** 64E- NICDumpRxFrame_3 ; Shortform for calling NICWriteAgain(), which is in Page1 (This is in Page3) ; ****************************************************************************** 64E- 011 ADB jmp @NICDumpRxFrame ; ****************************************************************************** 650- 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 ; ****************************************************************************** 650- 987 call IPCheckSumInit 651- 019 bank NIC_BANK 652- 219 03F mov nicCopyTemp, nicCopySrcMSB 654- 070 clr nicIOAddr ; CR 655- C22 mov w, #%00100010 ; Page0, abort DMA 656- C08 030 mov nicIOAddr, #$08 ; RSAR0 658- C26 mov w, #(6+6+2+20+4) ; point to ICMP 659- 94A call NICWrite_3 65A- 2B0 inc nicIOAddr ; ($09) RSAR1 65B- 219 mov w, nicCopySrcMSB 65C- 94A call NICWrite_3 65D- 2B0 inc nicIOAddr ; ($0A) RBCR0 65E- 21E mov w, nicCopyLenLSB 65F- 94A call NICWrite_3 660- 2B0 inc nicIOAddr ; ($0B) RBCR1 661- 21D mov w, nicCopyLenMSB 662- 94A call NICWrite_3 663- 070 clr nicIOAddr ; CR 664- C0A mov w, #%00001010 ; Page0, remote read 665- 94A call NICWrite_3 666- C10 030 mov nicIOAddr, #$10 ; RDMA ; configure data bus for input 668- _mode DIR_W 668- C1F 669- 043 66A- CFF mov w, #$FF ; input 66B- 007 mov !NIC_DATA_PORT, w ; put addr out on addr bus 66C- 206 mov w, NIC_CTRL_PORT 66D- EE0 and w, #%11100000 66E- 110 or w, nicIOAddr 66F- 026 mov NIC_CTRL_PORT, w 670- 2BD inc nicCopyLenMSB ; in order to loop easier later 671- 011 97D :loop call @NICReadAgain 673- 98C call IPCheckSumAcc 674- 019 bank NIC_BANK 675- 2FE decsz nicCopyLenLSB 676- A71 jmp :loop 677- 2FD decsz nicCopyLenMSB 678- A71 jmp :loop 679- 21F 039 mov nicCopySrcMSB, nicCopyTemp 67B- C24 03A mov nicCopySrcLSB, #(6+6+2+20+2) 67D- 01A bank IP_BANK 67E- 258 mov w, /ipCheckSumMSB 67F- 011 902 call @NICBufWrite 681- 2BA inc nicCopySrcLSB 682- 01A bank IP_BANK 683- 259 mov w, /ipCheckSumLSB 684- 011 902 call @NICBufWrite 686- 00D retp ; ****************************************************************************** 687- IPCheckSumInit ; Initializes the IP checksum routine. ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 687- 01A bank IP_BANK 688- 078 clr ipCheckSumMSB 689- 079 clr ipCheckSumLSB 68A- 4EA clrb flags.IP_CHKSUM_LSB ; next byte is MSB 68B- 00D retp ; ****************************************************************************** 68C- 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 ; ****************************************************************************** 68C- 01A bank IP_BANK 68D- 7EA A96 jnb flags.IP_CHKSUM_LSB, :msb ; are we processing an MSB? 68F- 1F9 :lsb add ipCheckSumLSB, w ; add it to the checksum 690- 703 sc ; was there a carry? 691- A9C jmp :done 692- 2B8 inc ipCheckSumMSB ; yes 693- 643 snz 694- 2B9 inc ipCheckSumLSB 695- A9C jmp :done 696- 1F8 :msb add ipCheckSumMSB, w ; add it to the checksum 697- 703 sc ; was there a carry? 698- A9C jmp :done 699- 2B9 inc ipCheckSumLSB ; yes, this time it is added to the LSB 69A- 643 snz 69B- 2B8 inc ipCheckSumMSB 69C- C80 1AA :done xor flags, #(1< ; {ipIdentMSB,ipIdentLSB} = IP ; ipProtocol = 1(ICMP)/ 6(TCP)/ 17(UDP) ; OUTPUT: {ipCheckSumMSB,ipCheckSumLSB} = new checksum value ; ****************************************************************************** 69F- 01A bank IP_BANK 6A0- 987 call IPCheckSumInit 6A1- C45 mov w, #$45 ; Version 4, 5x 32 bit words in IP header 6A2- 98C call IPCheckSumAcc 6A3- C00 mov w, #$00 6A4- 98C call IPCheckSumAcc 6A5- 21A mov w, ipLengthMSB 6A6- 98C call IPCheckSumAcc 6A7- 21B mov w, ipLengthLSB 6A8- 98C call IPCheckSumAcc 6A9- 21D mov w, ipIdentMSB 6AA- 98C call IPCheckSumAcc 6AB- 21E mov w, ipIdentLSB 6AC- 98C call IPCheckSumAcc 6AD- C40 mov w, #%01000000 ; Don't fragment 6AE- 98C call IPCheckSumAcc 6AF- C00 mov w, #0 6B0- 98C call IPCheckSumAcc 6B1- C20 mov w, #IP_TTL 6B2- 98C call IPCheckSumAcc 6B3- 21C mov w, ipProtocol 6B4- 98C call IPCheckSumAcc 6B5- 7CA ABF jnb flags.GOT_IP_ADDR, :remoteIP ; IP = 0.0.0.0 if no IP 6B7- 214 mov w, myIP3 6B8- 98C call IPCheckSumAcc 6B9- 215 mov w, myIP2 6BA- 98C call IPCheckSumAcc 6BB- 216 mov w, myIP1 6BC- 98C call IPCheckSumAcc 6BD- 217 mov w, myIP0 6BE- 98C call IPCheckSumAcc 6BF- 210 :remoteIP mov w, remoteIP3 6C0- 98C call IPCheckSumAcc 6C1- 211 mov w, remoteIP2 6C2- 98C call IPCheckSumAcc 6C3- 212 mov w, remoteIP1 6C4- 98C call IPCheckSumAcc 6C5- 213 mov w, remoteIP0 6C6- 98C call IPCheckSumAcc 6C7- 00D retp ; ****************************************************************************** 6C8- IPStartPktOut ; Starts an outgoing IP packet by constructing the IP packet header ; INPUT: {ipLengthMSB,ipLengthLSB} = IP ; {ipIdentMSB,ipIdentLSB} = IP ; ipProtocol = 1(ICMP)/ 6(TCP)/ 17(UDP) ; {ipCheckSumMSB,ipCheckSumLSB} = IP ; OUTPUT: none ; ****************************************************************************** 6C8- 01A bank IP_BANK 6C9- C06 mov w, #6 ; TCP protocol 6CA- 19C xor w, ipProtocol 6CB- 743 sz 6CC- C53 mov w, #TXBUF1_START ; default tx buffer is TXBUF1 6CD- 643 snz 6CE- C59 mov w, #TXBUF2_START ; unless it's TCP, then we use TXBUF2 6CF- 01E bank ARP_BANK 6D0- 70B sb arpFlags.ARP_REQ_SENT ; check if a prev packet is stalled 6D1- 03A mov stPktTxBufStart, w ; no, store new address pointer to new packet 6D2- 011 9E3 call @NICInitTxFrame ; = 0x0800 6D4- C08 mov w, #$08 6D5- 94A call NICWrite_3 6D6- C00 mov w, #$00 6D7- 94C call NICWriteAgain_3 ; = 4, = 5 6D8- C45 mov w, #$45 6D9- 94C call NICWriteAgain_3 ; 6DA- C00 mov w, #$00 ; normal precedence, D=T=R=0 6DB- 94C call NICWriteAgain_3 ; 6DC- 01A bank IP_BANK 6DD- 21A mov w, ipLengthMSB 6DE- 94C call NICWriteAgain_3 6DF- 21B mov w, ipLengthLSB 6E0- 94C call NICWriteAgain_3 ; 6E1- 21D mov w, ipIdentMSB 6E2- 94C call NICWriteAgain_3 6E3- 21E mov w, ipIdentLSB 6E4- 94C call NICWriteAgain_3 ; , 6E5- C40 mov w, #%01000000 ; do not fragment 6E6- 94C call NICWriteAgain_3 6E7- C00 mov w, #0 ; offset = 0 6E8- 94C call NICWriteAgain_3 ; 6E9- C20 mov w, #IP_TTL 6EA- 94C call NICWriteAgain_3 ; 6EB- 21C mov w, ipProtocol 6EC- 94C call NICWriteAgain_3 ; 6ED- 258 mov w, /ipCheckSumMSB 6EE- 94C call NICWriteAgain_3 6EF- 259 mov w, /ipCheckSumLSB 6F0- 94C call NICWriteAgain_3 ; 6F1- 011 905 call @NICWriteSrcIP ; 6F3- 011 906 call @NICWriteDestIP 6F5- 00D retp ; ****************************************************************************** 6F6- TCPProcPktIn ; Process a received TCP packet. This function implements the TCP state machine ; INPUT: none ; OUTPUT: none ; ****************************************************************************** 6F6- 014 902 call @TCPRxHeader ; receive the header 6F8- 643 snz ; is the packet OK? 6F9- 00D retp ; no, return ; check the special states 6FA- 01C bank TCP_BANK 6FB- C00 090 cje tcpState, #TCP_ST_CLOSED, :CLOSED 6FD- 643 B67 6FF- C01 090 cje tcpState, #TCP_ST_LISTEN, :LISTEN 701- 643 B69 703- C02 090 cje tcpState, #TCP_ST_SYNSENT, :SYNSENT 705- 643 B78 707- C05 090 cje tcpState, #TCP_ST_FINWAIT1, :FINWAIT1 709- 643 B53 70B- C06 090 cje tcpState, #TCP_ST_FINWAIT2, :FINWAIT2 70D- 643 B5A 70F- C09 090 cje tcpState, #TCP_ST_LASTACK, :LASTACK 711- 643 B64 ; check the flags 713- 01D bank TCB_BANK 714- 65D snb tcbFlags.TCP_FLAG_RST ; is the reset flag set? 715- B4F jmp :gotoClosed ; yes, drop packet and close the connection 716- 63D snb tcbFlags.TCP_FLAG_SYN ; is the SYN bit set? 717- 014 AA2 jmp @TCPSendReset ; yes, drop the packet and send a reset 719- 79D sb tcbFlags.TCP_FLAG_ACK ; is the ACK bit set? 71A- A4E jmp NICDumpRxFrame_3 ; no, drop the packet 71B- 014 903 call @TCPChkSeq ; check if received packet is expected ; we only accept ACKs of complete packets. Assume the ACK is for our last packet 71D- 01C bank TCP_BANK 71E- C04 030 mov tcpState, #TCP_ST_ESTABED ; switch to the established state 720- :noOutstanding ; does the packet contain data? (Determine this from the length) 720- 23E test tcpLengthMSB 721- 743 B26 jnz :packetHasData ; MSB is not zero 723- 23F test tcpLengthLSB ; MSB is zero 724- 643 B36 jz :noData ; MSB = LSB = 0 726- 015 9E7 :packetHasData call @TCPAppRxBytes ; inform app how many bytes available 728- _bank TCP_BANK 728- 01C 729- 4E4 72A- 2BE inc tcpLengthMSB 72B- 011 97D :processData call @NICReadAgain ; receive a byte 72D- 015 9E8 call @TCPAppRxData ; pass the byte to the application 72F- _bank TCP_BANK ; _bank cus we called TCPAppRxData priorly 72F- 01C 730- 4E4 731- 2FF decsz tcpLengthLSB 732- B2B jmp :processData 733- 2FE decsz tcpLengthMSB 734- B2B jmp :processData 735- 2BF inc tcpLengthLSB ; indicate for later there was data received 736- 014 97A :noData call @TCPAckUpdate ; send an ACK packet 738- 01C bank TCP_BANK 739- 23F test tcpLengthLSB ; was data received? 73A- 643 B44 jz :checkFIN ; no, it was an ACK packet. Just return 73C- 015 900 call @TCPAppRxDone ; indicate the packet was OK to the application 73E- _bank TCP_BANK ; _bank cus we called TCPAppRxDone priorly 73E- 01C 73F- 4E4 740- 61B B48 jb tcpRxFlags.TCP_FLAG_FIN, :doClose ; if FIN bit set, close the connection 742- 014 AC1 jmp @TCPSendAck 744- 01C :checkFIN bank TCP_BANK 745- 61B B48 jb tcpRxFlags.TCP_FLAG_FIN, :doClose; is the FIN bit set? 747- A4E jmp NICDumpRxFrame_3 748- 014 955 :doClose call @TCPIncRcvNxt ; ACK the FIN 74A- 01C bank TCP_BANK 74B- C07 030 mov tcpState, #TCP_ST_CLOSEWAIT ; change state 74D- 014 AC1 jmp @TCPSendAck 74F- 01C :gotoClosed bank TCP_BANK 750- C00 030 mov tcpState, #TCP_ST_CLOSED ; go to the closed state 752- A4E jmp NICDumpRxFrame_3 ; discard received packet 753- 94E :FINWAIT1 call NICDumpRxFrame_3 754- 01C bank TCP_BANK 755- 79B sb tcpRxFlags.TCP_FLAG_ACK ; check for ACK of FIN 756- 00D retp 757- C06 030 mov tcpState, #TCP_ST_FINWAIT2 ; rcved ACK of FIN 759- 00D retp 75A- 94E :FINWAIT2 call NICDumpRxFrame_3 75B- 01C bank TCP_BANK 75C- 71B sb tcpRxFlags.TCP_FLAG_FIN ; check for FIN 75D- 00D retp 75E- C00 030 mov tcpState, #TCP_ST_CLOSED ; rcved FIN 760- 014 955 call @TCPIncRcvNxt ; ACK the FIN 762- 014 AC1 jmp @TCPSendAck 764- :LASTACK ; ignore the packet ; should check the packet is actually an ACK 764- C00 030 mov tcpState, #TCP_ST_CLOSED ; go to the closed state 766- A4E jmp NICDumpRxFrame_3 767- 014 AA2 :CLOSED jmp @TCPSendReset ; we shouldn't receive packets while closed 769- 94E :LISTEN call NICDumpRxFrame_3 ; discard received packet 76A- 01D bank TCB_BANK 76B- 65D snb tcbFlags.TCP_FLAG_RST ; check for an RST 76C- 00D retp ; ignore a packet with RST 76D- 69D snb tcbFlags.TCP_FLAG_ACK ; check for an ACK 76E- 014 AA2 jmp @TCPSendReset ; bad ACK, send a RST 770- 014 969 call @TCPCopySeqToNxt 772- 014 9BC call @TCPSendSynAck 774- 01C bank TCP_BANK 775- C03 030 mov tcpState, #TCP_ST_SYNRCVED ; change state 777- 00D retp 778- 94E :SYNSENT call NICDumpRxFrame_3 779- 01D bank TCB_BANK 77A- 65D B8B jb tcbFlags.TCP_FLAG_RST, :rst ; is the reset bit set? 77C- 73D sb tcbFlags.TCP_FLAG_SYN ; if SYN bit not set, 77D- 00D retp ; ignore packet 77E- 79D sb tcbFlags.TCP_FLAG_ACK ; if ACK bit not set, 77F- 00D retp ; ignore packet ; check that SND.UNA <= SEG.ACK <= SND.NXT 780- 01C bank TCP_BANK 781- C04 030 mov tcpState, #TCP_ST_ESTABED ; the connection is now estabished 783- 01A bank IP_BANK 784- 07A clr ipLengthMSB ; set the received data length to one 785- C01 03B mov ipLengthLSB, #1 ; " 787- 014 97A call @TCPAckUpdate 789- 014 AC1 jmp @TCPSendAck 78B- 01C :rst bank TCP_BANK 78C- C00 030 mov tcpState, #TCP_ST_CLOSED ; close the TCP 78E- 00D retp ; ****************************************************************************** 78F- _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 ; ****************************************************************************** 78F- _bank TCP_BANK ; _bank cus we called TCPAppInit priorly 78F- 01C 790- 4E4 791- C02 090 cje tcpState, #TCP_ST_SYNSENT, :timeout ; check for SYN timeout 793- 643 BF0 795- C07 090 cje tcpState, #TCP_ST_CLOSEWAIT, :closeWait 797- 643 BF9 799- C04 090 cjae tcpState, #TCP_ST_ESTABED, :ok 79B- 603 B9E 79D- 00D retp 79E- 239 :ok test tcpUnAckMSB ; are there any bytes unacknowledged? 79F- 743 BF0 jnz :timeout 7A1- 23A test tcpUnAckLSB 7A2- 743 BF0 jnz :timeout 7A4- C05 090 cje tcpState, #TCP_ST_FINWAIT1, :finTimeout ; check for FIN timeout 7A6- 643 BE7 7A8- C04 090 :askAppTxData cse tcpState, #TCP_ST_ESTABED 7AA- 743 7AB- 00D retp ; only ask if connection is established 7AC- 015 90C call @TCPAppTxBytes ; no, ask the application if it wants to transmit 7AE- _bank TCP_BANK ; _bank cus we called TCPAppTxBytes priorly 7AE- 01C 7AF- 4E4 7B0- 219 mov w, tcpUnAckMSB 7B1- 11A or w, tcpUnAckLSB 7B2- 743 BB5 jnz :appHasTxData 7B4- 00D retp ; nope, it doesn't; so we're done here then 7B5- :appHasTxData ; start a TCP packet 7B5- 21A 03F mov tcpLengthLSB, tcpUnAckLSB ; tcpLength = # bytes to transmit 7B7- 219 03E mov tcpLengthMSB, tcpUnAckMSB 7B9- 01D bank TCB_BANK 7BA- C18 03D mov tcbFlags, #((1< (MSB) 7D7- 01C bank TCP_BANK 7D8- 25C mov w, /tcpCheckSumMSB 7D9- 011 902 call @NICBufWrite 7DB- 019 bank NIC_BANK 7DC- 2BA inc nicCopySrcLSB 7DD- 01C bank TCP_BANK 7DE- 25D mov w, /tcpCheckSumLSB 7DF- 011 902 call @NICBufWrite 7E1- 011 900 call @NICSendTxFrame ; end and send the packet 7E3- 01F bank TIMER_BANK ; initialise the restart timer 7E4- 073 clr tcpTimerMSB 7E5- 074 clr tcpTimerLSB 7E6- 00D retp 7E7- 01F :finTimeout bank TIMER_BANK 7E8- C08 093 csae tcpTimerMSB, #TCP_RESTART_EXP ; has the restart timer expired? 7EA- 703 7EB- 00D retp ; no 7EC- 073 clr tcpTimerMSB ; yes, initialise the restart timer 7ED- 074 clr tcpTimerLSB 7EE- 014 AC7 jmp @TCPSendFin 7F0- 01F :timeout bank TIMER_BANK 7F1- C08 093 csae tcpTimerMSB, #TCP_RESTART_EXP ; has the restart timer expired? 7F3- 703 7F4- 00D retp ; no 7F5- 073 clr tcpTimerMSB ; yes, initialise the restart timer 7F6- 074 clr tcpTimerLSB 7F7- 014 A06 jmp @TCPReTransmit ; transmit the packet again 7F9- C09 030 :closeWait mov tcpState, #TCP_ST_LASTACK 7FB- 014 AC7 jmp @TCPSendFin ; send FIN, ACK 800- ORG $800 ; Page4 800- B07 TCPTxByte jmp _TCPTxByte 801- B0D TCPStartPktOut jmp _TCPStartPktOut 802- B44 TCPRxHeader jmp _TCPRxHeader 803- BA7 TCPChkSeq jmp _TCPChkSeq 804- BBF TCPRestorePrev jmp _TCPRestorePrev 805- B97 TCPUpdateSeq jmp _TCPUpdateSeq ; ****************************************************************************** 806- 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 806- 019 bank NIC_BANK 807- 070 clr nicIOAddr ; CR 808- 011 96C :wait call @NICRead 80A- 641 A08 jb wreg.2, :wait ; wait for prior transmission to complete 80C- C22 mov w, #%00100010 ; Page0, abort DMA 80D- 94A call NICWrite_3 80E- C04 030 mov nicIOAddr, #$04 ; TPSR 810- C59 mov w, #TXBUF2_START 811- 94A call NICWrite_3 ; read the NIC's TCP transmit buffer to find out the IP ; so that we can re-initialize the NIC's TBCR 812- C59 039 mov nicCopySrcMSB, #TXBUF2_START 814- C10 03A mov nicCopySrcLSB, #(6+6+2+2) ; IP (MSB) 816- 011 903 call @NICBufRead 818- 01A bank IP_BANK 819- 03A mov ipLengthMSB, w 81A- 019 bank NIC_BANK 81B- 2BA inc nicCopySrcLSB ; IP (LSB) 81C- 011 903 call @NICBufRead 81E- 01A bank IP_BANK 81F- 03B mov ipLengthLSB, w 820- 011 A00 jmp @NICSendTxFrame ; re-transmit the ethernet frame ; ****************************************************************************** 822- TCPAppPassiveOpen ; Do a passive open. i.e. listen for connections on a given port. ; [TCP API Function] ; INPUT: {tcbLocalPortMSB,tcbLocalPortLSB} = TCP port to listen on ; OUTPUT: none ; ****************************************************************************** 822- _bank TCP_BANK 822- 01C 823- 4E4 824- C01 030 mov tcpState, #TCP_ST_LISTEN 826- 079 clr tcpUnAckMSB 827- 07A clr tcpUnAckLSB 828- 00D retp ; ****************************************************************************** 829- 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 ; {tcpRemotePortMSB,tcbRemotePortLSB} = remote TCP port ; OUTPUT: none ; ****************************************************************************** 829- _bank TCP_BANK 829- 01C 82A- 4E4 82B- 079 clr tcpUnAckMSB 82C- 07A clr tcpUnAckLSB 82D- C02 030 mov tcpState, #TCP_ST_SYNSENT 82F- 01D bank TCB_BANK 830- C02 03D mov tcbFlags, #(1< {tcbRcvNxt4-1} ; INPUT: {tcpTmpSeq4-1} ; OUTPUT: {tcbRcvNxt4-1} ; ****************************************************************************** 869- 01C bank TCP_BANK 86A- 211 mov w, tcpTmpSeq4 86B- 01D bank TCB_BANK 86C- 038 mov tcbRcvNxt4, w 86D- 01C bank TCP_BANK 86E- 212 mov w, tcpTmpSeq3 86F- 01D bank TCB_BANK 870- 039 mov tcbRcvNxt3, w 871- 01C bank TCP_BANK 872- 213 mov w, tcpTmpSeq2 873- 01D bank TCB_BANK 874- 03A mov tcbRcvNxt2, w 875- 01C bank TCP_BANK 876- 214 mov w, tcpTmpSeq1 877- 01D bank TCB_BANK 878- 03B mov tcbRcvNxt1, w 879- 00D retp ; ****************************************************************************** 87A- TCPAckUpdate ; Update SND.UNA and RCV.NXT ; INPUT: {tcpTmpAck4-1} ; {tcpTmpSeq4-1} ; {ipLengthMSB,ipLengthLSB} = length of received TCP data ; OUTPUT: {tcpSndUna4-1} ; {tcpRcvNxt4-1} ; ****************************************************************************** 87A- 014 969 call @TCPCopySeqToNxt ; set RCV.NXT = SEG.SEQ 87C- 014 A45 jmp @TCPAddRcvNxt ; add the length of the received packet to the ACK ; ****************************************************************************** 87E- TCPCmpNxtSeq ; Check if RCV.NXT == SEG.SEQ ; INPUT: {tcpTmpSeq4-1} = SEG.SEQ ; {tcbRcvNxt4-1} = RCV.NXT ; OUTPUT: z is set if RCV.NXT == SEG.SEQ ; ****************************************************************************** 87E- 01D bank TCB_BANK 87F- 21B mov w, tcbRcvNxt1 880- 01C bank TCP_BANK 881- 194 xor w, tcpTmpSeq1 882- 743 sz 883- 00D retp 884- 01D bank TCB_BANK 885- 21A mov w, tcbRcvNxt2 886- 01C bank TCP_BANK 887- 193 xor w, tcpTmpSeq2 888- 743 sz 889- 00D retp 88A- 01D bank TCB_BANK 88B- 219 mov w, tcbRcvNxt3 88C- 01C bank TCP_BANK 88D- 192 xor w, tcpTmpSeq3 88E- 743 sz 88F- 00D retp 890- 01D bank TCB_BANK 891- 218 mov w, tcbRcvNxt4 892- 01C bank TCP_BANK 893- 191 xor w, tcpTmpSeq4 894- 00D retp ; ****************************************************************************** 895- TCPSendEmptyPkt ; Constructs and sends a TCP packet containing no data ; INPUT: {remoteIP0-3} = destination IP addr for TCP pkt ; {tcbSndUna4-1} = sequence number ; {tcbRcvNxt4-1} = acknowledgement number ; tcbFlags = code flags ; {tcbLocalPortMSB,tcbLocalPortLSB} = TCP Source Port ; {tcbRemotePortMSB,tcbRemotePortLSB} = TCP Destination Port ; OUTPUT: ; ****************************************************************************** 895- 014 9CD call @TCPCheckSumInit 897- 01C bank TCP_BANK 898- 07E clr tcpLengthMSB 899- 07F clr tcpLengthLSB 89A- 014 901 call @TCPStartPktOut 89C- 011 900 call @NICSendTxFrame 89E- 01F bank TIMER_BANK 89F- 073 clr tcpTimerMSB 8A0- 074 clr tcpTimerLSB 8A1- 00D retp ; ****************************************************************************** 8A2- TCPSendReset ; Send a reset packet with and discard the received ; packet ; INPUT: {remoteIP0-3} = destination IP addr for TCP pkt ; {tcbRcvNxt4-1} = acknowledgement number ; {tcbLocalPortMSB,tcbLocalPortLSB} = TCP Source Port ; {tcbRemotePortMSB,tcbRemotePortLSB} = TCP Destination Port ; OUTPUT: ; ****************************************************************************** 8A2- 01D bank TCB_BANK 8A3- C04 03D mov tcbFlags, #(1< ; INPUT: {remoteIP0-3} = destination IP addr for TCP pkt ; {tcbRcvNxt4-1} = acknowledgement number ; {tcbLocalPortMSB,tcbLocalPortLSB} = TCP Source Port ; {tcbRemotePortMSB,tcbRemotePortLSB} = TCP Destination Port ; OUTPUT: {tcpSndUna4-1} = new sequence number ; ****************************************************************************** 8BC- 01D bank TCB_BANK 8BD- C12 03D mov tcbFlags, #((1< and discard the ; received packet ; INPUT: {remoteIP0-3} = destination IP addr for TCP pkt ; {tcbSndUna4-1} = sequence number ; {tcbRcvNxt4-1} = acknowledgement number ; {tcbLocalPortMSB,tcbLocalPortLSB} = TCP Source Port ; {tcbRemotePortMSB,tcbRemotePortLSB} = TCP Destination Port ; OUTPUT: ; ****************************************************************************** 8C1- 01D bank TCB_BANK 8C2- C10 03D mov tcbFlags, #(1< 8E6- 21E mov w, tcpLengthMSB 8E7- 9D2 call TCPCheckSumAcc 8E8- 21F mov w, tcpLengthLSB 8E9- 9D2 call TCPCheckSumAcc ; , 8EA- C00 mov w, #0 8EB- 9D2 call TCPCheckSumAcc 8EC- C06 mov w, #6 8ED- 9D2 call TCPCheckSumAcc ; 8EE- 01A bank IP_BANK 8EF- 214 mov w, myIP3 8F0- 9D2 call TCPCheckSumAcc 8F1- 01A bank IP_BANK 8F2- 215 mov w, myIP2 8F3- 9D2 call TCPCheckSumAcc 8F4- 01A bank IP_BANK 8F5- 216 mov w, myIP1 8F6- 9D2 call TCPCheckSumAcc 8F7- 01A bank IP_BANK 8F8- 217 mov w, myIP0 8F9- 9D2 call TCPCheckSumAcc ; 8FA- 01A bank IP_BANK 8FB- 210 mov w, remoteIP3 8FC- 9D2 call TCPCheckSumAcc 8FD- 01A bank IP_BANK 8FE- 211 mov w, remoteIP2 8FF- 9D2 call TCPCheckSumAcc 900- 01A bank IP_BANK 901- 212 mov w, remoteIP1 902- 9D2 call TCPCheckSumAcc 903- 01A bank IP_BANK 904- 213 mov w, remoteIP0 905- 9D2 call TCPCheckSumAcc 906- 00D retp ; ****************************************************************************** 907- _TCPTxByte ; Transmit a TCP byte accumulating the checksum each time ; INPUT: w = byte to send ; OUTPUT: none ; ****************************************************************************** 907- 02C mov globTemp1, w 908- 014 9D2 call @TCPCheckSumAcc 90A- 20C mov w, globTemp1 90B- 941 call NICWriteAgain_4 90C- 00D retp ; ****************************************************************************** 90D- _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 ; {tcbSndUna4-1} = sequence number ; {tcbRcvNxt4-1} = acknowledgement number ; tcbFlags = code flags ; {tcbLocalPortMSB,tcbLocalPortLSB} = TCP Source Port ; {tcbRemotePortMSB,tcbRemotePortLSB} = TCP Destination Port ; OUTPUT: ; ****************************************************************************** ; tcpLength += 90D- _bank TCP_BANK 90D- 01C 90E- 4E4 90F- C14 mov w, #(TCP_HDR_LENGTH<<2) ; add in size of TCP hdr (20) 910- 1FF add tcpLengthLSB, w 911- 603 snc 912- 2BE inc tcpLengthMSB ; tcpLength now is the length of TCP hdr and data ; IP = tcpLength + 913- C14 mov w, #20 ; add in size of IP hdr (20) 914- 1DF add w, tcpLengthLSB 915- 01A bank IP_BANK 916- 03B mov ipLengthLSB, w 917- 01C bank TCP_BANK 918- 21E mov w, tcpLengthMSB 919- 01A bank IP_BANK 91A- 03A mov ipLengthMSB, w 91B- 603 snc 91C- 2BA inc ipLengthMSB ; update IP 91D- 2BE inc ipIdentLSB 91E- 643 snz 91F- 2BD inc ipIdentMSB ; set IP for TCP 920- C06 03C mov ipProtocol, #6 ; compute IP 922- 013 99F call @IPGenCheckSum ; now we're ready to construct the IP header 924- 013 9C8 call @IPStartPktOut ; then construct the TCP header ; TCP ,,, ; ,,, 926- 01D bank TCB_BANK 927- C50 03C mov tcbOffset, #(TCP_HDR_LENGTH<<4) 929- C05 03E mov tcbSendWinMSB, #((TCP_WINDOW_SIZE&$FF00)>>8) 92B- C78 03F mov tcbSendWinLSB, #(TCP_WINDOW_SIZE&$00FF) 92D- C50 02E mov globTemp3, #TCB_BANK ; send the TCB fields 92F- 20E 024 :loop mov fsr, globTemp3 931- 200 mov w, indf ; load the value 932- 014 900 call @TCPTxByte ; transmit and accumulate header checksum 934- 2AE inc globTemp3 935- C60 08E cse globTemp3, #TCB_END ; is the loop finished? 937- 743 938- B2F jmp :loop ; TCP 939- 014 9E5 call @TCPCheckSumAddHdr 93B- 01C bank TCP_BANK 93C- 25C mov w, /tcpCheckSumMSB 93D- 941 call NICWriteAgain_4 93E- 25D mov w, /tcpCheckSumLSB 93F- 941 call NICWriteAgain_4 ; TCP 940- C00 mov w, #0 941- 941 call NICWriteAgain_4 942- 941 call NICWriteAgain_4 943- 00D retp ; ****************************************************************************** 944- _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 ; {tcbRemotePortMSB,tcbRemotePortLSB} ; {tcbSendWinMSB,tcbSendWinLSB} ; tcbOffset ; tcbFlags ; tcpRxFlags ; {tcpTmpSeq4-1} = ; {tcpTmpAck4-1} = ; {tcpLengthMSB,tcpLengthLSB} = length of TCP data ; {ipLengthMSB,ipLengthLSB} = length of TCP data ; ****************************************************************************** ; Check port and refuse packet if not for current connection 944- 01C bank TCP_BANK 945- C01 090 cjne tcpState, #TCP_ST_LISTEN, :checkSrc 947- 743 B4F ; 949- :readSrc ; read the source port 949- 01D bank TCB_BANK 94A- 93F call NICReadAgain_4 94B- 032 mov tcbRemotePortMSB, w 94C- 93F call NICReadAgain_4 94D- 033 mov tcbRemotePortLSB, w 94E- B58 jmp :checkDest 94F- :checkSrc ; check the source port is for the current connection 94F- 01D bank TCB_BANK 950- 93F call NICReadAgain_4 951- 192 xor w, tcbRemotePortMSB 952- 743 sz ; is the high byte the same? 953- B94 jmp :ignorePacket ; no, ignore the packet 954- 93F call NICReadAgain_4 ; get the low byte 955- 193 xor w, tcbRemotePortLSB 956- 743 sz ; is the low byte the same? 957- B94 jmp :ignorePacket ; no, ignore the packet ; 958- :checkDest ; check the destination port matches our port 958- 93F call NICReadAgain_4 959- 190 xor w, tcbLocalPortMSB 95A- 743 sz ; is the high byte the same? 95B- B94 jmp :ignorePacket ; no, ignore the packet 95C- 93F call NICReadAgain_4 ; get the low byte 95D- 191 xor w, tcbLocalPortLSB 95E- 743 sz ; Is the low byte the same? 95F- B94 jmp :ignorePacket ; no, ignore the packet ; 960- 01C bank TCP_BANK 961- 93F call NICReadAgain_4 962- 031 mov tcpTmpSeq4, w 963- 93F call NICReadAgain_4 964- 032 mov tcpTmpSeq3, w 965- 93F call NICReadAgain_4 966- 033 mov tcpTmpSeq2, w 967- 93F call NICReadAgain_4 968- 034 mov tcpTmpSeq1, w ; 969- 93F call NICReadAgain_4 96A- 035 mov tcpTmpAck4, w 96B- 93F call NICReadAgain_4 96C- 036 mov tcpTmpAck3, w 96D- 93F call NICReadAgain_4 96E- 037 mov tcpTmpAck2,w 96F- 93F call NICReadAgain_4 970- 038 mov tcpTmpAck1, w ; 971- 93F call NICReadAgain_4 ; receive the data offset. Used to skip the options 972- EF0 and w, #TCP_OFFSET_MASK ; mask out the offset 973- 01D bank TCB_BANK 974- 03C mov tcbOffset, w 975- 403 clc 976- 33C rr tcbOffset ; shift right to get the number of bytes 977- 33C rr tcbOffset ; ipLength = tcpLength = length of TCP data 978- 21C mov w, tcbOffset ; size of TCP header in bytes 979- 01A bank IP_BANK 97A- 0BB sub ipLengthLSB, w ; subtract out size of TCP header 97B- 21B mov w, ipLengthLSB 97C- 01C bank TCP_BANK 97D- 03F mov tcpLengthLSB, w 97E- 01A bank IP_BANK 97F- 703 sc 980- 0FA dec ipLengthMSB 981- 21A mov w, ipLengthMSB 982- 01C bank TCP_BANK 983- 03E mov tcpLengthMSB, w ; 984- 93F call NICReadAgain_4 ; receive the flags 985- 03B mov tcpRxFlags, w 986- 01D bank TCB_BANK 987- 03D mov tcbFlags, w ; take a copy of the flags ; 988- 93F call NICReadAgain_4 989- 03E mov tcbSendWinMSB, w ; receive the window 98A- 93F call NICReadAgain_4 98B- 03F mov tcbSendWinLSB, w ; ,, ; skip over these 98C- 01D bank TCB_BANK 98D- C10 0BC sub tcbOffset, #((TCP_HDR_LENGTH<<2)-4) 98F- 93F :loop call NICReadAgain_4 990- 2FC decsz tcbOffset 991- B8F jmp :loop 992- 443 clz 993- 00D retp 994- :ignorePacket ; ignore the rest of the packet. 994- 943 call NICDumpRxFrame_4 ; ## Need to send a reset in response to this packet. ; ## Unfortunately sending a packet would overwrite the TCB. ; ## Need to create a second TCB? 995- 543 stz 996- 00D retp ; ****************************************************************************** 997- _TCPUpdateSeq ; Add an 16-bit number to outgoing Sequence nr ; INPUT: {tcbSndUna1-4}{tcpUnAckMSB/LSB} = number to add ; OUTPUT: {tcbSndUna1-4} ; ****************************************************************************** 997- 01C bank TCP_BANK 998- 21A mov w, tcpUnAckLSB 999- 01D bank TCB_BANK 99A- 1F7 add tcbSndUna1, w 99B- 01C bank TCP_BANK 99C- 219 mov w, tcpUnAckMSB 99D- 603 snc 99E- 299 mov w, ++tcpUnAckMSB 99F- 01D bank TCB_BANK 9A0- 1F6 add tcbSndUna2, w 9A1- 703 sc 9A2- 00D retp 9A3- 3F5 incsz tcbSndUna3 9A4- 00D retp 9A5- 2B4 inc tcbSndUna4 9A6- 00D retp ; ****************************************************************************** 9A7- _TCPChkSeq ; This is called in the TCPProcPktIn to check if the received packet is the one ; expected or if it is a previous unacked packet. ; [TCP API Function] ; INPUT: none ; OUTPUT: z flag is set if the received packet is incorrect ; ****************************************************************************** 9A7- 97E call TCPCmpNxtSeq ; Check if received is expected 9A8- 643 BB8 jz :equal ; z is set if RCV.NXT == SEG.SEQ 9AA- _bank TCP_BANK 9AA- 01C 9AB- 4E4 9AC- 23A test tcpUnAckLSB 9AD- 743 sz 9AE- BB2 jmp :outstanding 9AF- 239 test tcpUnAckMSB 9B0- 643 snz 9B1- BBD jmp :noOutstanding 9B2- 904 :outstanding call TCPRestorePrev ; RCV.NXT = RCV.NXT - tcpUnAck 9B3- 97E call TCPCmpNxtSeq ; Check if received is ack on previous packet 9B4- 743 BBD jnz :noOutstanding ; z is set if RCV.NXT == SEG.SEQ 9B6- 543 setb z ; Return value = "OK" 9B7- 00D retp 9B8- :equal _bank TCP_BANK 9B8- 01C 9B9- 4E4 9BA- 07A clr tcpUnAckLSB 9BB- 079 clr tcpUnAckMSB ; Z is set (return value = "OK") 9BC- 00D retp 9BD- 4C5 :noOutstanding clrb LED_PIN ; DEBUG TODO 9BE- BBE jmp $ ; DEBUG ; ****************************************************************************** 9BF- _TCPRestorePrev ; Subtract an 16-bit number from RCV.NXT ; INPUT: {tcpUnAckLSB,tcpUnAckMSB} = number to add ; OUTPUT: {tcbRcvNxt1-4} ; ****************************************************************************** 9BF- 01C bank TCP_BANK 9C0- 21A mov w, tcpUnAckLSB 9C1- 01D bank TCB_BANK 9C2- 0BB sub tcbRcvNxt1, w 9C3- 01C bank TCP_BANK 9C4- 219 mov w, tcpUnAckMSB 9C5- 603 BCB jc :dontBorrow 9C7- 299 mov w, ++tcpUnAckMSB ; if prev.sub was negative 9C8- D00 test w ; carry on inc? 9C9- 643 BCF jz :exit ; yes (w = $100) 9CB- :dontBorrow 9CB- 01D bank TCB_BANK 9CC- 0BA sub tcbRcvNxt2, w 9CD- 603 snc ; c=0 => negative result 9CE- 00D retp 9CF- 01D :exit bank TCB_BANK 9D0- 239 test tcbRcvNxt3 9D1- 643 snz 9D2- 0F8 dec tcbRcvNxt4 9D3- 0F9 dec tcbRcvNxt3 9D4- 00D retp A00- ORG $A00 ; Page5 A00- BEF TCPAppRXDone jmp _TCPAppRXDone ; ****************************************************************************** A01- TCPAppInit ; Called repeatedly as long as TCP connection state is closed ; [TCP API Function] ; INPUT: none ; OUTPUT: none ; ****************************************************************************** A01- 01D bank TCB_BANK A02- C90 031 mov tcbLocalPortLSB, #HTTP_PORT_LSB A04- C1F 030 mov tcbLocalPortMSB, #HTTP_PORT_MSB A06- 01F bank HTTP_BANK A07- 077 clr httpParseState A08- 078 clr httpURIHash A09- 079 clr httpExtHash A0A- 014 A22 jmp @TCPAppPassiveOpen ; ****************************************************************************** A0C- 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: {tcpUnAckMSB,tcpUnAckLSB} = number of bytes to transmit ; ****************************************************************************** A0C- 01F bank HTTP_BANK A0D- C09 097 cjae httpParseState, #HTTP_PARSE_CLOSED, :closed A0F- 603 A19 A11- C08 097 cje httpParseState, #HTTP_PARSE_SENTLAST, :sentlast A13- 643 A3F A15- C01 097 cjae httpParseState, #HTTP_PARSE_URI, :send A17- 603 A1A A19- 00D :closed retp A1A- C07 037 :send mov httpParseState, #HTTP_PARSE_SENDING ; check how much there is to send A1C- 01F bank EEPROM_BANK A1D- C05 09D csae e2FileLenMSB, #(HTTP_SEG_SIZE>>8) A1F- 703 A20- A35 jmp :lastSegment ; msb#1 < msb#2 A21- C05 09D cse e2FileLenMSB, #(HTTP_SEG_SIZE>>8) A23- 743 A24- A29 jmp :notLast ; msb#1 > msb#2 A25- C87 1DE csa e2FileLenLSB, #(HTTP_SEG_SIZE&$00FF) A27- 703 A28- A35 jmp :lastSegment ; #1 <= #2 A29- :notLast ; not the last segment so send as much as possible (i.e. full segment) A29- C78 0BE sub e2FileLenLSB, #(HTTP_SEG_SIZE&$00FF) ; e2FileLen -= HTTP_SEG_SIZE A2B- 703 sc ; A2C- 0FD dec e2FileLenMSB ; A2D- C05 0BD sub e2FileLenMSB, #(HTTP_SEG_SIZE>>8) ; A2F- 01C bank TCP_BANK A30- C05 039 mov tcpUnAckMSB, #(HTTP_SEG_SIZE>>8) A32- C78 03A mov tcpUnAckLSB, #(HTTP_SEG_SIZE&$00FF) A34- 00D retp A35- :lastSegment ; last segment so send whatever is leftover A35- 21D mov w, e2FileLenMSB A36- 01C bank TCP_BANK A37- 039 mov tcpUnAckMSB, w A38- 01F bank EEPROM_BANK A39- 21E mov w, e2FileLenLSB A3A- 01C bank TCP_BANK A3B- 03A mov tcpUnAckLSB, w A3C- 01F bank HTTP_BANK A3D- 2B7 inc httpParseState ; next-state = HTTP_PARSE_CLOSING A3E- 00D retp A3F- :sentlast ; no more to send so we close A3F- 014 934 call @TCPAppClose A41- 2B7 inc httpParseState ; next-state = HTTP_PARSE_CLOSED A42- 00D retp ; ****************************************************************************** A43- 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 ; ****************************************************************************** IF HTTP A43- _bank HTTP_BANK A43- 01F A44- 4E4 A45- 016 942 call @E2Read8Ack ; Read next HTML byte from EEPROM. A47- 02C mov globTemp1, w ; save temporarily A48- C36 099 cje httpExtHash, #( HTTP_EXT_HASH_GIF ), :noop ; Skip the GIF's. A4A- 643 A58 A4C- C3A 099 cje httpExtHash, #( HTTP_EXT_HASH_PDF ), :noop ; Skip the PDF's. A4E- 643 A58 A50- C41 099 cje httpExtHash, #( HTTP_EXT_HASH_JPG ), :noop ; Skip the JPG's. A52- 643 A58 A54- C80 08C cjae globTemp1, #$80, :specialChar A56- 603 A5A A58- 20C :noop mov w, globTemp1 A59- 00D retp ; Return normal character. A5A- :specialChar ; process magic number in file indicating Dynamic content A5A- :f0 _bank MISC_BANK A5A- 018 A5B- 5E4 A5C- CF0 08C cjne globTemp1, #$F0, :f1 A5E- 743 A63 A60- 211 mov w, bcd3+0 ; send BCD A61- 016 A94 jmp @BCDToASCII ; Just send 1 Char. A63- CF1 08C :f1 cjne globTemp1, #$F1, :f2 A65- 743 A6A A67- 212 mov w, bcd3+1 ; send BCD A68- 016 A94 jmp @BCDToASCII ; Just send 1 Char. A6A- CF2 08C :f2 cjne globTemp1, #$F2, :f3 A6C- 743 A71 A6E- 213 mov w, bcd3+2 ; send BCD A6F- 016 A94 jmp @BCDToASCII ; Just send 1 Char. A71- :f3 IF X10 A71- _bank X10_BANK A71- 01C A72- 5E4 A73- CF3 08C cjne globTemp1, #$F3, :fSeven A75- 743 A82 A77- 292 mov w, ++x10Unit ; What house code are we watching? A78- 9DD call :sendW ; format unit number. A79- _bank X10_BANK A79- 01C A7A- 5E4 A7B- 210 02C mov globTemp1, x10HouseCode A7D- 403 clc ; Return House Code letter code. A7E- C41 1EC add globTemp1, #'A' ; Convert to alphabetic. A80- 20C mov w, globtemp1 A81- 00D retp ; return with alphabetic. A82- CF7 08C :fSeven cjne globTemp1, #$F7, :f4 A84- 743 A92 A86- 292 mov w, ++x10Unit ; What house code was last used? A87- 9DD call :sendW ; format unit number. A88- _bank X10_BANK A88- 01C A89- 5E4 A8A- 211 02C mov globTemp1, x10House A8C- 403 clc ; Return House Code letter code. A8D- C41 1EC add globTemp1, #'A' ; Convert to alphabetic. A8F- 20C mov w, globtemp1 A90- 00D retp ; return with alphabetic. ENDIF ; X10 A91- ADA jmp :default ; DEBUG ; Quick substitutions for mem locations < $80 A92- :f4 _bank HTTP_BANK A92- 01F A93- 4E4 A94- CF4 08C cjne globTemp1, #$F4, :f5 A96- 743 A9A A98- 21A mov w, httpPageCount A99- ADD jmp :sendW A9A- CF5 08C :f5 cjne globTemp1, #$F5, :f6 A9C- 743 AA0 A9E- 218 mov w, httpURIHash A9F- ADD jmp :sendW AA0- CF6 08C :f6 cjne globTemp1, #$F6, :f8 AA2- 743 AA6 AA4- 219 mov w, httpEXTHash AA5- ADD jmp :sendW AA6- :f8 _bank TIMER_BANK AA6- 01F AA7- 4E4 AA8- CF8 08C cjne globTemp1, #$F8, :f9 AAA- 743 AAE AAC- 211 mov w, ArpTimerMSB AAD- ADD jmp :sendW AAE- CF9 08C :f9 cjne globTemp1, #$F9, :fa AB0- 743 AB4 AB2- 213 mov w, tcpTimerMSB AB3- ADD jmp :sendW AB4- CFA 08C :fa cjne globTemp1, #$FA, :fb AB6- 743 ABA AB8- 215 mov w, connTimerMSB AB9- ADD jmp :sendW ABA- :fb _bank TCP_BANK ABA- 01C ABB- 4E4 ABC- CFB 08C cjne globTemp1, #$FB, :fc ABE- 743 AC2 AC0- 210 mov w, tcpState AC1- ADD jmp :sendW ; Quick substitutions for constants. AC2- CFC 08C :fc cjne globTemp1, #$FC, :fd AC4- 743 AC8 AC6- C00 mov w, #PGM_VERSION ; Version of Program AC7- ADD jmp :sendW AC8- CFD 08C :fd cjne globTemp1, #$FD, :fe ACA- 743 ACE ACC- C0A mov w, #PGM_RELEASE ; Release of Program ACD- ADD jmp :sendW ; Special processing for display... ACE- :fe _bank ADC_BANK ACE- 018 ACF- 5E4 AD0- CFF 08C :ff cjne globTemp1, #$FF, :default AD2- 743 ADA AD4- CB7 02C mov globTemp1, #183 ; Temperature fudge factor = b-mX AD6- 214 mov w, adc ; 1.125 factor found thru regression. ; clc ; rr wreg ; m = 0.5X ; clc ; rr wreg ; m = 0.25X ; clc ; rr wreg ; m = 0.125X ; add w, adc ; m += 1.0X AD7- 0AC sub globtemp1, w AD8- 20C mov w, globTemp1 AD9- ADD jmp :sendW ADA- 20C :default mov w, globTemp1 ADB- 024 mov fsr, w ; Use code as index into memory. ADC- 200 mov w, indf ; jmp :sendW ADD- 02C :sendW mov globTemp1, w ADE- C81 024 mov fsr, #bcd3 ; FSR Pointer for Bin8ToBCD AE0- 20C mov w, globTemp1 AE1- 016 97A call @Bin8ToBCD AE3- 211 mov w, bcd3+0 ; return with first BCD AE4- 016 A94 jmp @BCDToASCII ; Just send 1 Char. ENDIF ; HTTP ; ****************************************************************************** AE6- 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 ; ****************************************************************************** AE6- 00D retp ; ****************************************************************************** AE7- 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 ; ****************************************************************************** AE7- 00D retp ; ****************************************************************************** AE8- TCPAppRxData ; Called once for each byte received in a packet. ; [TCP API Function] ; INPUT: w = received data byte ; OUTPUT: none ; ****************************************************************************** AE8- 02C mov globTemp1, w AE9- 01F bank HTTP_BANK ; HTTP Parser for GET method only AEA- C00 097 cje httpParseState, #HTTP_PARSE_METHOD, :getMethod AEC- 643 B06 AEE- C01 097 cje httpParseState, #HTTP_PARSE_URI, :getURI AF0- 643 B0D IF X10 AF2- C02 097 cje httpParseState, #HTTP_PARSE_HOUSE, :getHouse AF4- 643 B61 AF6- C03 097 cje httpParseState, #HTTP_PARSE_UNIT, :getUnit AF8- 643 B77 AFA- C04 097 cje httpParseState, #HTTP_PARSE_EQUALS, :getEquals AFC- 643 B94 AFE- C05 097 cje httpParseState, #HTTP_PARSE_CMD, :getCmd B00- 643 B9A ENDIF B02- 00D retp B03- C06 037 :getEOL mov httpPArseState, #HTTP_PARSE_EOL B05- 00D retp B06- C20 08C :getMethod cje globTemp1, #' ', :gotMethod B08- 643 B0B B0A- 00D retp B0B- 2B7 :gotMethod inc httpParseState B0C- 00D retp B0D- 20C 02E :getURI mov globTemp3, globTemp1 B0F- C20 08C cje globTemp1, #' ', :gotURI B11- 643 B2C B13- C23 08C cje globTemp1, #'#', :gotURI B15- 643 B2C B17- C3F 08C cje globTemp1, #'?', :gotURI B19- 643 B2C B1B- C0D 08C cje globTemp1, #$0D, :gotURI B1D- 643 B2C B1F- C0A 08C cje globTemp1, #$0A, :gotURI B21- 643 B2C B23- 20C 1F8 add httpURIHash, globTemp1 ; Accumulate hash of URI. B25- 20C 1F9 add httpExtHash, globTemp1 ; Accumulate hash of file type. B27- C2E 08C csne globTemp1, #'.' ; Zero type hash after dot. B29- 643 B2A- 079 clr httpExtHash B2B- 00D retp B2C- :gotURI ; obtain pointer to file ; cjne httpURIHash, #HTTP_URI_HASH_ROOT, :gotURI1 ; ; mov httpExtHash, #HTTP_EXT_HASH_DEFAULT ; mov w, #HTTP_URI_HASH_DEFAULT ; Force Default page. ; jmp :gotURI2 ; But keep Hash value. B2C- 218 :gotURI1 mov w, httpURIHash B2D- 01F :gotURI2 bank EEPROM_BANK B2E- 03C mov e2AddrLSB, w B2F- 07B clr e2AddrMSB B30- 403 clc ; e2Addr = httpURIHash * 2 B31- 37C rl e2AddrLSB ; B32- 37B rl e2AddrMSB ; B33- 010 95E call @E2Init ; reset EEPROM B35- 016 970 call @E2SetAddr B37- 016 966 call @E2SendRdCmd B39- 016 942 call @E2Read8Ack B3B- 03B mov e2AddrMSB, w B3C- 016 947 call @E2Read8NoAckStop B3E- 03C mov e2AddrLSB, w ; start reading from file B3F- 016 970 call @E2SetAddr B41- 016 966 call @E2SendRdCmd ; file length B43- 016 942 call @E2Read8Ack B45- 03D mov e2FileLenMSB, w B46- 016 942 call @E2Read8Ack B48- 03E mov e2FileLenLSB, w B49- 11D or w, e2FileLenMSB ; Any data? B4A- 743 B52 jnz :gotURI4 B4C- _bank HTTP_BANK B4C- 01F B4D- 4E4 B4E- C49 039 mov httpExtHash, #HTTP_EXT_HASH_404 B50- C3E mov w, #HTTP_URI_HASH_404 ; Force 404 message. B51- B2D jmp :gotURI2 ; But keep Hash value. B52- :gotURI4 ; file checksum (ignore) B52- 016 942 call @E2Read8Ack B54- 016 942 call @E2Read8Ack B56- 2BA inc httpPageCount ; Over 1 billion served!... B57- C3F 08E :getQuestion cjne globTemp3, #'?', :getEOL B59- 743 B03 B5B- 2B7 :gotQuestion inc httpParseState IF X10 B5C- _bank X10_BANK B5C- 01C B5D- 5E4 B5E- 210 031 mov x10House, x10HouseCode ; load default House Code. ENDIF ; X10 B60- 00D retp IF X10 B61- CAF 1CC :getHouse cja globTemp1, #'P', :getEOL B63- 603 B03 B65- C41 08C cjb globTemp1, #'A', :getEOL B67- 703 B03 B69- C41 0AC sub globTemp1, #'A' ; Strip high bits. B6B- _bank X10_BANK B6B- 01C B6C- 5E4 B6D- 20C 031 mov x10House, globTemp1 B6F- :gotHouse _bank HTTP_BANK B6F- 01F B70- 4E4 B71- 2B7 inc httpParseState B72- _bank X10_BANK B72- 01C B73- 5E4 B74- C00 032 mov x10Unit, #0 ; load default Unit Code. B76- 00D retp B77- CC6 1CC :getUnit cja globTemp1, #'9', :gotUnit B79- 603 B8C B7B- C30 08C cjb globTemp1, #'0', :gotUnit B7D- 703 B8C B7F- C30 0AC sub globTemp1, #'0' ; Strip high bits. B81- _bank X10_BANK B81- 01C B82- 5E4 B83- 212 mov w, x10Unit ; Multiply old Unit value by ten. B84- 403 clc ; B85- 361 rl WREG ; B86- 361 rl WREG ; B87- 1D2 add w, x10Unit ; B88- 361 rl WREG ; B89- 1CC :addUnit add w, globTemp1 ; ...and add ones digit. B8A- 032 mov x10Unit, w B8B- 00D retp B8C- :gotUnit _bank X10_BANK B8C- 01C B8D- 5E4 B8E- 232 test x10Unit B8F- 743 sz B90- 0F2 dec x10Unit ; Get result from 1-16 to 0-15 B91- _bank HTTP_BANK B91- 01F B92- 4E4 B93- 2B7 inc httpParseState B94- C3D 08C :getEquals cjne globTemp1, #'=', :getEOL B96- 743 B03 B98- 2B7 :gotEquals inc httpParseState B99- 00D retp B9A- C20 08C :getCmd cje globTemp1, #' ', :noCmd B9C- 643 BE2 B9E- C23 08C cje globTemp1, #'#', :noCmd BA0- 643 BE2 BA2- C3F 08C cje globTemp1, #'?', :noCmd BA4- 643 BE2 BA6- C0D 08C cje globTemp1, #$0D, :noCmd BA8- 643 BE2 BAA- C0A 08C cje globTemp1, #$0A, :noCmd BAC- 643 BE2 BAE- C4F 08C csne globTemp1, #'O' BB0- 643 BB1- 00D retp ; Skip the "O" in "ON" and "OFF". BB2- C4E 08C cjne globTemp1, #'N', $+6 BB4- 743 BB8 BB6- C01 mov w, #X10_CMD_ON BB7- BE6 jmp :gotCmd BB8- C46 08C cjne globTemp1, #'F', $+6 BBA- 743 BBE BBC- C02 mov w, #X10_CMD_OFF BBD- BE6 jmp :gotCmd BBE- C42 08C cjne globTemp1, #'B', $+6 BC0- 743 BC4 BC2- C04 mov w, #X10_CMD_BRIGHT BC3- BE6 jmp :gotCmd BC4- C44 08C cjne globTemp1, #'D', $+6 BC6- 743 BCA BC8- C03 mov w, #X10_CMD_DIM BC9- BE6 jmp :gotCmd BCA- C3E 08C cjne globTemp1, #'>', $+6 BCC- 743 BD0 BCE- C05 mov w, #X10_CMD_ALL_ON BCF- BE6 jmp :gotCmd BD0- C3C 08C cjne globTemp1, #'<', $+6 BD2- 743 BD6 BD4- C06 mov w, #X10_CMD_ALL_OFF BD5- BE6 jmp :gotCmd BD6- C2B 08C cjne globTemp1, #'+', $+6 BD8- 743 BDC BDA- C07 mov w, #X10_CMD_LIGHTS_ON BDB- BE6 jmp :gotCmd BDC- C2D 08C cjne globTemp1, #'-', $+6 BDE- 743 BE2 BE0- C08 mov w, #X10_CMD_LIGHTS_OFF BE1- BE6 jmp :gotCmd BE2- :noCmd _bank HTTP_BANK BE2- 01F BE3- 4E4 BE4- 2B7 inc httpParseState BE5- 00D retp BE6- :gotCmd _bank X10_BANK BE6- 01C BE7- 5E4 BE8- 033 mov x10Cmd, w BE9- 017 901 call @x10Send ; Execute the House/Unit/Cmd in X10. BEB- _bank HTTP_BANK BEB- 01F BEC- 4E4 BED- 2B7 inc httpParseState BEE- 00D retp ENDIF ; X10 ; ****************************************************************************** BEF- _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 ; ****************************************************************************** BEF- 00D retp C00- ORG $C00 ; Page6 ; E2Delay600ns jmp _E2Delay600ns ; E2Delay900ns jmp _E2Delay900ns ; E2Delay1300ns jmp _E2Delay1300ns ; E2SDAInput jmp _E2SDAInput ; E2SDAOutputHi jmp _E2SDAOutputHI ; E2SDAOutputLo jmp _E2SDAOutputLo ; E2GenStartCond jmp _E2GenStartCond ; E2GenStopCond jmp _E2GenStopCond ; E2Read8Ack jmp _E2Read8Ack ; E2Write8 jmp _E2Write8 ; E2Read8 jmp _E2Read8 ; 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 IF DHCP DHCPREQUESTSend jmp _DHCPREQUESTSend ENDIF ; ****************************************************************************** C00- E2Delay600ns ; Delay 600ns ; INPUT: none ; OUTPUT: none ; ****************************************************************************** C00- C06 mov w, #6 C01- 2E1 :loop decsz wreg C02- A01 jmp :loop C03- 00D retp ; ****************************************************************************** C04- E2Delay900ns ; Delay 900ns ; INPUT: none ; OUTPUT: none ; ****************************************************************************** C04- C08 mov w, #8 C05- 2E1 :loop decsz wreg C06- A05 jmp :loop C07- 00D retp ; ****************************************************************************** C08- E2Delay1300ns ; Delay 1300ns ; INPUT: none ; OUTPUT: none ; ****************************************************************************** C08- C0D mov w, #13 C09- 2E1 :loop decsz wreg C0A- A09 jmp :loop C0B- 00D retp ; ****************************************************************************** C0C- E2SDAInput C0C- E2SDAOutputHi ; Set SDA as input ; INPUT: none ; OUTPUT: none ; ****************************************************************************** C0C- CAA 005 mov !E2_PORT, #E2_DDR_SDA_IN C0E- 00D retp ; ****************************************************************************** C0F- E2SDAOutputLo ; Set SDA as output-low ; INPUT: none ; OUTPUT: none ; ****************************************************************************** C0F- 4A5 clrb E2SDA_PIN C10- C8A 005 mov !E2_PORT, #E2_DDR_SDA_OUT C12- 00D retp ; ****************************************************************************** C13- E2GenStartCond ; Generate START condition ; INPUT: none ; OUTPUT: none ; ****************************************************************************** C13- 90C call E2SDAOutputHi C14- 585 setb E2SCL_PIN C15- 900 call E2Delay600ns C16- 90F call E2SDAOutputLo C17- 900 call E2Delay600ns C18- 485 clrb E2SCL_PIN C19- 900 call E2Delay600ns C1A- 00D retp ; ****************************************************************************** C1B- E2GenStopCond ; Generate STOP condition ; INPUT: none ; OUTPUT: none ; ****************************************************************************** C1B- 90F call E2SDAOutputLo C1C- 585 setb E2SCL_PIN C1D- 900 call E2Delay600ns C1E- 90C call E2SDAOutputHi C1F- 908 call E2Delay1300ns C20- 00D retp ; ****************************************************************************** C21- E2Write8 ; Write 8 bits out the I2C bus ; INPUT: w = data to write ; OUTPUT: none ; ****************************************************************************** C21- 02C mov globTemp1, w ; data buffer C22- C08 02D mov globTemp2, #8 ; bit counter C24- 904 :loop call E2Delay900ns C25- 7EC sb globTemp1.7 C26- 90F call E2SDAOutputLo C27- 6EC snb globTemp1.7 C28- 90C call E2SDAOutputHi C29- 904 call E2Delay900ns C2A- 585 setb E2SCL_PIN C2B- 900 call E2Delay600ns C2C- 485 clrb E2SCL_PIN C2D- 36C rl globTemp1 C2E- 2ED decsz globTemp2 C2F- A24 jmp :loop C30- 00D retp ; ****************************************************************************** C31- E2Read8 ; Read 8 bits from the I2C bus ; INPUT: none ; OUTPUT: w = data read ; ****************************************************************************** C31- 90C call E2SDAInput C32- C08 02D mov globTemp2, #8 ; bit counter C34- 904 :loop call E2Delay900ns C35- 7A5 sb E2SDA_PIN C36- 403 clc C37- 6A5 snb E2SDA_PIN C38- 503 stc C39- 36C rl globTemp1 C3A- 585 setb E2SCL_PIN C3B- 900 call E2Delay600ns C3C- 485 clrb E2SCL_PIN C3D- 904 call E2Delay900ns C3E- 2ED decsz globTemp2 C3F- A34 jmp :loop C40- 20C mov w, globTemp1 C41- 00D retp ; ****************************************************************************** C42- E2Read8Ack ; Read 8 bits from the I2C bus and send ACK ; INPUT: none ; OUTPUT: w = data read ; ****************************************************************************** C42- 931 call E2Read8 C43- 02C mov globTemp1, w C44- 958 call E2SendAck C45- 20C mov w, globTemp1 C46- 00D retp ; ****************************************************************************** C47- 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 ; ****************************************************************************** C47- 931 call E2Read8 C48- 02C mov globTemp1, w C49- 95F call E2SendNotAck C4A- 91B call E2GenStopCond C4B- 20C mov w, globTemp1 C4C- 00D retp ; ****************************************************************************** C4D- E2RecvAck ; Receive ACK bit from I2C receiver ; INPUT: none ; OUTPUT: z: 1 = received ACK, 0 = didn't receive ACK ; ****************************************************************************** C4D- 90C call E2SDAInput C4E- 904 call E2Delay900ns C4F- 585 setb E2SCL_PIN C50- 7A5 sb E2SDA_PIN C51- 543 stz C52- 6A5 snb E2SDA_PIN C53- 443 clz C54- 900 call E2Delay600ns C55- 485 clrb E2SCL_PIN C56- 904 call E2Delay900ns C57- 00D retp ; ****************************************************************************** C58- E2SendAck ; Send ACK bit as acknowledge ; INPUT: none ; ****************************************************************************** C58- 90F call E2SDAOutputLo C59- 904 call E2Delay900ns C5A- 585 setb E2SCL_PIN C5B- 900 call E2Delay600ns C5C- 485 clrb E2SCL_PIN C5D- 904 call E2Delay900ns C5E- 00D retp ; ****************************************************************************** C5F- E2SendNotAck ; Send ACK bit as not-acknowledge ; INPUT: none ; ****************************************************************************** C5F- 90C call E2SDAOutputHi C60- 904 call E2Delay900ns C61- 585 setb E2SCL_PIN C62- 900 call E2Delay600ns C63- 485 clrb E2SCL_PIN C64- 904 call E2Delay900ns C65- 00D retp ; ****************************************************************************** C66- E2SendRdCmd ; Tell I2C device we wish to read from it for this transaction ; INPUT: none ; OUTPUT: none ; ****************************************************************************** C66- 913 call E2GenStartCond C67- CA1 mov w, #E2_CMD_RD C68- 921 call E2Write8 C69- 94D call E2RecvAck C6A- 00D retp ; ****************************************************************************** C6B- E2SendWrCmd ; Tell I2C Device we wish to write to it for this transaction ; INPUT: none ; OUTPUT: none ; ****************************************************************************** C6B- 913 call E2GenStartCond C6C- CA0 mov w, #E2_CMD_WR C6D- 921 call E2Write8 C6E- 94D call E2RecvAck C6F- 00D retp ; ****************************************************************************** C70- E2SetAddr ; Set address pointer ; INPUT: {e2AddrMSB, e2AddrLSB} = address to set to ; OUTPUT: none ; ****************************************************************************** C70- 96B call E2SendWrCmd C71- _bank EEPROM_BANK C71- 01F C72- 4E4 C73- 21B mov w, e2AddrMSB C74- 921 call E2Write8 C75- 94D call E2RecvAck C76- 21C mov w, e2AddrLSB C77- 921 call E2Write8 C78- 94D call E2RecvAck C79- 00D retp ; ****************************************************************************** C7A- 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 ; ****************************************************************************** C7A- 060 clr indf C7B- 2A4 inc fsr C7C- 060 clr indf C7D- 2A4 inc fsr ; LSD C7E- 020 mov indf, w C7F- C64 :loopHun mov w, #100 C80- 080 mov w, indf-w C81- 703 A8A jnc :loopTen C83- 020 mov indf, w C84- 0E4 dec fsr C85- 0E4 dec fsr ; MSD C86- 2A0 inc indf C87- 2A4 inc fsr C88- 2A4 inc fsr ; LSD C89- A7F jmp :loopHun C8A- C0A :loopTen mov w, #10 C8B- 080 mov w, indf-w C8C- 703 sc C8D- A93 jmp :exit C8E- 020 mov indf, w C8F- 0E4 dec fsr C90- 2A0 inc indf C91- 2A4 inc fsr C92- A8A jmp :loopTen C93- 00D :exit retp ; ****************************************************************************** C94- BCDToASCII ; Converts an unpacked BCD number to an ASCII character ; INPUT: w = unpacked BCD ; OUTPUT: w = ASCII character ; ****************************************************************************** C94- 02C mov globTemp1, w C95- C30 mov w, #'0' C96- 1CC add w, globTemp1 C97- 00D retp IF UDP ; ****************************************************************************** NICReadAgain_6 ; Shortform for calling NICReadAgain(), which is in Page1 (This is in Page6) ; ****************************************************************************** jmp @NICReadAgain ; ****************************************************************************** NICWriteAgain_6 ; Shortform for calling NICWriteAgain(), which is in Page1 (This is in Page6) ; ****************************************************************************** jmp @NICWriteAgain ; ****************************************************************************** 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 _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 inc ipIdentLSB snz inc ipIdentMSB ; set IP for UDP mov ipProtocol, #17 ; compute IP call @IPGenCheckSum ; now we're ready to construct the IP header call @IPStartPktOut ; then construct the UDP header bank UDP_BANK ; UDP mov w, udpTxSrcPortMSB call NICWriteAgain_6 mov w, udpTxSrcPortLSB call NICWriteAgain_6 ; UDP mov w, udpTxDestPortMSB call NICWriteAgain_6 mov w, udpTxDestPortLSB call NICWriteAgain_6 ; UDP mov w, #8 add w, udpTxDataLenLSB mov w, udpTxDataLenMSB snc inc wreg call NICWriteAgain_6 mov w, #8 add w, udpTxDataLenLSB call NICWriteAgain_6 ; UDP = 0 mov w, #$0 call NICWriteAgain_6 call NICWriteAgain_6 retp ; ****************************************************************************** UDPEndPktOut ; Wraps up and transmits the UDP packet ; [UDP API Function] ; INPUT: none ; OUTPUT: none ; ****************************************************************************** _bank NIC_BANK jmp @NICSendTxFrame ; ****************************************************************************** UDPProcPktIn ; Processes an Incoming UDP packet ; INPUT: nicCurrPktPtr = points to beginning of received packet ; OUTPUT: none ; ****************************************************************************** bank UDP_BANK ; UDP call NICReadAgain_6 mov udpRxSrcPortMSB, w call NICReadAgain_6 mov udpRxSrcPortLSB, w ; UDP call NICReadAgain_6 xor w, udpRxDestPortMSB jnz :outtaHere call NICReadAgain_6 xor w, udpRxDestPortLSB jnz :outtaHere ; UDP call NICReadAgain_6 mov udpRxDataLenMSB, w call NICReadAgain_6 mov udpRxDataLenLSB, w ; ignore UDP REPT 2 call NICReadAgain_6 ENDR ; UDP snb flags.RX_IS_IP_BCST call UDPProcBcstPktIn sb flags.RX_IS_IP_BCST call @UDPAppProcPktIn :outtaHere call @NICDumpRxFrame retp IF DHCP ; ****************************************************************************** UDPProcBcstPktIn ; The only kind of broadcast UDP packets accepted are DHCP messages: DHCPOFFER ; and DHCPACK ; INPUT: none ; OUTPUT: myIP0-3 ; ****************************************************************************** clrb flags.GOT_DHCP_OFFER clrb flags.GOT_IP_ADDR call NICReadAgain_6 xor w, #2 ; check = BOOTP reply jnz :outtaHere call NICReadAgain_6 xor w, #1 ; check = 1 jnz :outtaHere call NICReadAgain_6 xor w, #6 ; check = 6 jnz :outtaHere ; ignore call NICReadAgain_6 ; check = 0xABABABAB REPT 4 call NICReadAgain_6 xor w, #$AB jnz :outtaHere ENDR ; ignore , , mov globTemp1, #(2+2+4) :loop1 call NICReadAgain_6 decsz globTemp1 jmp :loop1 ; record bank IP_BANK call NICReadAgain_6 mov myIP3, w call NICReadAgain_6 mov myIP2, w call NICReadAgain_6 mov myIP1, w call NICReadAgain_6 mov myIP0, w ; check if it is non-zero mov w, myIP3 or w, myIP2 or w, myIP1 or w, myIP0 jz :outtaHere ; skip , , , ; , , mov globTemp1, #(4+4+16+64+128+4) :loop2 call @NICPseudoRead decsz globTemp1 jmp :loop2 ; call NICReadAgain_6 xor w, #53 ; DHCP Message Type jnz :outtaHere call NICReadAgain_6 xor w, #1 jnz :outtaHere call NICReadAgain_6 xor w, #2 ; DHCPOFFER snz setb flags.GOT_DHCP_OFFER xor w, #2 xor w, #5 ; DHCPACK snz setb flags.GOT_IP_ADDR ; now search for that dang(!) :loop4 call NICReadAgain_6 xor w, #54 ; Server Identifier jz :foundServId call NICReadAgain_6 ; length mov globTemp1, w :loop3 call @NICPseudoRead decsz globTemp1 jmp :loop3 jmp :loop4 :foundServId call NICReadAgain_6 ; ignore length bank DHCP_BANK call NICReadAgain_6 mov dhcpServerId3, w call NICReadAgain_6 mov dhcpServerId2, w call NICReadAgain_6 mov dhcpServerId1, w call NICReadAgain_6 mov dhcpServerId0, w :outtaHere retp ; ****************************************************************************** DHCPSendCommon1 ; Helper function for DHCPDISCOVERSend and DHCPREQUESTSend ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; set ethernet addr to broadcast addr bank NIC_BANK mov w, #$FF mov nicRemoteEth0, w mov nicRemoteEth1, w mov nicRemoteEth2, w mov nicRemoteEth3, w mov nicRemoteEth4, w mov nicRemoteEth5, w ; set IP addr to broadcast addr bank IP_BANK mov w, #$FF mov remoteIP3, w mov remoteIP2, w mov remoteIP1, w mov remoteIP0, w ; tell ARP not to send out an ARP REQUEST for this pkt setb arpFlags.ARP_BYPASS bank UDP_BANK clr udpTxSrcPortMSB ; DHCP client mov udpTxSrcPortLSB, #68 ; clr udpTxDestPortMSB ; DHCP server mov udpTxDestPortLSB, #67 ; call @UDPStartPktOut ; mov w, #1 call NICWriteAgain_6 ; mov w, #1 call NICWriteAgain_6 ; mov w, #6 call NICWriteAgain_6 ; mov w, #0 call NICWriteAgain_6 ; = 0xABABABAB mov w, #$AB REPT 4 call NICWriteAgain_6 ENDR ; = 256 mov w, #1 REPT 2 call NICWriteAgain_6 ENDR ; mov w, #$80 call NICWriteAgain_6 mov w, #0 call NICWriteAgain_6 retp ; ****************************************************************************** DHCPSendCommon2 ; Helper function for DHCPDISCOVERSend and DHCPREQUESTSend ; INPUT: none ; OUTPUT: none ; ****************************************************************************** ; mov w, #SX_ETH_ADDR0 call NICWriteAgain_6 mov w, #SX_ETH_ADDR1 call NICWriteAgain_6 mov w, #SX_ETH_ADDR2 call NICWriteAgain_6 mov w, #SX_ETH_ADDR3 call NICWriteAgain_6 mov w, #SX_ETH_ADDR4 call NICWriteAgain_6 mov w, #SX_ETH_ADDR5 call NICWriteAgain_6 ; ,, mov globTemp1, #(10+64+128) mov w, #0 :loop2 call NICWriteAgain_6 decsz globTemp1 jmp :loop2 ; mov w, #99 call NICWriteAgain_6 mov w, #130 call NICWriteAgain_6 mov w, #83 call NICWriteAgain_6 mov w, #99 call NICWriteAgain_6 retp ; ****************************************************************************** DHCPDISCOVERSend ; Send DHCPDISCOVER message ; INPUT: none ; OUTPUT: none ; ****************************************************************************** bank UDP_BANK clr udpTxDataLenMSB mov udpTxDataLenLSB, #(240+3+0+1) ; without requested-IP option ;mov udpTxDataLenLSB, #(240+3+6+1) ; with requested-IP option call DHCPSendCommon1 ; , ,, = 0 mov globTemp1, #(4+4+4+4) mov w, #0 :loop1 call NICWriteAgain_6 decsz globTemp1 jmp :loop1 call DHCPSendCommon2 ; mov w, #53 call NICWriteAgain_6 mov w, #1 call NICWriteAgain_6 mov w, #1 ; DHCPDISCOVER call NICWriteAgain_6 ; -- optional ;mov w, #50 ;call NICWriteAgain_6 ;mov w, #4 ;call NICWriteAgain_6 ;mov w, #SX_IP_ADDR3 ;call NICWriteAgain_6 ;mov w, #SX_IP_ADDR2 ;call NICWriteAgain_6 ;mov w, #SX_IP_ADDR1 ;call NICWriteAgain_6 ;mov w, #SX_IP_ADDR0 ;call NICWriteAgain_6 ; -- not optional mov w, #255 call NICWriteAgain_6 ; and ... that should do it! call @UDPEndPktOut clrb arpFlags.ARP_BYPASS retp ; ****************************************************************************** _DHCPREQUESTSend ; Send DHCPREQUEST message ; INPUT: none ; OUTPUT: none ; ****************************************************************************** bank UDP_BANK mov udpTxDataLenMSB, #((240+3+6+6+1)>>8) mov udpTxDataLenLSB, #((240+3+6+6+1)&$FF) call DHCPSendCommon1 ; bank IP_BANK mov w, myIP3 call NICWriteAgain_6 mov w, myIP2 call NICWriteAgain_6 mov w, myIP1 call NICWriteAgain_6 mov w, myIP0 call NICWriteAgain_6 ; ,, = 0 mov globTemp1, #(4+4+4) mov w, #0 :loop1 call NICWriteAgain_6 decsz globTemp1 jmp :loop1 call DHCPSendCommon2 ; mov w, #53 call NICWriteAgain_6 mov w, #1 call NICWriteAgain_6 mov w, #3 ; DHCPREQUEST call NICWriteAgain_6 ; mov w, #54 ; option server identifier call NICWriteAgain_6 mov w, #4 ; length call NICWriteAgain_6 bank DHCP_BANK mov w, dhcpServerId3 call NICWriteAgain_6 mov w, dhcpServerId2 call NICWriteAgain_6 mov w, dhcpServerId1 call NICWriteAgain_6 mov w, dhcpServerId0 call NICWriteAgain_6 ; -- not optional mov w, #50 call NICWriteAgain_6 mov w, #4 call NICWriteAgain_6 bank IP_BANK mov w, myIP3 call NICWriteAgain_6 mov w, myIP2 call NICWriteAgain_6 mov w, myIP1 call NICWriteAgain_6 mov w, myIP0 call NICWriteAgain_6 ; -- not optional mov w, #255 call NICWriteAgain_6 ; and ... that should do it! call @UDPEndPktOut clrb arpFlags.ARP_BYPASS retp ELSE ; DHCP ; ****************************************************************************** UDPProcBcstPktIn ; The only kind of broadcast UDP packets accepted are DHCP messages: DHCPOFFER ; and DHCPACK ; INPUT: none ; OUTPUT: none ; ****************************************************************************** retp ; cus DHCP not enabled ENDIF ; DHCP ENDIF ; UDP E00- ORG $E00 ; Page7 (Holly Cow! Still not done??) IF X10 E00- A6B X10Init jmp _X10Init E01- A7E X10Send jmp _X10Send ENDIF ; X10 ; CM17A begin IF CM17A IF X10 ; ****************************************************************************** ; ; Support subroutines for CM17A Wireless X10 Interface ; ; ****************************************************************************** ; ; X10 RETW tables need to be at the top of a code page. ; E02- E0F cm17aHouse2Mask and w, #$0f ; Only 16 values. E03- _pc_check E03- 1E2 jmp PC+w E04- 860 870 retw %01100000,%01110000,%01000000,%01010000 ;ABCD E06- 840 850 E08- 880 890 retw %10000000,%10010000,%10100000,%10110000 ;EFGH E0A- 8A0 8B0 E0C- 8E0 8F0 retw %11100000,%11110000,%11000000,%11010000 ;IJKL E0E- 8C0 8D0 E10- 800 810 retw %00000000,%00010000,%00100000,%00110000 ;MNOP E12- 820 830 E14- _retw_check E14- E07 cm17aUnit2Mask and w, #$07 ; High bit is set in Data1 byte. E15- _pc_check E15- 1E2 jmp PC+w E16- 800 810 retw %00000000,%00010000,%00001000,%00011000 ;1234 E18- 808 818 E1A- 840 850 retw %01000000,%01010000,%01001000,%01011000 ;5678 E1C- 848 858 E1E- _retw_check E1E- 0E1 cm17aCmd2Mask dec WREG E1F- E07 and w, #$07 ; Only 8 values. E20- _pc_check E20- 1E2 jmp PC+w E21- 800 retw %00000000 ;ON E22- 820 retw %00100000 ;OFF E23- 898 retw %10011000 ;DIM E24- 888 retw %10001000 ;BRIGHT E25- 890 retw %10010000 ;ALL_ON same as LIGHTS_ON E26- 880 retw %10000000 ;ALL_OFF E27- 890 retw %10010000 ;LIGHTS_ON E28- 8A0 retw %10100000 ;LIGHTS_OFF E29- _retw_check ; ****************************************************************************** ; Send X10 comand to CM17A ; ****************************************************************************** E29- cm17aSendX10 _bank CM17A_BANK E29- 01C E2A- 5E4 ; Start sending data to cm17a E2B- _bank CM17A_BANK E2B- 01C E2C- 5E4 E2D- CD5 mov w, #CM17A_HEADER1 E2E- 957 call cm17aSendByte ; queue to send header byte1 E2F- CAA mov w, #CM17A_HEADER2 E30- 957 call cm17aSendByte ; queue to send header byte 2 ; Calculate house/unit/command code for transmission. E31- _bank X10_BANK E31- 01C E32- 5E4 E33- 211 mov w, x10House E34- 902 call cm17aHouse2Mask ; Convert House to bit code E35- _bank CM17A_BANK E35- 01C E36- 5E4 E37- 034 mov cm17aX10Data1, w E38- _bank X10_BANK E38- 01C E39- 5E4 E3A- C08 092 cjb x10Unit, #8, :lowUnit E3C- 703 A42 E3E- :highUnit _bank CM17A_BANK E3E- 01C E3F- 5E4 E40- C04 134 or cm17aX10Data1, #%0100 ; The Unit high-bit resides in upper byte. E42- :lowUnit E42- 214 mov w, cm17aX10Data1 E43- 957 call cm17aSendByte ; queue to send data byte 1 E44- _bank X10_BANK E44- 01C E45- 5E4 E46- 212 mov w, x10Unit E47- 914 call cm17aUnit2Mask ; Convert Unit to bit code. E48- _bank CM17A_BANK E48- 01C E49- 5E4 E4A- 035 mov cm17aX10Data2, w E4B- _bank X10_BANK E4B- 01C E4C- 5E4 E4D- 213 mov w, x10Cmd E4E- 91E call cm17aCmd2Mask ; Convert Cmd to bit mask. E4F- _bank CM17A_BANK E4F- 01C E50- 5E4 E51- 135 or cm17aX10Data2, w E52- 215 mov w, cm17aX10Data2 E53- 957 call cm17aSendByte ; queue to send data byte 2 E54- CAD mov w, #CM17A_Footer E55- 957 call cm17aSendByte ; queue to sebd footer byte E56- 00D retp ENDIF ; X10 ; ****************************************************************************** ; Send single byte of comand to CM17A ; ****************************************************************************** E57- 02C cm17aSendByte mov globTemp1, w E58- _bank CM17A_BANK E58- 01C E59- 5E4 E5A- C00 097 cjne cm17aBitCount, #0, $ ; Wait for previous X10 command. E5C- 743 A5A E5E- 20C 036 mov cm17aBitData, globTemp1 E60- C08 037 mov cm17aBitCount, #8 E62- 00D retp ; ****************************************************************************** ; Initialization Routine for CM17A ; ****************************************************************************** E63- cm17aInit E63- cm17aReset _bank CM17A_BANK E63- 01C E64- 5E4 E65- 077 clr cm17aBitCount E66- CFF 038 mov cm17aBitTimer, #CM17A_RESET_TIME E68- 505 setb CM17A_PORT.CM17A_PIN_DTR ; set X10 lines low E69- 545 setb CM17A_PORT.CM17A_PIN_RTS E6A- 00D retp ENDIF ; CM17A ; CM17A end IF UDP ; ****************************************************************************** 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 field in the UDP packet. ; [UDP API Function] ; INPUT: {udpRxDataLenMSB,udpRxDataLenLSB} = number of bytes in UDP ; {udpRxSrcPortMSB,udpRxSrcPortLSB} = UDP ; OUTPUT: none ; ****************************************************************************** call @NICReadAgain IF CREDENCE xor re, w ; toggle I/O pins _bank MISC_BANK mov ledPort, re ELSE and w, #%01000000 xor ra, w ; toggle I/O pins _bank MISC_BANK mov ledPort, ra ENDIF _bank UDP_BANK clr udpTxSrcPortMSB clr udpTxSrcPortLSB mov udpTxDestPortMSB, udpRxSrcPortMSB mov udpTxDestPortLSB, udpRxSrcPortLSB mov udpTxDataLenMSB, #0 mov udpTxDataLenLSB, #2 call @UDPStartPktOut IF CREDENCE mov w, re ; send new port state ELSE mov w, ra ; send new port state ENDIF call @NICWriteAgain mov w, #$00 ; one-byte padding call @NICWriteAgain call @UDPEndPktOut retp ENDIF ; UDP ; X10 begin IF X10 ; ****************************************************************************** E6B- _x10Init ; ****************************************************************************** E6B- _bank X10_BANK E6B- 01C E6C- 5E4 ; Which house are we watching? E6D- 209 mov w, X10_HOUSE_PORT ; read House Code from HEX switch. E6E- E0F and w, #$0F ; bits 0-3. E6F- F0F xor w, #$0F ; invert logic, if required. E70- 030 mov x10HouseCode, w ; seed values for display E71- 210 031 mov x10House, x10HouseCode E73- 072 clr x10Unit E74- 073 clr x10Cmd ; Clear the House State array. E75- CD0 mov w, #x10HouseState ; Point to array. E76- 024 mov fsr, w E77- 060 :loop clr indf ; Clear array. E78- 2A4 inc fsr E79- CE0 084 cjb fsr, #(x10HouseState+16), :loop E7B- 703 A77 E7D- 00D retp ; ****************************************************************************** E7E- _x10Send ; Record a command in state array, and call hardware rouitine to send command. ; ****************************************************************************** E7E- _bank X10_BANK E7E- 01C E7F- 5E4 E80- CF0 1D1 csbe x10House, #15 ; Is House code in range? E82- 603 E83- 00D retp E84- CF0 1D2 csbe x10Unit, #15 ; Is Unit in range? E86- 603 E87- 00D retp E88- 210 091 cjne x10House, x10HouseCode, :justsend ; House we're watching? E8A- 743 AE6 E8C- C01 093 cje x10Cmd, #X10_CMD_ON, :on E8E- 643 AAD E90- C02 093 cje x10Cmd, #X10_CMD_OFF, :off E92- 643 AB4 E94- C04 093 cje x10Cmd, #X10_CMD_BRIGHT, :bright E96- 643 ABB E98- C03 093 cje x10Cmd, #X10_CMD_DIM, :dim E9A- 643 AC7 E9C- C05 093 cje x10Cmd, #X10_CMD_ALL_ON, :allon E9E- 643 ADC EA0- C06 093 cje x10Cmd, #X10_CMD_ALL_OFF, :alloff EA2- 643 AD3 EA4- C07 093 cje x10Cmd, #X10_CMD_LIGHTS_ON, :allon EA6- 643 ADC EA8- C08 093 cje x10Cmd, #X10_CMD_LIGHTS_OFF, :alloff EAA- 643 AD3 EAC- 00D retp ; Unknown command. EAD- CD0 :on mov w, #x10HouseState ; Status table EAE- 403 clc EAF- 1D2 add w, x10Unit ; Index into status table EB0- 024 mov fsr, w EB1- C64 020 mov indf, #100 EB3- AE6 jmp :justsend EB4- CD0 :off mov w, #x10HouseState ; Status table EB5- 403 clc EB6- 1D2 add w, x10Unit ; Index into status table EB7- 024 mov fsr, w EB8- C00 020 mov indf, #0 EBA- AE6 jmp :justsend EBB- CD0 :bright mov w, #x10HouseState ; Status table EBC- 403 clc EBD- 1D2 add w, x10Unit ; Index into status table EBE- 024 mov fsr, w EBF- C64 080 cjae indf, #100, :justsend EC1- 603 AE6 EC3- 403 clc EC4- C05 1E0 add indf, #5 EC6- AE6 jmp :justsend EC7- CD0 :dim mov w, #x10HouseState ; Status table EC8- 403 clc EC9- 1D2 add w, x10Unit ; Index into status table ECA- 024 mov fsr, w ECB- C00 080 cje indf, #0, :justsend ECD- 643 AE6 ECF- 403 clc ED0- CFB 1E0 add indf, #-5 ED2- AE6 jmp :justsend ED3- CD0 :alloff mov w, #x10HouseState ; Point to array. ED4- 024 mov fsr, w ED5- :loopOff ED5- 060 clr indf ; Clear array. ED6- 2A4 inc fsr ED7- CE0 084 cjb fsr, #(x10HouseState+16), :loopOff ED9- 703 AD5 EDB- AE6 jmp :justsend EDC- CD0 :allon mov w, #x10HouseState ; Point to array. EDD- 024 mov fsr, w EDE- :loopOn EDE- C64 020 mov indf, #100 ; Clear array. EE0- 2A4 inc fsr EE1- CE0 084 cjb fsr, #(x10HouseState+16), :loopOn EE3- 703 ADE EE5- AE6 jmp :justsend EE6- :justsend IF CM17A EE6- 017 929 call @cm17aSendX10 ENDIF ; CM17A EE8- 00D retp ENDIF ; X10 ; X10 end ; *********** ; *** END *** ; *********** END