list p=pic16c74
__config h'3ffa' ;HS crystal, 20Mhz
include <p16c74.inc>
;
; *Change these* : Configuration equates.
;
IP1 equ d'192' ;first octet of IP address
IP2 equ d'168' ;second octet of IP address
IP3 equ d'1' ;third octet of IP address
IP4 equ d'2' ;fourth octet of IP address
;
MAC1 equ 0x00 ;\
MAC2 equ 0x00 ; \
MAC3 equ 0x00 ; \
MAC4 equ 0x12 ; 48 bit IEEE OUI (Organizationally Unique Identifier)
MAC5 equ 0x34 ; /
MAC6 equ 0x56 ;/
;
; Some useful macros
;
ppRD macro addr ;Read PacketPage port
movlw addr&0xff
movwf offsetL
movlw addr>>8
movwf offsetH
call ReadPP
endm
;
ppWR macro addr,val ;Write PacketPage port
movlw addr&0xff
movwf offsetL
movlw addr>>8
movwf offsetH
movlw val&0xff
movwf valueL
movlw val>>8
movwf valueH
call WritePP
endm
;
Dinput macro ;Change the data bus to input
bsf STATUS,RP0
movlw 0xff
movwf TRISB
bcf STATUS,RP0
endm
;
Doutput macro ;Change the data bus to output
bsf STATUS,RP0
clrf TRISB
bcf STATUS,RP0
endm
;
ior macro port ;I/O port read
movlw port
call ioRead
endm
;
iow macro port ;I/O port write
movwf PORTB
movlw port
movwf PORTA
call ioWrite
endm
;
; Crystal CS8900 PacketPage equates
;
portRxTxData equ 0x00 ;Receive/Transmit data (port 0)
portRxTxData1 equ 0x02 ;Receive/Transmit data (port 0)
portTxCmd equ 0x04 ;Transmit Commnad
portTxLength equ 0x06 ;Transmit Length
portISQ equ 0x08 ;Interrupt status queue
portPtr equ 0x0a ;PacketPage pointer
portData equ 0x0c ;PacketPage data (port 0)
portData1 equ 0x0e ;PacketPage data (port 1)
;
; CS8900 PacketPage Offsets
;
ppEISA equ 0x0000 ;EISA Registration number of CS8900
ppProdID equ 0x0002 ;Product ID Number
ppIOBase equ 0x0020 ;I/O Base Address
ppIntNum equ 0x0022 ;Interrupt number (0,1,2, or 3)
ppMemBase equ 0x002C ;Memory Base address register (20 bit)
ppRxCfg equ 0x0102 ;Receiver Configuration
ppRxCtl equ 0x0104 ;Receiver Control
ppTxCfg equ 0x0106 ;Transmit Configuration
ppBufCfg equ 0x010A ;Buffer Configuration
ppLineCtl equ 0x0112 ;Line Control
ppSelfCtl equ 0x0114 ;Self Control
ppBusCtl equ 0x0116 ;Bus Control
ppTestCtl equ 0x0118 ;Test Control
ppISQ equ 0x0120 ;Interrupt status queue
ppRxEvt equ 0x0124 ;Receiver Event
ppTxEvt equ 0x0128 ;Transmitter Event
ppBufEvt equ 0x012C ;Buffer Event
ppRxMiss equ 0x0130 ;Receiver Miss Counter
ppTxCol equ 0x0132 ;Transmit Collision Counter
ppLineSt equ 0x0134 ;Line Status
ppSelfSt equ 0x0136 ;Self Status
ppBusSt equ 0x0138 ;Bus Status
ppTxCmd equ 0x0144 ;Transmit Command Request
ppTxLength equ 0x0146 ;Transmit Length
ppIndAddr equ 0x0158 ;Individual Address (IA)
ppRxStat equ 0x0400 ;Receive Status
ppRxLength equ 0x0402 ;Receive Length
ppRxFrame equ 0x0404 ;Receive Frame Location
ppTxFrame equ 0x0A00 ;Transmit Frame Location
;
; Register Numbers
;
REG_NUM_MASK equ 0x003F
REG_NUM_RX_EVENT equ 0x0004
REG_NUM_TX_EVENT equ 0x0008
REG_NUM_BUF_EVENT equ 0x000C
REG_NUM_RX_MISS equ 0x0010
REG_NUM_TX_COL equ 0x0012
;
; Self Control Register
;
SELF_CTL_RESET equ 0x0040
SELF_CTL_HC1E equ 0x2000
SELF_CTL_HCB1 equ 0x8000
;
; Self Status Register
;
SELF_ST_INIT_DONE equ 0x0080
SELF_ST_SI_BUSY equ 0x0100
SELF_ST_EEP_PRES equ 0x0200
SELF_ST_EEP_OK equ 0x0400
SELF_ST_EL_PRES equ 0x0800
;
; Bus Control Register
;
BUS_CTL_USE_SA equ 0x0200
BUS_CTL_MEM_MODE equ 0x0400
BUS_CTL_IOCHRDY equ 0x1000
BUS_CTL_INT_ENBL equ 0x8000
;
; Bus Status Register
;
BUS_ST_TX_BID_ERR equ 0x0080
BUS_ST_RDY4TXNOW equ 0x0100
;
; Line Control Register
;
LINE_CTL_RX_ON equ 0x0040
LINE_CTL_TX_ON equ 0x0080
LINE_CTL_AUI_ONLY equ 0x0100
LINE_CTL_10BASET equ 0x0000
;
; Test Control Register
;
TEST_CTL_DIS_LT equ 0x0080
TEST_CTL_ENDEC_LP equ 0x0200
TEST_CTL_AUI_LOOP equ 0x0400
TEST_CTL_DIS_BKOFF equ 0x0800
TEST_CTL_FDX equ 0x4000
;
; Receiver Configuration Register
;
RX_CFG_SKIP equ 0x0040
RX_CFG_RX_OK_IE equ 0x0100
RX_CFG_CRC_ERR_IE equ 0x1000
RX_CFG_RUNT_IE equ 0x2000
RX_CFG_X_DATA_IE equ 0x4000
;
; Receiver Event Register
;
RX_EVENT_RX_OK equ 0x0100
RX_EVENT_IND_ADDR equ 0x0400
RX_EVENT_BCAST equ 0x0800
RX_EVENT_CRC_ERR equ 0x1000
RX_EVENT_RUNT equ 0x2000
RX_EVENT_X_DATA equ 0x4000
;
;Receiver Control Register
;
RX_CTL_RX_OK_A equ 0x0100
RX_CTL_MCAST_A equ 0x0200
RX_CTL_IND_A equ 0x0400
RX_CTL_BCAST_A equ 0x0800
RX_CTL_CRC_ERR_A equ 0x1000
RX_CTL_RUNT_A equ 0x2000
RX_CTL_X_DATA_A equ 0x4000
;
;Transmit Configuration Register
;
TX_CFG_LOSS_CRS_IE equ 0x0040
TX_CFG_SQE_ERR_IE equ 0x0080
TX_CFG_TX_OK_IE equ 0x0100
TX_CFG_OUT_WIN_IE equ 0x0200
TX_CFG_JABBER_IE equ 0x0400
TX_CFG_16_COLL_IE equ 0x8000
TX_CFG_ALL_IE equ 0x8FC0
;
;Transmit Event Register
;
TX_EVENT_TX_OK equ 0x0100
TX_EVENT_OUT_WIN equ 0x0200
TX_EVENT_JABBER equ 0x0400
TX_EVENT_16_COLL equ 0x1000
;
; Transmit Command Register
;
TX_CMD_START_5 equ 0x0000
TX_CMD_START_381 equ 0x0080
TX_CMD_START_1021 equ 0x0040
TX_CMD_START_ALL equ 0x00C0
TX_CMD_FORCE equ 0x0100
TX_CMD_ONE_COLL equ 0x0200
TX_CMD_NO_CRC equ 0x1000
TX_CMD_NO_PAD equ 0x2000
;
;Buffer Configuration Register
;
BUF_CFG_SW_INT equ 0x0040
BUF_CFG_RDY4TX_IE equ 0x0100
BUF_CFG_TX_UNDR_IE equ 0x0200
;
; PORTA pin assignments (Crystal address bus)
;
SA0 equ 0
SA1 equ 1
SA2 equ 2
SA3 equ 3
;RA4 equ 4 ;not used (ST)
;RA5 equ 5 ;not used (TTL)
;
; PORTB pin assignments (Crystal data bus)
;
SD0 equ 0
SD1 equ 1
SD2 equ 2
SD3 equ 3
SD4 equ 4
SD5 equ 5
SD6 equ 6
SD7 equ 7
;
; PORTC pin assignments (Crystal signals CHIPSEL/IOW/IOR)
;
IOR equ 0 ;active low signal to initiate I/O read operation
IOW equ 1 ;active low signal to initiate I/O write operation
CHIPSEL equ 2 ;active low signal to select the CS8900 chip
INTR equ 3 ;active HIGH interrupt pending signal. Auto cleared after read of ISQ
;RC4 equ 4 ;not used (ST)
;RC5 equ 5 ;not used (ST)
;RC6 equ 6 ;not used (ST)
;RC7 equ 7 ;not used (ST)
;
; PORTD pin assignments
;
;RD0 equ 0 ;not used
;RD1 equ 1 ;not used
;RD2 equ 2 ;not used
;RD3 equ 3 ;not used
;RD4 equ 4 ;not used
;RD5 equ 5 ;not used
;RD6 equ 6 ;not used
;RD7 equ 7 ;not used
;
; PORTE pin assignments (LCD control)
;
;RE0 equ 0 ;not used
;RE1 equ 1 ;not used
;RE2 equ 2 ;not used
;
; Register file assignments
;
tempH equ 0x20
tempL equ 0x21
loops equ 0x22
loops2 equ 0x23
loops3 equ 0x24
char equ 0x25
cnt_low equ 0x26
cnt_mid equ 0x27
cnt_hi equ 0x28
bcd1 equ 0x29
bcd2 equ 0x2a
bcd3 equ 0x2b
valueH equ 0x2c
valueL equ 0x2d
offsetH equ 0x2e
offsetL equ 0x2f
flags equ 0x30
hextemp equ 0x31
lengthH equ 0x32
lengthL equ 0x33
packet equ 0x34 ;the highest register file location is 3F because we need 64 bytes after this.
;
; Packet offset equates
;
;
; Packet header
;
pktLenH equ 0x00
pktLenL equ 0x01
pktDest0H equ 0x02
pktDest0L equ 0x03
pktDest1H equ 0x04
pktDest1L equ 0x05
pktDest2H equ 0x06
pktDest2L equ 0x07
pktSrc0H equ 0x08
pktSrc0L equ 0x09
pktSrc1H equ 0x0a
pktSrc1L equ 0x0b
pktSrc2H equ 0x0c
pktSrc2L equ 0x0d
pktTypeH equ 0x0e
pktTypeL equ 0x0f
;
; ARP
;
ar_hwtype equ 0x10 ;hardware type
ar_prtype equ 0x12 ;protocol type
ar_hwlen equ 0x14 ;hardware address length
ar_prlen equ 0x15 ;protocol address length
ar_op equ 0x16 ;ARP operation (1=request, 2=reply)
ar_sha equ 0x18 ;senders hardware address
ar_spa equ 0x1e ;senders IP address
ar_tha equ 0x22 ;target hardware address
ar_tpa equ 0x28 ;target IP address
;
; IP header
;
ip_verlen equ 0x10 ;IP version and header length(in longs)
ip_tos equ 0x11 ;IP type of service
ip_len equ 0x12 ;packet length (length-header_length)
ip_id equ 0x14 ;datagram id
ip_fragoff equ 0x16 ;fragment offset
ip_ttl equ 0x18 ;time to live (in gateway hops)
ip_proto equ 0x19 ;protocol (ICMP=1, TCP=6, EGP=8, UDP=17)
ip_cksum equ 0x1a ;header checksum
ip_src equ 0x1c ;IP address of source
ip_dst equ 0x20 ;IP addess of destination
ip_data equ 0x24
;
; IP value equates
;
IPT_ICMP equ 1 ;protocol type for ICMP packets
IPT_TCP equ 6 ;protocol type for TCP packets
IPT_EGP equ 8 ;protocol type for EGP packets
IPT_UDP equ 0x11 ;protocol type for UDP packets
;
; ICMP header
;
ic_type equ ip_data ;0=reply, 8=request, others=who-cares
ic_code equ ic_type+1 ;code
ic_cksum equ ic_code+1 ;checksum of header+data
ic_id equ ic_cksum+2 ;message id
ic_seq equ ic_id+2 ;sequence number
;
; UDP Header
;
u_src equ ip_data ;source udp port number
u_dst equ u_src+2 ;destination UDP port number
u_len equ u_dst+2 ;length of UDP header+data
u_cksum equ u_len+2 ;checksum (see note)
u_data equ u_cksum+2 ;start of data
;
; Note: checksum is calculated by taking the 16 bit sums of the ip_src, ip_dst,
; ip_proto, u_len, and the sum starting at u_src for a length of u_len
; yes, this means that u_len is taken twice! u_cksum is zero during the calc.
; The sum is then one's complemented. This is the checksum
;
org 0
goto start
;
org 4
retfie
;
start bsf STATUS,RP0
movlw 0xff ;make all RA/RE
movwf ADCON1 ;pins digital I/O
clrf TRISA ;crystal address bus output
clrf TRISB ;crystal data bus output
clrf TRISC ;crystal control signals output
bcf STATUS,RP0
bsf PORTC,IOR ;no read on crystal
bsf PORTC,IOW ;no write on crystal
bsf PORTC,CHIPSEL ;address enable
clrf PORTA ;clear address bus
call VerChip
call ResetChip
call InitChip
clrf flags
loop btfss PORTC,INTR ;wait for interrupt
goto loop
call ProcessISQ
btfss flags,0 ;received frame flag
goto loop
bcf flags,0 ;clear the receive flag
btfss flags,1 ;bit set when valid arp
goto loop
bcf flags,1 ;clear the valid arp request flag
call SendARP
goto loop
;
; wait for W milliseconds
;
wait movwf loops
wait0 movlw 5
movwf loops2
wait1 movlw .110
movwf loops3
wait2 nop
nop
nop
nop
nop
nop
decfsz loops3,1
goto wait2
decfsz loops2,1
goto wait1
decfsz loops,1
goto wait0
return
;
; Compare two 16 bit numbers and return the result in STATUS,C
; If C=0, valueH/valueL is less than tempH/tempL
; if C=1, then valueH/valueL is greater than or equal to tempH/tempL
; valueH/valueH are destroyed in the process.
cmp16 movf tempL,0 ;get low
subwf valueL,1
btfsc STATUS,C ;C=0 means its neg
goto cmpH ;C=1, valueL is >= 0x7f
movlw 1
subwf valueH,1 ;decrement high
btfss STATUS,C ;if it goes neg, then
goto cmpIsLess ; value is less than 0x7f
cmpH movf tempH,0 ;0x00 part of 0x007f
subwf valueH,1 ;subtract
btfss STATUS,C
goto cmpIsLess
bsf STATUS,C ; valueH/valueL is greater or equal to tempH/tempL
return
cmpIsLess
bcf STATUS,C ;valueH/valueL is less than 0x007F
return
;************************************************************************
;* C S 8 9 0 0 D r i v e r F u n c t i o n s *
;************************************************************************
;
; SendARP - Send a response ARP to the requestor
;
SendARP
Doutput
movlw TX_CMD_START_ALL
iow portTxCmd
movlw 0
iow portTxCmd+1
movlw d'42' ;length of ARP response frame
iow portTxLength
movlw 0
iow portTxLength+1
RTGetStat
ppRD ppBusSt ;get BusStatus
btfss valueH,0 ;is BUS_ST_RDY4TXNOW (ready for transmit)
goto RTGetStat ;no, wait for it
Doutput
; Send dest (6)
movf packet+pktSrc0H,0
iow portRxTxData
movf packet+pktSrc0L,0
iow portRxTxData+1
movf packet+pktSrc1H,0
iow portRxTxData
movf packet+pktSrc1L,0
iow portRxTxData+1
movf packet+pktSrc2H,0
iow portRxTxData
movf packet+pktSrc2L,0
iow portRxTxData+1
; Send src (6)
movlw MAC1
iow portRxTxData
movlw MAC2
iow portRxTxData+1
movlw MAC3
iow portRxTxData
movlw MAC4
iow portRxTxData+1
movlw MAC5
iow portRxTxData
movlw MAC6
iow portRxTxData+1
; Send type (2)
movlw 0x08
iow portRxTxData
movlw 0x06
iow portRxTxData+1
; Send hwtype (2)
movlw 0x00
iow portRxTxData
movlw 0x01
iow portRxTxData+1
; Send prtype (protocol type) (2)
movlw 0x08
iow portRxTxData
movlw 0x00
iow portRxTxData+1
; Send hardware and protocol address lengths (2)
movlw 0x06
iow portRxTxData
movlw 0x04
iow portRxTxData+1
; Send operation (response) (2)
movlw 0x00
iow portRxTxData
movlw 0x02
iow portRxTxData+1
; Send Senders HW address (6)
movlw MAC1
iow portRxTxData
movlw MAC2
iow portRxTxData+1
movlw MAC3
iow portRxTxData
movlw MAC4
iow portRxTxData+1
movlw MAC5
iow portRxTxData
movlw MAC6
iow portRxTxData+1
; Send Senders IP (4)
movlw IP1
iow portRxTxData
movlw IP2
iow portRxTxData+1
movlw IP3
iow portRxTxData
movlw IP4
iow portRxTxData+1
; Send Target HW address (6)
movf packet+pktSrc0H,0
iow portRxTxData
movf packet+pktSrc0L,0
iow portRxTxData+1
movf packet+pktSrc1H,0
iow portRxTxData
movf packet+pktSrc1L,0
iow portRxTxData+1
movf packet+pktSrc2H,0
iow portRxTxData
movf packet+pktSrc2L,0
iow portRxTxData+1
; Send Target IP (4)
movf packet+ar_spa,0
iow portRxTxData
movf packet+ar_spa+1,0
iow portRxTxData+1
movf packet+ar_spa+2,0
iow portRxTxData
movf packet+ar_spa+3,0
iow portRxTxData+1
return
;
;
;
; Receive Event
; Input with RxEvent in valueH
;
ReceiveEvent
Dinput ;make data bus input
;
; It's important to read the status and length high-order
; byte first.
;
ior portRxTxData+1 ;read and discard status
ior portRxTxData ;read and discard status
movlw packet+2 ;set indirect
movwf FSR ; address
ior portRxTxData+1 ;get length high
movwf packet+pktLenH ;save in header area
movwf lengthH ; and in lengthH
movwf valueH ;save for compare
ior portRxTxData ;get length low
movwf packet+pktLenL ;save in header area
movwf lengthL ; and in lengthL
movwf valueL ;save for compare
ReadFrame
movlw 0x7f-packet ;this is the max packet length
addlw packet
subwf FSR,0
btfsc STATUS,C
goto RFCont ;done
; if C=0 (FSR-packet+64 is neg) then we have not received max bytes yet so write to register file
ior portRxTxData ;read from CS8900
movwf INDF ;write it to file register
incf FSR,1 ;increment file location
ior portRxTxData+1 ;read from CS8900
movwf INDF ;write it to file register
incf FSR,1 ;increment file location
goto RFCont ;continue
RFCont movlw 2
subwf lengthL,1
btfsc STATUS,C ;see if negative (C=0)
goto RF1 ;C set so result is zero or better
movlw 1
subwf lengthH,1 ;decrement high
btfss STATUS,C
goto ReadDone ;high went neg, we're done
RF1 movf lengthL,0 ;get low
btfss STATUS,Z
goto ReadFrame ;not zero, continue
movf lengthH,0
btfss STATUS,Z
goto ReadFrame ;not zero, continue
ReadDone
movlw 1
iorwf flags,1 ;flag frame read
movlw 0x08 ;check if
subwf packet+pktTypeH,0 ; packet type
btfss STATUS,Z ; is 0x0806 (ARP)
goto ChkIP ;no, check IP
movlw 0x06
subwf packet+pktTypeL,0
btfsc STATUS,Z
goto DoArp
ChkIP movlw 0x08 ;check if
subwf packet+pktTypeH,0 ; packet type
btfss STATUS,Z ; is 0x0800 (IP)
return ;no, just return
movf packet+pktTypeL,0
btfsc STATUS,Z
goto DoIP ;process IP packet
return
discard ppRD ppRxCfg
movlw RX_CFG_SKIP
iorwf valueL,1
call WritePP ;discard frame
return
;
; It's an arp request, Could be a request or a response.
; ARP packets are small so the whole thing is always in
; the register file.
;
DoArp movlw 0x01 ;make sure it's 1
subwf packet+ar_hwtype+1,0 ;compare to low
btfss STATUS,Z
return ;exit, bad request
movlw 0x08 ;make sure it's 0x0800
subwf packet+ar_prtype,0 ;compare to high
btfss STATUS,Z
return ;exit, bad request
movlw 0 ;make sure it's 0x0800
subwf packet+ar_prtype+1,0 ;compare to low
btfss STATUS,Z
return ;exit, bad request
movlw 0x06 ;make sure it's 6 for hwlen
subwf packet+ar_hwlen,0 ;compare to high
btfss STATUS,Z
return ;exit, bad request
movlw 0x04 ;make sure it's 4 for protocol length
subwf packet+ar_prlen,0 ;compare to low
btfss STATUS,Z
return ;exit, bad request
movlw 0x01 ;make sure it's 0x0001 for arp request
subwf packet+ar_op+1,0 ;compare to low
btfss STATUS,Z
return ;exit, bad request
movlw IP1 ;First IP octet
subwf packet+ar_tpa,0
btfss STATUS,Z
return ;exit, bad request
movlw IP2 ;second IP octet
subwf packet+ar_tpa+1,0
btfss STATUS,Z
return ;exit, bad request
movlw IP3 ;Third IP octet
subwf packet+ar_tpa+2,0
btfss STATUS,Z
return ;exit, bad request
movlw IP4 ;fourth IP octet
subwf packet+ar_tpa+3,0
btfss STATUS,Z
return ;exit, bad request
; If we got to here, then we have a valid ARP request for our IP address
movlw 2
iorwf flags,1
return
;
; Process IP packet for ICMP or UDP requests
;
DoIP movlw IPT_ICMP ;get protocol number for ICMP
subwf packet+ip_proto,0 ;compare to this packet's proto
btfsc STATUS,Z ;if zero, then it's ICMP
goto DoICMP ;go process ICMP packet
movlw IPT_UDP ;get protocol number for UDP
subwf packet+ip_proto,0 ;compare to this packet's proto
btfss STATUS,Z ;if zero, then it's ICMP
return ;just return, we dont process this type
DoUDP movlw 7 ;port we're listing for requests on
subwf packet+u_dst+1,0 ;compare to UDP packet
btfss STATUS,Z ;if zero, then it's echo port
return ;otherwise, just return
clrf packet+ip_cksum ;clear
clrf packet+ip_cksum+1 ; checksum
movf packet+ip_src,0 ;move
movwf packet+ip_dst ; ip
movf packet+ip_src+1,0 ; of
movwf packet+ip_dst+1 ; source
movf packet+ip_src+2,0 ; to
movwf packet+ip_dst+2 ; dest
movf packet+ip_src+3,0
movwf packet+ip_dst+3
movlw IP1 ;move
movwf packet+ip_src ; our
movlw IP2 ; ip
movwf packet+ip_src+1 ; address
movlw IP3 ; to
movwf packet+ip_src+2 ; source
movlw IP4
movwf packet+ip_src+3
movf packet+pktSrc0H,0 ;move
movwf packet+pktDest0H ; mac src to dest
movf packet+pktSrc0L,0
movwf packet+pktDest0L
movf packet+pktSrc1H,0 ;move
movwf packet+pktDest1H ; mac src to dest
movf packet+pktSrc1L,0
movwf packet+pktDest1L
movf packet+pktSrc2H,0 ;move
movwf packet+pktDest2H ; mac src to dest
movf packet+pktSrc2L,0
movwf packet+pktDest2L
movlw MAC1 ;move
movwf packet+pktSrc0H ; our
movlw MAC2 ; MAC
movwf packet+pktSrc0L ; address
movlw MAC3 ; to
movwf packet+pktSrc1H ; source
movlw MAC4
movwf packet+pktSrc1L
movlw MAC5
movwf packet+pktSrc2H
movlw MAC6
movwf packet+pktSrc2L
movlw d'20'
movwf lengthL
clrf lengthH
movlw packet+ip_verlen
call cksum
movf valueH,0
movwf packet+ip_cksum ;save new checksum
movf valueL,0
movwf packet+ip_cksum+1
movf packet+u_src,0 ;get src port
movwf tempL
movf packet+u_dst,0 ;put dest port
movwf packet+u_src ;in source
movf tempL,0
movwf packet+u_dst ;put source port in dest
movf packet+u_src+1,0 ;get src port
movwf tempL
movf packet+u_dst+1,0 ;put dest port
movwf packet+u_src+1 ;in source
movf tempL,0
movwf packet+u_dst+1 ;put source port in dest
clrf packet+u_cksum ;clear UDP checksum for new calc
clrf packet+u_cksum+1 ;clear byte two
clrf cnt_low
clrf cnt_mid ;clear checksum accum
clrf cnt_hi
movlw packet+ip_src
movwf FSR
movlw d'8' ;IP_ALEN*2
call UDPCkSum
movf packet+ip_proto,0 ;get protocol (1 byte)
addwf cnt_low,1 ;add to accum
btfss STATUS,C
goto ProtoDone
movlw 1
addwf cnt_mid,1
btfsc STATUS,C
incf cnt_hi,1
ProtoDone
movlw packet+u_len ;add in UDP len
movwf FSR
movlw d'2'
call UDPCkSum
movlw packet+u_src
movwf FSR
movf packet+u_len+1,0
call UDPCkSum
movf cnt_hi,0
addwf cnt_low,1
btfsc STATUS,C
incf cnt_mid,1
comf cnt_mid,0
movwf packet+u_cksum
comf cnt_low,0
movwf packet+u_cksum+1
Doutput
movlw TX_CMD_START_ALL
iow portTxCmd
movlw 0
iow portTxCmd+1
movf packet+pktLenL,0 ;length of ARP response frame
iow portTxLength
movf packet+pktLenH,0
iow portTxLength+1
UDPGetStat
ppRD ppBusSt ;get BusStatus
btfss valueH,0 ;is BUS_ST_RDY4TXNOW (ready for transmit)
goto UDPGetStat ;no, wait for it
Doutput
btfss packet+pktLenL,0
goto WriteEven ;even # of bytes
movf packet+pktLenL,0 ;get length
addlw packet
movwf FSR
clrf INDF ;clear byte
WriteEven
movlw packet+2
movwf FSR
movf packet+pktLenL,0
movwf tempL ;save length of send in temp
WriteUDP
movf INDF,0
iow portRxTxData
incf FSR,1
movf INDF,0
iow portRxTxData+1
incf FSR,1
movlw 2
subwf tempL,1
btfsc STATUS,Z
goto UDPDone
btfsc STATUS,C
goto WriteUDP
UDPDone
return
;
; Calc (cumulative) checksum of UDP header/data
;
UDPCkSum
movwf tempL ;save length of buffer
bcf STATUS,C ;clear carry
rrf tempL,1 ;/2 cuz we process 2 bytes at a time
UDPCklp movf INDF,0 ;get next byte high
movwf valueH ;save it
incf FSR,1 ;increment to low byte
movf INDF,0 ;get low
incf FSR,1 ;increment
addwf cnt_low,1 ;add to accum
btfss STATUS,C
goto UDPLcarry
movlw 1
addwf cnt_mid,1
btfsc STATUS,C
incf cnt_hi,1
UDPLcarry
movf valueH,0 ;get the high again
addwf cnt_mid,1
btfsc STATUS,C
incf cnt_hi,1
decfsz tempL,1
goto UDPCklp
return
;
; Process ICMP (ping) requests
;
DoICMP ;we might want to check in the future for IA or broadcast requests
clrf packet+ip_cksum
clrf packet+ip_cksum+1 ;clear checksum
movf packet+ip_src,0 ;move
movwf packet+ip_dst ; ip
movf packet+ip_src+1,0 ; of
movwf packet+ip_dst+1 ; source
movf packet+ip_src+2,0 ; to
movwf packet+ip_dst+2 ; dest
movf packet+ip_src+3,0
movwf packet+ip_dst+3
movlw IP1 ;move
movwf packet+ip_src ; our
movlw IP2 ; ip
movwf packet+ip_src+1 ; address
movlw IP3 ; to
movwf packet+ip_src+2 ; source
movlw IP4
movwf packet+ip_src+3
clrf packet+ic_cksum ;clear ICMP
clrf packet+ic_cksum+1 ; checksum
clrf packet+ic_type ;make type a reply
clrf packet+ic_code ;clear code
movf packet+pktSrc0H,0 ;move
movwf packet+pktDest0H ; mac src to dest
movf packet+pktSrc0L,0
movwf packet+pktDest0L
movf packet+pktSrc1H,0 ;move
movwf packet+pktDest1H ; mac src to dest
movf packet+pktSrc1L,0
movwf packet+pktDest1L
movf packet+pktSrc2H,0 ;move
movwf packet+pktDest2H ; mac src to dest
movf packet+pktSrc2L,0
movwf packet+pktDest2L
movlw MAC1 ;move
movwf packet+pktSrc0H ; our
movlw MAC2 ; MAC
movwf packet+pktSrc0L ; address
movlw MAC3 ; to
movwf packet+pktSrc1H ; source
movlw MAC4
movwf packet+pktSrc1L
movlw MAC5
movwf packet+pktSrc2H
movlw MAC6
movwf packet+pktSrc2L
movlw d'20' ;length of IP header
movwf lengthL ;set length of
clrf lengthH ; checksum calculation
movlw packet+ip_verlen ;displacement to start of IP header
call cksum ;calculate the checksum
movf valueH,0
movwf packet+ip_cksum ;set new checksum
movf valueL,0
movwf packet+ip_cksum+1
movf packet+ip_len,0 ;get length high
movwf lengthH
movlw d'20' ;ip header length
subwf packet+ip_len+1,0 ;calc length of ICMP header+data
movwf lengthL
btfss STATUS,C
decf lengthH,1 ;if prev sub went neg then dec high
movlw packet+ic_type ;start of ICMP header
call cksum
movf valueH,0 ;set new checksum
movwf packet+ic_cksum
movf valueL,0
movwf packet+ic_cksum+1
Doutput
movlw TX_CMD_START_ALL
iow portTxCmd
movlw 0
iow portTxCmd+1
movf packet+pktLenL,0 ;length of ICMP response frame
iow portTxLength ; is the same as
movf packet+pktLenH,0 ; the request.
iow portTxLength+1
ICMPGetStat
ppRD ppBusSt ;get BusStatus
btfss valueH,0 ;is BUS_ST_RDY4TXNOW (ready for transmit)
goto ICMPGetStat ;no, wait for it
Doutput
movlw packet+pktDest0H
movwf FSR
movf packet+pktLenL,0 ;length
movwf lengthL ; to
movf packet+pktLenH,0 ; send
movwf lengthH
WritePing
movf INDF,0 ;get next byte
incf FSR,1
iow portRxTxData
movf INDF,0 ;get next byte
incf FSR,1
iow portRxTxData+1
movlw 2 ;subtract
subwf lengthL,1 ; two byte from length
btfsc STATUS,C ;see if negative (C=0)
goto WP1 ;C set so result is zero or better
movlw 1
subwf lengthH,1 ;decrement high
btfss STATUS,C ;c=0 means negative
goto ICMPDone ;high went neg, we're done
WP1 movf lengthL,0 ;get low
btfss STATUS,Z
goto WritePing ;not zero, continue
movf lengthH,0
btfss STATUS,Z
goto WritePing ;not zero, continue
ICMPDone
return
;
; Calc checksum. Reads packet at offset W for
; LengthH/LengthL bytes and calculates the checksum
; in valueH/valueL.
;
cksum movwf FSR
clrf cnt_low ;we do the arithmetic
clrf cnt_mid ; using a 24
clrf cnt_hi ; bit area
cksuml movf INDF,0 ;get high byte of 16-bit word
movwf valueH ;save it
incf FSR,1
movf INDF,0
incf FSR,1
addwf cnt_low,1 ;add to accum
btfss STATUS,C
goto noLcarry
movlw 1
addwf cnt_mid,1
btfsc STATUS,C
incf cnt_hi,1
noLcarry
movf valueH,0 ;get the high again
addwf cnt_mid,1
btfsc STATUS,C
incf cnt_hi,1
;
movlw 2 ;subtract
subwf lengthL,1 ; two byte from length
btfsc STATUS,C ;see if negative (C=0)
goto CK1 ;C set so result is zero or better
movlw 1
subwf lengthH,1 ;decrement high
btfss STATUS,C ;c=0 means negative
goto CkDone ;high went neg, we're done
CK1 movf lengthL,0 ;get low
btfss STATUS,Z
goto cksuml ;not zero, continue
movf lengthH,0
btfss STATUS,Z
goto cksuml ;not zero, continue
;
CkDone movf cnt_hi,0 ;get the third byte of 24 bit area
addwf cnt_low,1 ;any carries into this are added in
btfsc STATUS,C ;if that caused a carry, then
incf cnt_mid,1 ; increment the middle byte
comf cnt_low,0 ;get and ones complement
movwf valueL ;save it to low
comf cnt_mid,0 ;get and ones complement
movwf valueH ;save as high
return
;
; Transmit Event
;
TransmitEvent
return
;
; Processes the pending interrupt requests from the Interrupt Status Queue
;
ProcessISQ
; Read the ISQ
NextEvt Dinput
ior portISQ ;read interrupt status queue
movwf valueL ;save value low
ior portISQ+1 ;read interrupt status queue high
movwf valueH ;save value high
movf valueL,0 ;get val
btfsc STATUS,Z
return ;if zero, then done
movlw REG_NUM_RX_EVENT
subwf valueL,0 ;RxEvent?
btfsc STATUS,Z
goto evtRecv
movlw REG_NUM_TX_EVENT
subwf valueL,0 ;TxEvent?
btfsc STATUS,Z ;Ingore BufEvent, RxMiss, and TxCol
call TransmitEvent
goto NextEvt
evtRecv call ReceiveEvent
goto NextEvt
;
; Initializes the chip
;
InitChip
ppWR ppLineCtl,LINE_CTL_10BASET ;set to 10BaseT
ppWR ppTestCtl,TEST_CTL_FDX ;set to full duplex
ppWR ppRxCfg,RX_CFG_RX_OK_IE ;enable RxOK interrupt
ppWR ppRxCtl,(RX_CTL_RX_OK_A|RX_CTL_IND_A|RX_CTL_BCAST_A)
ppWR ppTxCfg,TX_CFG_ALL_IE
;
; Important: The IA needs to be byte revered IA=aa:bb:cc:dd:ee:ff
;
ppWR ppIndAddr,(MAC2<<8|MAC1) ;0xbbaa Write
ppWR ppIndAddr+2,(MAC4<<8|MAC3) ;0xddcc out
ppWR ppIndAddr+4,(MAC6<<8|MAC5) ;0xffee 48 bit IA
ppWR ppIntNum,0x00 ;INT is on INTRQ0
ppRD ppBusCtl ;get Bus Control
bsf valueH,7 ;enable irq
call WritePP ;write it back
ppRD ppLineCtl ;get Line Control
bsf valueL,6 ;set SerRxOn
bsf valueL,7 ;set SerTxOn
call WritePP ;write it back
return
;
; Resets the CS8900
;
ResetChip
ppWR ppSelfCtl,SELF_CTL_RESET ;issue a reset to the chip
ResetWait
movlw d'1' ;wait for
call wait ;a millisecond
ppRD ppSelfCtl ;get the Self Control status
btfsc valueL,6 ;see it bit 6 (RESET) was cleared
goto ResetWait ;no, then still in reset, wait some more
ppRD ppSelfSt ;get self status
btfss valueL,7 ;bit 7 is INITD
goto ResetWait ; when set, initialization of the CS8900 is done
return
;
; Verifies that the CS8900 is attached and sets the STATUS,Z flag to
; indicate success or not set if failure.
;
VerChip
Dinput ;make the data bus input
; first, get the signature at portPtr which should be 0x3000
ior portPtr ;read PacketPage Ptr
movwf valueL ;save value low
ior portPtr+1 ;read PacketPage Ptr for high order byte
movwf PORTA ;set the address bus
movwf valueH ;save high low
movf valueL,0 ;get low value
btfss STATUS,Z ;should be 0 (i.e. 0x3000 low is 0x00)
goto VerBad
movlw 0x30 ;high part of 0x3000
subwf valueH,0 ;subtract from value obtained
btfss STATUS,Z ;see if compared okay
goto VerBad
ppRD ppEISA ;get the EISA number whoch should be 0x630E
movlw 0x63
subwf valueH,0 ;compare to 0x63
btfss STATUS,Z
goto VerBad
movlw 0x0e ;compare to 0x0e
subwf valueL,0
btfss STATUS,Z
goto VerBad
ppRD ppProdID ;get the Product ID which should be 000x xxxx 0000 0000
;where x xxxx = 0 0011 for rev E and 0 0101 for rev F
movf valueL,0 ;set return status
VerBad return ;return with status,z indicating success (Z) or not set for failure
;
; Writes the value at valueH/valueL to the PagePacket register who's
; address is in offsetH/offsetL
;
WritePP
Doutput ;make the data bus output
movf offsetL,0 ;get the low order byte
iow portPtr ;write to PacketPage Ptr
movf offsetH,0 ;get the high order byte
iow portPtr+1 ;write to PacketPage ptr
movf valueL,0 ;get low order value to write
iow portData ;write to PacketPage data
movf valueH,0 ;get high order data
iow portData+1 ;write to PacketPage data
return
;
; Reads the PagePacket at offsetH/offsetL and returns the result in
; valueH/valueL.
;
ReadPP Doutput ;make the data bus output
movf offsetL,0 ;get the offset to read
iow portPtr ;write to PacketPage Ptr
movf offsetH,0 ;get the high order offset
iow portPtr+1 ;PagePacket Pointer Register high byte
Dinput ;make the data bus input
ior portData ;read the PacketPage data
movwf valueL ;save value low
ior portData+1 ;read the high order byte
movwf valueH ;save the high order byte value
return
ioRead movwf PORTA
bcf PORTC,CHIPSEL
bcf PORTC,IOR
nop
movf PORTB,0
bsf PORTC,IOR
bsf PORTC,CHIPSEL
return
;
ioWrite bcf PORTC,CHIPSEL
bcf PORTC,IOW
nop
bsf PORTC,IOW
bsf PORTC,CHIPSEL
return
end
file: /Techref/microchip/tcpip/crystal.asm, 42KB, , updated: 1999/6/4 14:59, local time: 2025/5/2 21:58,
|
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://www.linistepper.com/techref/microchip/tcpip/crystal.asm"> microchip tcpip crystal</A> |
Did you find what you needed?
|