; ; Device data ; ; v1.20 sxkey sofware for AB0004AA+ does not support TURBO, STACKX directives ; but stops at opcode instruction ; ; v1.12 is used for AA9999 devices, v1.2 cannot be used for that one. ; ; ; V5 utilise le double paquet de 2x1K ; ; device TURBO, STACKX, OSCHS, DRT18MS ; device TURBO, STACKX device OSCHS3, DRT18MS id 'SX52' reset reset_entry freq 50_000_000 ; stackx allows 8 levels of stack, otherwise only 2 are used ; and screws up completely the SW ; carryx allows add/sub Do not use ; OSCHS : External High Speed Osc, mandatory to enable external oscillator ; Disable it when using SX-KEY !!! ; DRT18MS : Boots after 18ms ; ram variables ; Equates RESET_CS8900 = rc.4 RAMWrite = rc.5 RAMRead = rc.6 ; FIFOs variables ; Equates FIFOWrite = re.7 FIFORead = re.6 FIFOFull = re.5 ClearFIFO = re.4 EmptyFIFO = re.3 ;Priority IPPriority equ $7C ; Constants ; *Change these* : Configuration equates. Timeout equ 50 NbRetry equ 200 IP1 equ $86 ; 134 first octet of IP address IP2 equ $AB ; 171 second octet of IP address IP3 equ 73 ; third octet of IP address IP4 equ 45 ; fourth octet of IP address MAC1 equ $00 ;\ MAC2 equ $11 ; \ MAC3 equ $86 ; \ MAC4 equ $54 ; 48 bit IEEE OUI (Organizationally Unique Identifier) MAC5 equ $80 ; / MAC6 equ $96 ;/ ;Gateway IP adress GIP1 equ $86 ; 134 first octet of IP address GIP2 equ $AB ; 171 second octet of IP address GIP3 equ $0C ; 12 third octet of IP address GIP4 equ $C7 ; 199 fourth octet of IP address ; Crystal CS8900 PacketPage equates portRxTxData equ $00 ;Receive/Transmit data (port 0) portRxTxData1 equ $02 ;Receive/Transmit data (port 0) portTxCmd equ $04 ;Transmit Commnad portTxLength equ $06 ;Transmit Length portISQ equ $08 ;Interrupt status queue portPtr equ $0A ;PacketPage pointer portData equ $0C ;PacketPage data (port 0) portData1 equ $0E ;PacketPage data (port 1) ; CS8900 PacketPage Offsets ppEISA equ $0000 ;EISA Registration number of CS8900 ppProdID equ $0002 ;Product ID Number ppIOBase equ $0020 ;I/O Base Address ppIntNum equ $0022 ;Interrupt number (0,1,2, or 3) ppMemBase equ $002C ;Memory Base address register (20 bit) ppRxCfg equ $0102 ;Receiver Configuration ppRxCtl equ $0104 ;Receiver Control ppTxCfg equ $0106 ;Transmit Configuration ppBufCfg equ $010A ;Buffer Configuration ppLineCtl equ $0112 ;Line Control ppSelfCtl equ $0114 ;Self Control ppBusCtl equ $0116 ;Bus Control ppTestCtl equ $0118 ;Test Control ppISQ equ $0120 ;Interrupt status queue ppRxEvt equ $0124 ;Receiver Event ppTxEvt equ $0128 ;Transmitter Event ppBufEvt equ $012C ;Buffer Event ppRxMiss equ $0130 ;Receiver Miss Counter ppTxCol equ $0132 ;Transmit Collision Counter ppLineSt equ $0134 ;Line Status ppSelfSt equ $0136 ;Self Status ppBusSt equ $0138 ;Bus Status ppTxCmd equ $0144 ;Transmit Command Request ppTxLength equ $0146 ;Transmit Length ppIndAddr equ $0158 ;Individual Address (IA) ppRxStat equ $0400 ;Receive Status ppRxLength equ $0402 ;Receive Length ppRxFrame equ $0404 ;Receive Frame Location ppTxFrame equ $0A00 ;Transmit Frame Location ; Register Numbers REG_NUM_MASK equ $003F REG_NUM_RX_EVENT equ $0004 REG_NUM_TX_EVENT equ $0008 REG_NUM_BUF_EVENT equ $000C REG_NUM_RX_MISS equ $0010 REG_NUM_TX_COL equ $0012 ; Self Control Register SELF_CTL_RESET equ $0040 SELF_CTL_HC1E equ $2000 SELF_CTL_HCB1 equ $8000 ; Self Status Register SELF_ST_INIT_DONE equ $0080 SELF_ST_SI_BUSY equ $0100 SELF_ST_EEP_PRES equ $0200 SELF_ST_EEP_OK equ $0400 SELF_ST_EL_PRES equ $0800 ; Bus Control Register BUS_CTL_USE_SA equ $0200 BUS_CTL_MEM_MODE equ $0400 BUS_CTL_IOCHRDY equ $1000 BUS_CTL_INT_ENBL equ $8000 ; Bus Status Register BUS_ST_TX_BID_ERR equ $0080 BUS_ST_RDY4TXNOW equ $0100 ; Line Control Register LINE_CTL_RX_ON equ $0040 LINE_CTL_TX_ON equ $0080 LINE_CTL_AUI_ONLY equ $0100 LINE_CTL_10BASET equ $0000 ; Test Control Register TEST_CTL_DIS_LT equ $0080 TEST_CTL_ENDEC_LP equ $0200 TEST_CTL_AUI_LOOP equ $0400 TEST_CTL_DIS_BKOFF equ $0800 TEST_CTL_FDX equ $4000 ; Receiver Configuration Register RX_CFG_SKIP equ $0040 RX_CFG_RX_OK_IE equ $0100 RX_CFG_CRC_ERR_IE equ $1000 RX_CFG_RUNT_IE equ $2000 RX_CFG_X_DATA_IE equ $4000 ; Receiver Event Register RX_EVENT_RX_OK equ $0100 RX_EVENT_IND_ADDR equ $0400 RX_EVENT_BCAST equ $0800 RX_EVENT_CRC_ERR equ $1000 RX_EVENT_RUNT equ $2000 RX_EVENT_X_DATA equ $4000 ;Receiver Control Register RX_CTL_RX_OK_A equ $0100 RX_CTL_MCAST_A equ $0200 RX_CTL_IND_A equ $0400 RX_CTL_BCAST_A equ $0800 RX_CTL_CRC_ERR_A equ $1000 RX_CTL_RUNT_A equ $2000 RX_CTL_X_DATA_A equ $4000 ;Transmit Configuration Register TX_CFG_LOSS_CRS_IE equ $0040 TX_CFG_SQE_ERR_IE equ $0080 TX_CFG_TX_OK_IE equ $0100 TX_CFG_OUT_WIN_IE equ $0200 TX_CFG_JABBER_IE equ $0400 TX_CFG_16_COLL_IE equ $8000 TX_CFG_ALL_IE equ $8FC0 ;Transmit Event Register TX_EVENT_TX_OK equ $0100 TX_EVENT_OUT_WIN equ $0200 TX_EVENT_JABBER equ $0400 TX_EVENT_16_COLL equ $1000 ; Transmit Command Register TX_CMD_START_5 equ $0000 TX_CMD_START_381 equ $0080 TX_CMD_START_1021 equ $0040 TX_CMD_START_ALL equ $00C0 TX_CMD_FORCE equ $0100 TX_CMD_ONE_COLL equ $0200 TX_CMD_NO_CRC equ $1000 TX_CMD_NO_PAD equ $2000 ;Buffer Configuration Register BUF_CFG_SW_INT equ $0040 BUF_CFG_RDY4TX_IE equ $0100 BUF_CFG_TX_UNDR_IE equ $0200 ; PORTA pin assignments (Crystal address bus) SA0 equ 0 SA1 equ 1 SA2 equ 2 SA3 equ 3 ; 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 ; Register file assignments ; GLOBAL Register are accessible from $0A to $0F (6) org $0A tempH ds 1 ; GLOBAL REGISTER SPACE tempL ds 1 valueH ds 1 valueL ds 1 offsetH ds 1 offsetL ds 1 ; Bank 0, adress $10 org $10 manageUDP = $ flags ds 1 ;$10 bit1=valid frame, bit2=ARP frame, bit3=Send back init , bit4=send ARP Request lengthH ds 1 ;$11 lengthL ds 1 ;$12 AdrssH ds 1 ;$13 AdrssL ds 1 ;$14 ppEISH ds 1 ;$15 ppEISL ds 1 ;$16 ppProdIDV ds 1 ;$17 packetNbReceive ds 1 ;$19 packetNbSend ds 1 ;$1a HandCheckCountH ds 1 ;$1b HandCheckCountL ds 1 ;$1c HandCheckFlags ds 1 ;$1d HandCheckNbTry ds 1 ;$1e HandCheckTimeOut ds 1 ;$1f org $20 packet ds 10*15 ; what's remains : 128 bytes for reception org $B0 packetbackup ds 3*16 ; Packet backup to return a message org $E0 RRefreshARPCounterLL ds 1 RRefreshARPCounterLH ds 1 RRefreshARPCounterHL ds 1 RRefreshARPCounterHH ds 1 org $F0 RAMCurrentSlot ds 1 RAMNbSlotFree ds 1 RAMSlotToWriteRead ds 1 RAMSlotFree ds 2 RAMpacketNbSendSlot ds 2 RAMPacketToSendSlotH ds 2 RAMPacketToSendSlotL ds 2 RAMPacketToSendH ds 1 RAMPacketToSendL ds 1 RAMPacket ds 1 RAMPacketH ds 1 RAMPacketL ds 1 ; Packet offset equates ; Packet header ; all fit in a single bank $20 pktLenH equ $00 pktLenL equ $01 pktDest0H equ $02 pktDest0L equ $03 pktDest1H equ $04 pktDest1L equ $05 pktDest2H equ $06 pktDest2L equ $07 pktSrc0H equ $08 pktSrc0L equ $09 pktSrc1H equ $0a pktSrc1L equ $0b pktSrc2H equ $0c pktSrc2L equ $0d pktTypeH equ $0e pktTypeL equ $0f ; ARP ; next bank, $30 ar_hwtype equ $10 ;hardware type ar_prtype equ $12 ;protocol type ar_hwlen equ $14 ;hardware address length ar_prlen equ $15 ;protocol address length ar_op equ $16 ;ARP operation (1=request, 2=reply) ar_sha equ $18 ;senders hardware address ar_spa equ $1e ;senders IP address ;next bank , $40 ar_tha equ $22 ;target hardware address ar_tpa equ $28 ;target IP address ; IP header ; next bank, $30 ip_verlen equ $10 ;IP version and header length(in longs) ip_tos equ $11 ;IP type of service ip_len equ $12 ;packet length (length-header_length) ip_id equ $14 ;datagram id ip_fragoff equ $16 ;fragment offset ip_ttl equ $18 ;time to live (in gateway hops) ip_proto equ $19 ;protocol (ICMP=1, TCP=6, EGP=8, UDP=17) ip_cksum equ $1a ;header checksum ip_src equ $1c ;IP address of source ;next bank $40 ip_dst equ $20 ;IP addess of destination ip_data equ $24 ; 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 $11 ;protocol type for UDP packets ; ; ICMP header ; bank 40 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 UDP_PORT_SCR equ 191 ;UDP port we are listenning here ; 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 ; PORTA is Adresses ; PORTB is DATA ; PortC is control ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; WHAT this program does ? ; ; This program uses the cs8900 as 8 bits and the IO mode ; Initialise the cs8900 ; - Gives its mac adresses ; waits for interrupts on IRQ line port C ; if one, reads the frame, checks it's an IP frame or ARP frame. ; if it's an ARP frame nothing is done. ; if it's an IP frame, checks if it's an ICMP frame (for ping requests) ; -if yes sends back the ping request ; Global register space Watch ValueH ,8,UHex Watch ValueL ,8,UHex Watch offsetH ,8,UHex Watch offsetL ,8,UHex Watch TempH ,8,UHex Watch TempL ,8,UHex ;BanK 1 Watch lengthH ,8,UHex Watch lengthL ,8,UHex Watch flags ,8,UHex Watch AdrssH ,8,UHex Watch AdrssL ,8,UHex Watch ppEISH ,8,UHex Watch ppEISL ,8,UHex Watch ppProdIDV,8,UHex Watch RAMPacketToSendH,8,UHex Watch RAMPacketToSendL,8,UHex Watch RAMPacketH,8,UHex Watch RAMPacketL,8,UHex org 0 interrupt jmp @interrupt_ Dinput macro ;Change the data bus to input mov !RB,#%11111111 ;Set port B to input direction , crystal data bus input endm Doutput macro ;Change the data bus to output mov !RB,#%00000000 ;Set port B to output direction , crystal data bus output endm ; Write to Port B the W value at the address \1 iow macro 1 ; I/O port write PORT is the parameter mov RB,W ; writes W to the port B mov W,#\1 ; writes port value to W mov RA,W ; Activates A address port nop clrb RC._IOW ; Add nops here to make 1 nop=20ns nop nop nop nop nop nop nop nop setb RC._IOW endm ; performs IO read, \1 is the PORT parameter, or the PORT ; Result : W is the read value. iortoW macro 1 ;I/O port read no bank related mov W,#\1 mov RA,W ;set port nop clrb RC._IOR nop nop nop nop nop nop nop nop mov W,RB ;Get to W the Data in port B setb RC._IOR endm iortoWp mov RA,W ;set port nop clrb RC._IOR nop nop nop nop nop nop nop nop mov W,RB ;Get to W the Data in port B setb RC._IOR retp ; Reads values from packetPage port ; \1 is the 16 bits adress ; OffsetL,offsetH the low byte and high byte of \1 ; result in : ValueL and ValueH ppRD macro 1 ;Read PacketPage port mov W,#\1 & $ff mov offsetL,W mov W,#\1 >> 8 mov offsetH,W Doutput ;make the data bus output mov W,offsetL ;get the offset to read iow portPtr ;write to PacketPage Ptr mov W,offsetH ;get the high order offset iow portPtr+1 ;PagePacket Pointer Register high byte Dinput ;make the data bus input mov w,#portData ;read the PacketPage data call @iortoWp mov valueL,W ;save value low mov W,#portData+1 ;read the high order byte call @iortoWp mov valueH,W ;save the high order byte value endm ; Write to PacketPage port setup and command values to cs8900 registers ; \1 is the 16 bits adress ; \2 is the parameter to write ; offsetL,offsetH the low byte and high byte of \1 ppWR macro 2 ;Write PacketPage port mov W,#\1 & $ff mov offsetL,W mov W,#\1 >> 8 mov offsetH,W mov W,#\2 & $ff mov valueL,W mov W,#\2 >> 8 mov valueH,W call WritePP endm ;jmp TABLE _InitFIFO jmp @InitFIFO _ResetFIFO jmp @ResetFIFO _InitRAM jmp @InitRAM _testFIFO jmp @testFIFO _VerChip jmp @VerChip _ResetChip jmp @ResetChip _InitChip jmp @InitChip _SendArp jmp @SendArp _SendARPResponse jmp @SendARPResponse _ReceiveEvent jmp @ReceiveEvent _TransmitEventJMP jmp @TransmitEvent _wait1ms jmp @wait1ms _wait500ms jmp @wait500ms _wait500ns jmp @wait500ns ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; STARTING POINT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; reset_entry mov W,#31 mov M,W ; Mov M,#$1F DOES not WORK ; IMPORTANT -> Define that all mov !rx,#lit are ; related to define port direction, otherwise, PORT can behave as dead !!!! mov !rd,#%00000000 ; init rd (debug port) mov !RC,#%00001000 ; Set port C to output direction , ALL crystal ctrl signals, except INTR mov RD,#$FF ; Put 1s to Debug port call _wait500ms ; Start all high ! setb RESET_CS8900 ; Reset Hard Call _wait500ns ; More than 400ns clrb RESET_CS8900 ; clrb RD.6 call _wait500ms ; Leave time to cs8900 to initialize .... setb RD.6 clrb RD.7 call _wait1ms setb RD.7 ; init pulse mov !option,#%10011111 ;enable rtcc interrupt mov !RA,#%00000000 ; Set port A to output direction , crystal address bus output mov !RB,#%11111111 ; Set port B to input direction , crystal data bus mov !RE,#%00101000 ; Set port E (FIFO control) mov FSR,#$10 ; Change to Bank 1 , has no effect on variables on bank 0 setb RC._IOR ; no read on crystal setb RC._IOW ; no write on crystal clrb RC.CHIPSEL ; address enable mov RA,#0 ; clear PORTA mov fsr,#$0A ; reset ram banks 1..F, global :loopWipeMemory ; Delete all SX52 memory clr ind ijnz fsr,:loopWipeMemory ;FIFO and RAM init call _InitFIFO call _InitRAM call _ResetFIFO clrb RD.7 ; Startup bit call @_ResetChip ; takes 12.5ms setb RD.7 ; Startup bit call @_InitChip ;Setup ARP request mov FSR,#$10 clrb flags.3 ; Si a 1 parle a un gateway eventuel clrb flags.4 ; Si a 1 resete le cs8900 si rien n'est recu ; mettre a 1 ces flags a l'ESO ;Send ARP counter mov fsr,#$E0 mov RRefreshARPCounterLL,#$FF mov RRefreshARPCounterLH,#$FF mov RRefreshARPCounterHL,#$FF mov RRefreshARPCounterHH,#$0F ;Setup handcheck mov FSR,#$10 clrb HandCheckFlags.0 mov HandCheckTimeOut,#TimeOut mov FSR,#$F0 mov RAMNbSlotFree,#2 loopCs8900INTR ; wait for cs8900 Frame recieve interrupt mov RD,#$FF ; Put 1s to Debug port jb RC.INTR,endloop ; call _testFIFO ; Input FIFO from slave , is there is something ? ; Arp request refresh ; mov fsr,#$E0 decsz RRefreshARPCounterLL jmp RRefreshARPCounterNext1 mov RRefreshARPCounterLL,#$FF decsz RRefreshARPCounterLH jmp RRefreshARPCounterNext1 mov RRefreshARPCounterLH,#$FF decsz RRefreshARPCounterHL jmp RRefreshARPCounterNext1 mov RRefreshARPCounterHL,#$50 decsz RRefreshARPCounterHH jmp RRefreshARPCounterNext1 mov RRefreshARPCounterHH,#$01 mov FSR,#$10 sb flags.4 jmp RRefreshARPCounterNext1 call @_ResetChip call @_InitChip ;FIFO and RAM init call _InitFIFO call _InitRAM call _ResetFIFO call _sendARP clrb RD.2 ; ARP sent RRefreshARPCounterNext1 clrb RD.0 ; MainLoop jmp LoopCs8900INTR endloop mov FSR,#$10 sb flags.3 jmp NextEvt clrb flags.3 call _sendARP ; Read the ISQ NextEvt Dinput ;Reset CS8900 counter ;mov fsr,#$E0 ;mov RRefreshARPCounterLL,#$FF ;mov RRefreshARPCounterLH,#$FF ;mov RRefreshARPCounterHL,#$50 ;mov RRefreshARPCounterHH,#$01 clrb RD.2 ; ProcessISQ iortoW portISQ ;read interrupt status queue mov valueL,W ;save value low iortoW portISQ+1 ;read interrupt status queue high mov valueH,W ;save value high test valueL jz endISQ ;if zero, then done mov TempL,valueL mov W,#REG_NUM_RX_EVENT sub TempL,W ;IS RxEvent? sb STATUS.2 ;get low value if zero Z=1 jmp testeventSend: snb valueH.0 jmp evtRecv ;ppRD ppRxCfg ;Read RxConfig ;setb valueL.6 ;call WritePP ;jmp NextEvt testeventSend: mov TempL,valueL mov W,#REG_NUM_TX_EVENT sub TempL,W ; TxEvent? snb STATUS.2 ; Ignore BufEvent, RxMiss, and TxCol call @_TransmitEventJMP ; Nothing is done here .... jmp NextEvt evtRecv call _ReceiveEvent jmp NextEvt endISQ mov FSR,#$10 ; Change to Bank 1 sb flags.0 ; Is frame valid ? received frame flag jmp loopCs8900INTR clrb flags.0 ; clear the receive flag sb flags.1 ; bit set when valid arp jmp loopCs8900INTR clrb flags.1 ; clear the valid arp request flag call @_SendARPResponse jmp loopCs8900INTR org $200 ; Writes the value at valueH/valueL to the PagePacket register who's ; address is in offsetH/offsetL WritePP Doutput ;make the data bus output mov W,offsetL ;get the low order byte iow portPtr ;write to PacketPage Ptr mov W,offsetH ;get the high order byte iow portPtr+1 ;write to PacketPage ptr mov W,valueL ;get low order value to write iow portData ;write to PacketPage data mov W,valueH ;get high order data iow portData+1 ;write to PacketPage data retp ; wait for 1msec millisecond wait1ms mov TempH,#25 :wait_loop1 mov TempL,#255 :wait_loop2 nop nop nop nop nop nop djnz tempL,:wait_loop2 djnz tempH,:wait_loop1 retp ResetChip ppRD ppSelfCtl ;issue a reset to the chip setb valueL.6 call WritePP ;write it back to cs8900 ResetWait call wait1ms ;a millisecond ppRD ppSelfCtl ;get the Self Control status snb valueL.6 ;see it bit 6 (RESET) was cleared jmp ResetWait ;no, then still in reset, wait some more ppRD ppSelfSt ;get self status sb valueL.7 ;bit 7 is INITD jmp ResetWait ;when set, initialization of the CS8900 is done retp InitChip ; Writes registers to cs89000 ppWR ppTestCtl ,TEST_CTL_FDX ; set to full duplex ; Receive configuration ppWR ppRxCfg ,RX_CFG_RX_OK_IE ; enable RxOK interrupt ; Set receive control ppWR ppRxCtl ,(RX_CTL_RX_OK_A|RX_CTL_IND_A|RX_CTL_BCAST_A) ; Frame with CRC ok, between 64 and 1518 bytes + ; Frames are Ok if destination address match individual address PacketBasePage + $0158 and $015D ; Frames are Ok if destination address match multicast address that passes the hash filter ;ppWR ppTxCfg ,TX_CFG_ALL_IE ; set transmit config ; all Interrup Events are SET ; Important: The IA needs to be byte revered IA=aa:bb:cc:dd:ee:ff ; send MAC adress to cs8900 ppWR ppIndAddr ,(MAC2<<8|MAC1) ;$bbaa Write ppWR ppIndAddr+2,(MAC4<<8|MAC3) ;$ddcc out ppWR ppIndAddr+4,(MAC6<<8|MAC5) ;$ffee 48 bit IA ppWR ppIntNum,$00 ;INT is on INTRQ0 ppRD ppBusCtl ;get/read Bus Control setb valueH.7 ;enable irq call WritePP ;write it back to cs8900 ppRD ppLineCtl ;get Line Control setb valueL.6 ;set SerRxOn setb valueL.7 ;set SerTxOn call WritePP ;write it back to cs8900 retp ; 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 $3000 iortoW portPtr ; read PacketPage Ptr mov valueL,W ; save the read W value low mov FSR,#$10 mov AdrssL,valueL ; save Address iortoW portPtr+1 ; read PacketPage Ptr for high order byte mov RA,W ; set the address bus, copied to RA mov valueH,W ; save high low mov AdrssH,valueH ; save Address test valueL ; get low value if zero Z=1 sb STATUS.2 ; should be 0 (i.e. $3000 low is $00), if Z=0 skip next jmp VerBad mov TempH,valueH mov AdrssH,valueH ; save Address mov W,#$30 ; high part of $3000 sub TempH,W ; subtract from value obtained valueH=valueH-W sb STATUS.2 ; see if compared okay jmp VerBad ppRD ppEISA ; get the EISA number which MUST be $630E otherwise something has failed mov TempH ,valueH ; beware here W is modified !! mov ppEISH,valueH ; beware here W is modified !! mov W,#$63 sub TempH,W ; compare to $63 sb STATUS.2 jmp VerBad mov TempL ,valueL mov ppEISL,valueL ; beware here W is modified !! mov W, #$0E ; compare to $0E sub TempL,W sb STATUS.2 jmp VerBad ppRD ppProdID ; get the Product ID which should be 00$ xxxx 0000 0000 ; where x xxxx = 0 0011 for rev E and 0 0101 for rev F mov ppProdIDV,W ; set return status mov W,#0 retp ; Ok everything is OK mov W,#1 ; Failure !! VerBad retp ; return with status,z indicating success (Z) or not set for failure ; Transmit Event, nothing is done ! TransmitEvent retp ; 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 ;make sure it's 1 mov FSR,#$30 ; change de banque mov TempH,packet+ar_hwtype+1 mov W,#$01 ; check if sub TempH,W ; packet type sb STATUS.2 ;compare to low retp ;exit, bad request mov TempH,packet+ar_prtype ;compare to high mov W,#$08 sub TempH,W ;make sure it's 0x0800 sb STATUS.2 retp mov TempH,packet+ar_prtype+1 ;compare to high mov W,#$00 sub TempH,W ;make sure it's 0x0800 sb STATUS.2 retp mov TempH,packet+ar_hwlen ;compare to high mov W,#$06 sub TempH,W ;make sure it's 6 for hwlen sb STATUS.2 retp mov TempH,packet+ar_prlen ;compare to high mov W,#$04 ;make sure it's 4 for prlen sub TempH,W sb STATUS.2 retp mov TempH,packet+ar_op+1 ;compare to high mov W,#$01 ;make sure it's 1 for ARP request sub TempH,W sb STATUS.2 retp mov FSR,#$40 ; change de banque mov TempH,packet+ar_tpa ;compare to 1st IP adress mov W,#IP1 ;make sure it's 1 for ARP request sub TempH,W sb STATUS.2 retp mov TempH,packet+ar_tpa+1 ;compare to 2nd IP adress mov W,#IP2 ;make sure it's 1 for ARP request sub TempH,W sb STATUS.2 retp mov TempH,packet+ar_tpa+2 ;compare to 3rd IP adress mov W,#IP3 ;make sure it's 1 for ARP request sub TempH,W sb STATUS.2 retp mov TempH,packet+ar_tpa+3 ;compare to 4th IP adress mov W,#IP4 ;make sure it's 1 for ARP request sub TempH,W sb STATUS.2 retp ; If we got to here, then we have a valid ARP request for our(=in chip) IP address mov FSR,#$10 ; change de banque mov W,#$02 or flags,W ; flag frame read Inclusive IOR retp ; wait for 1msec millisecond wait500ms mov valueH,#50 ; 500ms :wait_loop_500ms1 mov TempH,#255 ; 10 ms :wait_loop_500ms2 mov TempL,#255 :wait_loop_500ms3 nop nop nop nop nop nop djnz tempL, :wait_loop_500ms3 djnz tempH, :wait_loop_500ms2 djnz ValueH,:wait_loop_500ms1 retp ; wait for 500ns wait500ns mov TempL,#15 :wait_loop_500ns nop djnz tempL, :wait_loop_500ns retp org $600 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Calc checksum. Reads packet at offset W for ; LengthH/LengthL bytes and calculates the checksum ; in valueH/valueL. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cksum ;offsetH -> W input starting address ;offsetL low checksum ;offsetH med checksum ;TempL hi checksum ;LengthH and lenghTL are length of the data to checksum ;ValueL and ValueH are the results mov OffsetH,W ; saves offset mov FSR,#$10 mov valueL ,LengthL mov TempH ,LengthH mov FSR,OffsetH ;set indirect adress clr offsetH ; 8-16 using a 24 clr offsetL ; 0-8 We do the arithmetic clr TempL ; 16-24 bit area clrb STATUS.0 ; set carry to zero cksuml mov W,INDF ;get high byte of 16-bit word mov valueH,W ;save it inc FSR mov W,INDF inc FSR add offsetL,W ; add to accum (1) sb STATUS.0 jmp noLcarry mov W,#$01 ; if carry add it to offsetH (2) add offsetH,W snb STATUS.0 inc TempL ; if carry add it to TempL (3) noLcarry mov W,valueH ; get the high byte again from the string to sum add offsetH,W ; add it to accum (2) snb STATUS.0 ; carry ? inc TempL ; Yes inc (3) mov W,#$02 ; subtract sub ValueL,W ; two byte from lengthL snb STATUS.0 ; see if negative (C=0) jmp CK1 ; C set so result is zero or better ; we are close to completion mov W,#$01 sub TempH,W ;decrement LengthH high sb STATUS.0 ;c=0 means negative jmp CkDone ;high went neg, we're done CK1 test valueL ;get low, is lengthL sb STATUS.2 ;Z=1 if zero jmp cksuml ;not zero, continue test TempH ; TempH is LenghH sb STATUS.2 ;Z=1 if zero jmp cksuml ;not zero, continue CkDone mov W,TempL ;get the third byte of 24 bit area (3) add offsetL,W ;any carries into this are added in snb STATUS.0 ;if that caused a carry, then inc offsetH ; increment the middle byte mov valueL,#$FF ;get and ones complement mov W,offsetL sub valueL,W ;save it to low mov valueH,#$FF ;get and ones complement mov W,offsetH sub valueH,W ;save as high retp SWAP_IP_MAC_ADDR_IPCKSUM mov FSR,#$30 ; change de banque clr packet+ip_cksum clr packet+ip_cksum+1 ;clear checksum mov TempH,packet+ip_src ;move mov FSR,#$40 ; change de banque mov packet+ip_dst,tempH ; ip mov FSR,#$30 ; change de banque mov TempH,packet+ip_src+1 ; of mov FSR,#$40 mov packet+ip_dst+1,TempH ; source mov FSR,#$30 mov TempH,packet+ip_src+2 ; to mov FSR,#$40 mov packet+ip_dst+2,TempH ; dest mov FSR,#$30 mov TempH,packet+ip_src+3 mov FSR,#$40 mov packet+ip_dst+3,TempH mov FSR,#$30 mov W,#IP1 ;move mov packet+ip_src,W ; our mov W,#IP2 ; ip mov packet+ip_src+1,W ; address mov W,#IP3 ; to mov packet+ip_src+2,W ; source mov W,#IP4 mov packet+ip_src+3,W mov FSR,#$20 mov W,packet+pktSrc0H ;move mov packet+pktDest0H,W ; mac src to dest mov W,packet+pktSrc0L mov packet+pktDest0L,W mov W,packet+pktSrc1H ;move mov packet+pktDest1H,W ;mac src to dest mov W,packet+pktSrc1L mov packet+pktDest1L,W mov W,packet+pktSrc2H ;move mov packet+pktDest2H,W ;mac src to dest mov W,packet+pktSrc2L mov packet+pktDest2L,W mov W,#MAC1 ;move mov packet+pktSrc0H,W ; our mov W,#MAC2 ; MAC mov packet+pktSrc0L,W ; address mov W,#MAC3 ; to mov packet+pktSrc1H,W ; source mov W,#MAC4 mov packet+pktSrc1L,W mov W,#MAC5 mov packet+pktSrc2H,W mov W,#MAC6 mov packet+pktSrc2L,W ; Compute here cheksum of IP header mov FSR,#$10 mov W,#$14 ; length of IP header mov lengthL,W ; set length of clr lengthH ; checksum calculation mov FSR,#$30 mov W,#packet+ip_verlen ; displacement to of IP header call cksum ; calculate the checksum mov FSR,#$30 mov packet+ip_cksum ,valueH ;set new checksum mov packet+ip_cksum+1,valueL retp ; ; Process ICMP (ping) requests ; DoICMP ; Create the response FRAME for PING requests ; builds the Frame to be sent into the chip RAM ; not so easy ??? ; All Ip_* are located at $30 ; ip_dst equ $20 are on bank $40 ; ip_data equ $24 are on bank $40 ; ic* equ $24 are on bank $40 ; test checksum routine and compare it with the actual IP value ;mov FSR,#$10 ;mov W,#$14 ; length of IP header ;mov lengthL,W ; set length of ;clr lengthH ; checksum calculation ;mov FSR,#$30 ;clr packet+ip_cksum ;clr packet+ip_cksum+1 ; clear checksum ;mov W,#packet+ip_verlen ; displacement to start of IP header ;call cksum ; calculate the checksum ;mov FSR,#$40 ;stc ;cse packet+ip_dst ,#IP1 ;retp ;cse packet+ip_dst+1,#IP2 ;retp ;cse packet+ip_dst+2,#IP3 ;retp ;cse packet+ip_dst+3,#IP4 ;retp mov FSR,#packet+ic_type stc cje IND,#8,:DoICMP_next1 retp :DoICMP_next1 mov FSR,#$30 mov packet+ip_ttl,#128 ; Update Time To Live in IP header call SWAP_IP_MAC_ADDR_IPCKSUM ; swap Adresses and compute IP checksum ; don't change anything here about IP header anymore mov FSR,#$40 clr packet+ic_cksum ;clear ICMP clr packet+ic_cksum+1 ; checksum clr packet+ic_type ;make type a reply clr packet+ic_code ;clear code ; here remove lengthL=TotalIPacketLength-IPheaderLength to have the right value of the ICMP header+data length mov FSR,#$30 mov TempH,packet+ip_len ;get length high IP packet length (length-header_length) mov TempL,packet+ip_len+1 ;get length low mov FSR,#$10 mov lengthH,TempH ; save it, typically $00 mov lengthL,TempL ; save it, typically $3C mov W,#$14 ;ip header length sub lengthL,W ;calc length of ICMP header+data , remove length of IP pure header snb STATUS.2 dec lengthH ;if prev sub went neg then dec high mov FSR,#$40 mov W,#packet+ic_type ;start of ICMP header at W for checksum call cksum mov FSR,#$40 mov W,valueH ;set new checksum for icmp mov packet+ic_cksum,W mov W,valueL mov packet+ic_cksum+1,W ; ckecksum OK ; start to send data to cs8900 Doutput ; Writes the frame to CS8900S mov W,#TX_CMD_START_ALL iow portTxCmd mov W,#$00 iow portTxCmd+1 mov FSR,#$20 mov W,packet+pktLenL ; length of ICMP response frame iow portTxLength ; is the same as mov W,packet+pktLenH ; the request. iow portTxLength+1 ICMPGetStat ppRD ppBusSt ; get BusStatus sb valueH.0 ; is BUS_ST_RDY4TXNOW (ready for transmit) jmp ICMPGetStat ; no, wait for it Doutput mov FSR,#$20 mov ValueL,packet+pktLenL ;length, always less than 255 bytes mov W,#packet+pktDest0H mov FSR,W WritePing ;send the DATA to cs8900 mov W,INDF ;get next byte iow portRxTxData inc FSR mov W,INDF ;get next byte iow portRxTxData+1 inc FSR dec valueL decsz valueL jmp WritePing ;not zero, continue mov FSR,#$10 ICMPDone retp ;;;;;;;;;;;;; Makes UDP reply FRAME OrderFromPCPk equ $FA org $800 ; jump table to go across pages boudaries _SendDATAToUDPFromRAM jmp @SendDATAToUDPFromRAM __ResetFIFO jmp @ResetFIFO _writeRAM jmp @writeRAM _FillFIFO jmp @FillFIFO _SWAP_IP_MAC_ADDR_IPCKSUM jmp @SWAP_IP_MAC_ADDR_IPCKSUM _cksum jmp @cksum _Send_PacketHeader jmp @Send_PacketHeader _Send_PacketDATA jmp @Send_PacketDATA _Send_UDPDATAFromRAM jmp @Send_UDPDATAFromRAM TestFIFO ;Communication still not initialised mov FSR,#$10 sb flags.2 retp ;Test handCheck ;;;;;;;;;;;;;;; mov FSR,#$10 sb HandCheckFlags.0 jmp :TestFIFO_next4 ; no handcheck, ; There is a hand check ? test HandCheckCountH sz jmp :TestFIFO_next4 ;decsz HandCheckNbTry ; HandCheckNbTry is removed, send the packet until an asteroid fall on the SX52 !!.. ;jmp :TestFIFO_next7 ;clrb HandCheckFlags.0 ; Send again and again the next slot... ; at first, find the next unfree slot ! ;Choose a slot, it's always the oldest sent packet ; DEBUG DEBUG, it's only the next unfree slot..., find the next unfree slot ; mov FSR,#$F0 ; clr RAMSlotToWriteRead ;:TestFIFO_loop20 ; mov FSR,#RAMSlotFree ; add FSR,RAMSlotToWriteRead ; snb IND.0 ; jmp :TestFIFO_loop21 ; inc RAMSlotToWriteRead ; jmp :TestFIFO_loop20 ;:TestFIFO_loop21 mov tempL,#0 mov FSR,#$10 mov tempH,packetNbSend mov FSR,#$F0 mov RAMSlotToWriteRead,#1 :TestFIFO_loop20 mov FSR,#RAMSlotFree add FSR,RAMSlotToWriteRead sb IND.0 jmp :TestFIFO_loop22 ; select the oldest packet mov FSR,#RAMpacketNbSendSlot add FSR,RAMSlotToWriteRead mov OffsetH,IND mov OffsetL,TempH sub OffsetL,OffsetH csae OffsetL,tempL jmp :TestFIFO_loop22 ; Update the oldest packet mov tempL,OffsetL mov valueL,RAMSlotToWriteRead :TestFIFO_loop22 ; Test if RAMSlotToWriteRead is equal to 0 test RAMSlotToWriteRead snz jmp :TestFIFO_loop21 dec RAMSlotToWriteRead jmp :TestFIFO_loop20 :TestFIFO_loop21 mov RAMSlotToWriteRead,valueL ; Slot found, it's the RAMSlotToWriteRead slot ; Send the slot to CS8900 ; Set up the slot to write call _SendDATAToUDPFromRAM ;Wait for the next handcheck ;Setup the next handcheck mov FSR,#$10 mov HandCheckCountH,#HandCheckTimeOut mov HandCheckCountL,#255 :TestFIFO_next4 ;End of test hand check ;;;;;;;;;;;;;; ;;;;;;;;;;;;;; ; Send a packet if the FIFO is not empty and if there is a free slot to put the next packet into ;Test if FIFO is empty sb EmptyFIFO retp ;if ok, send the data to UDP ;Fill the buffer at first mov FSR,#$F0 ;Check if there is a free memory slot, otherwise return test RAMnbSlotFree snz retp ;Find the next free slot :TestFIFO_loop10 mov FSR,#RAMSlotFree add FSR,RAMCurrentSlot sb IND.0 jmp :TestFIFO_loop1 inc RAMCurrentSlot csne RAMCurrentSlot,#2 clr RAMCurrentSlot jmp :TestFIFO_loop10 :TestFIFO_loop1 ;Set DataBus to input DInput clrb FIFORead nop nop mov FSR,#$F0 mov W,RB ;Get to W the Data in port B setb FIFORead ;Si RAMPacket=0 , on update RAMPacketToSendH ;Si RAMPacket=1 , on update RAMPacketToSendL test RAMPacket jnz :TestFIFO_next1 mov RAMPacketToSendH,w inc RAMPacket jmp :TestFIFO_next3 :TestFIFO_next1 mov ValueH,w stc cjne RAMPacket,#1,:TestFIFO_next5 mov RAMPacketToSendL,ValueH inc RAMPacket ;Decremente de 2 (Compatible anciennes version (V2)) test RAMPacketToSendL snz dec RAMPacketToSendH dec RAMPacketToSendL snz dec RAMPacketToSendH dec RAMPacketToSendL ; On test si la taille du packet est correcte, sinon reset FIFO cjbe RAMPacketToSendH,6,:TestFIFO_next3 call __ResetFIFO clr RAMPacket clr RAMPacketL clr RAMPacketH retp :TestFIFO_next5 ;On ecrit la valeur dans la RAM call _writeRAM inc RAMPacketL snz inc RAMPacketH stc cjne RAMPacketL,RAMPacketToSendL,:TestFIFO_next3 stc cjne RAMPacketH,RAMPacketToSendH,:TestFIFO_next3 ;compare RAMPacket et RAMPacketToSend test RAMPacketH jnz :TestFIFO_next2 stc cje RAMPacketL,#1,:TestFIFO_next3 :TestFIFO_next2 ; Send Data to UDP mov FSR,#$10 inc packetNbSend mov tempH,packetNbSend mov FSR,#$F0 ; Set up the slot to write mov RAMSlotToWriteRead,RAMCurrentSlot mov FSR,#RAMpacketNbSendSlot add FSR,RAMSlotToWriteRead mov IND,TempH ; RAMnbSlotFree decreased by one dec RAMnbSlotFree ; Slot is no more free mov FSR,#$F0 mov FSR,#RAMSlotFree add FSR,RAMSlotToWriteRead setb IND.0 mov FSR,#RAMPacketToSendSlotH add FSR,RAMSlotToWriteRead mov IND,RAMPacketToSendH mov FSR,#RAMPacketToSendSlotL add FSR,RAMSlotToWriteRead mov IND,RAMPacketToSendL call _SendDATAToUDPFromRAM ;Wait for the handcheck ;Setup the handcheck mov FSR,#$10 snb HandCheckFlags.0 jmp :TestFIFO_next30 mov HandCheckNbTry,#NbRetry setb HandCheckFlags.0 mov HandCheckCountH,#HandCheckTimeOut mov HandCheckCountL,#255 :TestFIFO_next30 ;clear the current RAMPointer, next Slot... mov FSR,#$F0 clr RAMPacket clr RAMPacketH clr RAMPacketL retp :TestFIFO_next3 snb EmptyFIFO jmp :TestFIFO_loop1 retp ;; Process Order, if nothings DONE udp DATA+2 is still cleared DoUDP mov FSR,#$40 ; All the UDP header is there stc cse packet+ip_dst,#IP1 retp cse packet+ip_dst+1,#IP2 retp cse packet+ip_dst+2,#IP3 retp cse packet+ip_dst+3,#IP4 retp cse packet+u_dst+1 ,#UDP_PORT_SCR retp cje packet+u_data+1,#0,:DOUdp_ifend1 ;Reset cje packet+u_data+1,#1,:DOUdp_ifend1 ;Data receive cje packet+u_data+1,#2,:DOUdp_ifend3 ;Data send retp :DOUdp_ifend1 ; Compare to last packet number ; If message already received, then ; Send back again the handcheck whitout executing the command mov FSR,#$40 mov TempH,packet+u_data mov FSR,#$10 stc cje packetNbReceive,TempH,:DOUdp_ifend2 ;Execute command mov FSR,#$40 cje packet+u_data+1,#1,:DOUdp_ifend4 ;Reset all call __ResetFIFO mov FSR,#$F0 clr RAMPacketL clr RAMPacketH mov FSR,#$40 mov packet+u_data+1,#1 mov FSR,#$10 mov packetNbSend,#0 jmp :DOUdp_ifend2 :DOUdp_ifend4 ;Send data to FIFO stc mov FSR,#$40 mov valueL,packet+u_len+1 sub valueL,#10 mov OffsetL,#packet+u_data+2 call _FillFIFO clc :DOUdp_ifend2 ; Send the handcheck ; Update last packet number mov FSR,#$40 ; All the UDP header is there mov TempH,packet+u_data mov FSR,#$10 mov packetNbReceive,TempH ; Sends back Data call _SWAP_IP_MAC_ADDR_IPCKSUM mov FSR,#$40 ; All the UDP header is there clr packet+u_cksum ; clear UDP checksum, UDP checksum IS USELESS clr packet+u_cksum+1 ; clear byte two ; Swap source-dest mov TempL,packet+u_src ;get src port mov packet+u_dst,TempL ;put src port mov TempL,packet+u_src+1 ;get src port mov packet+u_dst+1,TempL ;put src port clr packet+u_src mov packet+u_src+1,#UDP_PORT_SCR ; write the LOCAL UDP port ;Set priority mov FSR,#$30 and packet+ip_tos,#$03 or packet+ip_tos,#IPPriority clc ; Update the packet size mov offsetL,#2 ; Update UDP header size mov FSR,#$40 mov packet+u_len+1,offsetL add packet+u_len+1,#8 ; Update IP header size mov FSR,#$30 mov packet+ip_len+1,offsetL add packet+ip_len+1,#28 mov FSR,#$20 mov packet+pktLenL,offsetL add packet+pktLenL,#42 csa packet+pktLenL,#60 mov packet+pktLenL,#60 ; Compute here cheksum of IP header mov FSR,#$30 ; change de banque clr packet+ip_cksum clr packet+ip_cksum+1 ;clear checksum mov FSR,#$10 mov W,#$14 ; length of IP header mov lengthL,W ; set length of clr lengthH ; checksum calculation mov FSR,#$30 mov W,#packet+ip_verlen ; displacement to of IP header call _cksum ; calculate the checksum mov FSR,#$30 mov packet+ip_cksum ,valueH ;set new checksum mov packet+ip_cksum+1,valueL ; OK all the frame is ready, now send it back to cs8900 call _Send_PacketHeader call _Send_PacketDATA ; Backup the header mov offsetL,#Packet mov offsetH,#PacketBackup mov valueL,#$30 :DoUDP_loop1 mov FSR,offsetL mov TempH,IND mov FSR,offsetH mov IND,TempH inc offsetL inc offsetH djnz valueL,:DoUDP_loop1 ;Header saved mov FSR,#$10 setb flags.2 retp :DOUdp_ifend3 ;Read mov FSR,#$40 ; All the UDP header is there mov tempL,packet+u_data mov tempH,#2 :DOUdp_ifend11 mov FSR,#RAMpacketNbSendSlot add FSR,tempH dec FSR stc cje IND,tempL,:DOUdp_ifend10 dec tempH sz jmp :DOUdp_ifend11 retp :DOUdp_ifend10 ; Release a slot mov FSR,#$F0 mov FSR,#RAMSlotFree add FSR,TempH dec FSR snb IND.0 inc RAMnbSlotFree clrb IND.0 ; if all the slot are free, no more handcheck stc cse RAMnbSlotFree,#2 retp mov FSR,#$10 clrb HandCheckFlags.0 retp :DOUdp_ifend5 org $A00 _DoARpJMP jmp @DoArp _DOIPCMP jmp @DoICMP _DoUDP jmp @DoUDP __Send_PacketHeader jmp @Send_PacketHeader __Send_PacketData jmp @Send_PacketData _prepareARPResponse jmp @prepareARPResponse _PrepareARP jmp @PrepareARP _PrepareARPForRequest jmp @PrepareARPForRequest __cksum jmp @cksum ; READ buffer from CS8900 MaxPCKsize equ 128 ; Max paquet SIZE , otherwise kills all !! ReadBufferCS8900 Dinput ;make data bus input ; ; It's important to read the status and length high-order ; byte first. ; iortoW portRxTxData+1 ;read and discard status iortoW portRxTxData ;read and discard status; don't care of W mov W,#packet ;set indirect mov FSR,W ; address iortoW portRxTxData+1 ;get length high mov ValueH,W mov packet+pktLenH,ValueH ;save in header area, bank 2 mov FSR,#$10 ; Change to Bank 1 mov lengthH,ValueH ; and in lengthH mov TempH,ValueH ; and in lengthH mov W,#$00 sub TempH,W ;IS packet more than n x 256 bytes ? snb STATUS.2 ;if Zero jmp OKlengthPP mov FSR,#$20 ; Yes ! clr packet+pktLenL clr packet+pktLenH retp ;no ? let's go out OKlengthPP mov FSR,#$20 ; Change back to Bank 2 where the data or frame is stored iortoW portRxTxData ;get length low mov ValueL,W mov packet+pktLenL,ValueL ;save in header area mov TempL,ValueL clr W sub TempL,W ; IS packet null ? snb STATUS.2 ; if zero, go out retp ; No ? let's go out mov TempL,#MaxPCKsize ; MAX PackET SIZE mov W,ValueL sub TempL,W ; IS packet less than #MaxPCK ? snb STATUS.0 ; if zero, go out jmp ReadFrame mov FSR,#$20 ; Yes ! clr packet+pktLenL clr packet+pktLenH retp ;No ? let's go out ReadFrame ; Something wird here, packet MUST be even !! snb ValueL.0 inc ValueL ; Add one mov W,#packet+1 ;set indirect mov FSR,W ; address RFCont iortoW portRxTxData ;read from CS8900 inc FSR ;increment pointer mov INDF,W ;Writes to the RAM iortoW portRxTxData+1 ;read from CS8900 inc FSR mov INDF,W dec valueL decsz valueL jmp RFCONT mov FSR,#$10 ; Change to Bank 1 mov W,#01 or flags,W ; flag frame read Inclusive IOR mov W,#packet ;set indirect mov FSR,W ; address to bank 2 ReadDone ; FRAME read, DONE and stored into the RAM retp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Receive Event ; Input with RxEvent in valueH ; ReceiveEvent call ReadBufferCS8900 mov TempH,packet+pktLenL ; If packet is null go OUT mov W,#$00 snb STATUS.2 retp ;;;;;;;;; Analyze the FRAME ;;;;;;;;;;;;; mov TempH,packet+pktTypeH mov W,#$08 ; check if sub TempH,W ; packet type sb STATUS.2 ; is $0806 ->>>>>>>>> (ARP) jmp @ChkIP ; no, check IP mov TempH,packet+pktTypeL mov W,#$06 sub TempH,W snb STATUS.2 call _DoARpJMP ; goes to the JMP table, simple call ChkIP mov W,#packet+pktTypeH ;set indirect mov FSR,W ; address to bank 2 mov TempH,packet+pktTypeH mov W,#$08 ; check if sub TempH,W sb STATUS.2 ; is $0800 ->>>>>>>>> (IP) retp ; no IP ?, then just return mov TempL,packet+pktTypeL ; test low byte test TempL sb STATUS.2 retp mov W,#packet+ip_proto ; set indirect mov FSR,W ; address to bank mov TempH,packet+ip_proto mov W,#IPT_ICMP ; get protocol number for ICMP sub TempH,W ; compare to this packet's proto snb STATUS.2 ; if zero, then it's ICMP (Ping) call _DOIPCMP ; process ICMP packet mov TempH,packet+ip_proto mov W,#IPT_UDP ; get protocol number for ICMP sub TempH,W ; compare to this packet's proto snb STATUS.2 ; if zero, then it's ICMP (Ping) call _DoUDP ; process ICMP packet retp PrepareARPForRequest mov FSR,#$20 mov packet+pktDest0H,#$FF mov packet+pktDest0L,#$FF mov packet+pktDest1H,#$FF mov packet+pktDest1L,#$FF mov packet+pktDest2H,#$FF mov packet+pktDest2L,#$FF mov FSR,#$30 ; Send operation (request) mov packet+ar_op , #$00 mov packet+ar_op+1, #$01 ; Send Target HW address mov FSR,#$40 mov packet+ar_tha ,#0 mov packet+ar_tha+1,#0 mov packet+ar_tha+2,#0 mov packet+ar_tha+3,#0 mov packet+ar_tha+4,#0 mov packet+ar_tha+5,#0 ; Send Target IP mov packet+ar_tpa ,#GIP1 mov packet+ar_tpa+1,#GIP2 mov packet+ar_tpa+2,#GIP3 mov packet+ar_tpa+3,#GIP4 retp PrepareARP mov FSR,#$20 clr packet+pktLenH mov packet+pktLenL,#60 mov packet+pktSrc0H,#MAC1 mov packet+pktSrc0L,#MAC2 mov packet+pktSrc1H,#MAC3 mov packet+pktSrc1L,#MAC4 mov packet+pktSrc2H,#MAC5 mov packet+pktSrc2L,#MAC6 ; Send type mov packet+pktTypeH,#$08 mov packet+pktTypeL,#$06 mov FSR,#$30 ; Send hwtype mov packet+ar_hwtype , #$00 mov packet+ar_hwtype+1, #$01 ; Send prtype (protocol type) mov packet+ar_prtype , #$08 mov packet+ar_prtype+1, #$00 ; Send hardware and protocol address lengths mov packet+ar_hwlen, #$06 mov packet+ar_hwlen+1, #$04 ; Send Senders HW address mov packet+ar_sha ,#MAC1 mov packet+ar_sha+1,#MAC2 mov packet+ar_sha+2,#MAC3 mov packet+ar_sha+3,#MAC4 mov packet+ar_sha+4,#MAC5 mov packet+ar_sha+5,#MAC6 ; Send Senders IP mov FSR,#$30 mov packet+ar_spa , #IP1 mov packet+ar_spa+1, #IP2 mov FSR,#$40 mov packet+ar_spa+2, #IP3 mov packet+ar_spa+3, #IP4 retp prepareARPResponse mov FSR,#$20 mov packet+pktDest0H,packet+pktSrc0H mov packet+pktDest0L,packet+pktSrc0L mov packet+pktDest1H,packet+pktSrc1H mov packet+pktDest1L,packet+pktSrc1L mov packet+pktDest2H,packet+pktSrc2H mov packet+pktDest2L,packet+pktSrc2L mov FSR,#$30 ; Send operation (response) mov packet+ar_op , #$00 mov packet+ar_op+1, #$02 ; Send Target IP mov FSR,#$30 mov TempL, packet+ar_spa mov FSR,#$40 mov packet+ar_tpa,TempL mov FSR,#$30 mov TempL, packet+ar_spa+1 mov FSR,#$40 mov packet+ar_tpa+1,TempL mov packet+ar_tpa+2,packet+ar_spa+2 mov packet+ar_tpa+3,packet+ar_spa+3 ; Send Target HW address mov FSR,#$20 mov TempL,packet+pktDest0H mov FSR,#$40 mov packet+ar_tha ,TempL mov FSR,#$20 mov TempL,packet+pktDest0L mov FSR,#$40 mov packet+ar_tha+1,TempL mov FSR,#$20 mov TempL,packet+pktDest1H mov FSR,#$40 mov packet+ar_tha+2,TempL mov FSR,#$20 mov TempL,packet+pktDest1L mov FSR,#$40 mov packet+ar_tha+3,TempL mov FSR,#$20 mov TempL,packet+pktDest2H mov FSR,#$40 mov packet+ar_tha+4,TempL mov FSR,#$20 mov TempL,packet+pktDest2L mov FSR,#$40 mov packet+ar_tha+5,TempL retp ; SendARP - Send a response ARP to the requestor ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SendARPResponse call _prepareARPResponse call _PrepareARP call __Send_PacketHeader call __Send_PacketData retp SendARP call _PrepareARPForRequest call _PrepareARP call __Send_PacketHeader call __Send_PacketData retp InitRAM setb RAMWrite setb RAMRead mov FSR,#$F0 clr RAMPacketToSendH clr RAMPacketToSendL clr RAMPacketH clr RAMPacketL retp InitFIFO setb FIFOWrite setb FIFORead setb clearFIFO retp ResetFIFO clrb clearFIFO nop nop nop nop nop nop nop nop nop nop nop setb clearFIFO retp fillFIFO DOutput clr TempL :fillFIFO_loop1 mov FSR,offsetL add FSR,TempL mov w,IND mov RB,w nop clrb FIFOWrite nop setb FIFOWrite inc TempL djnz valueL,:fillFIFO_loop1 retp writeRAM DOutput mov FSR,#$F0 mov RA,RAMPacketL setb RE.2 setb RE.1 setb RE.0 sb RAMPacketH.0 clrb RE.0 sb RAMPacketH.1 clrb RE.1 sb RAMCurrentSlot.0 clrb RE.2 mov RB,valueH nop clrb RAMWrite nop setb RAMWrite retp readRAM DInput mov RA,OffsetL setb RE.2 setb RE.1 setb RE.0 sb OffsetH.0 clrb RE.0 sb OffsetH.1 clrb RE.1 sb RAMSlotToWriteRead.0 clrb RE.2 nop clrb RAMRead nop mov w,RB mov valueH,w setb RAMRead retp org $C00 ___Send_PacketHeader jmp @Send_PacketHeader __Send_UDPDATAFromRAM jmp @Send_UDPDATAFromRAM ___cksum jmp @cksum SendDATAToUDPFromRAM ;Send data to UDP :SendDATAToUDPFromRAM_next7 ; Restore the header mov offsetL,#Packet mov offsetH,#PacketBackup mov valueL,#$30 :SendDATAToUDPFromRAM_loop2 mov FSR,offsetH mov TempH,IND mov FSR,offsetL mov IND,TempH inc offsetL inc offsetH djnz valueL,:SendDATAToUDPFromRAM_loop2 ; Send data header (2 bytes) mov FSR,#RAMpacketNbSendSlot add FSR,RAMSlotToWriteRead mov TempH,IND mov FSR,#packet+u_data mov IND,TempH inc FSR mov IND,#2 ;Set priority mov FSR,#$30 and packet+ip_tos,#$03 or packet+ip_tos,#IPPriority mov FSR,#RAMPacketToSendSlotH add FSR,RAMSlotToWriteRead mov offsetH,IND mov FSR,#RAMPacketToSendSlotL add FSR,RAMSlotToWriteRead mov offsetL,IND clc add offsetL,#2 snc inc OffsetH ; Update UDP header size mov FSR,#$40 mov packet+u_len,offsetH mov packet+u_len+1,offsetL add packet+u_len+1,#8 snc inc packet+u_len ; Update IP header size mov FSR,#$30 mov packet+ip_len ,offsetH mov packet+ip_len+1,offsetL add packet+ip_len+1,#28 snc inc packet+ip_len mov FSR,#$20 mov packet+pktLenH,offsetH mov packet+pktLenL,offsetL add packet+pktLenL,#42 snc inc packet+pktLenH test packet+pktLenH sz jmp :SendDATAToUDPFromRAM_next6 stc cjae packet+pktLenL,#60,:SendDATAToUDPFromRAM_next6 mov packet+pktLenL,#60 :SendDATAToUDPFromRAM_next6 clc ; Compute here cheksum of IP header mov FSR,#$30 ; change de banque clr packet+ip_cksum clr packet+ip_cksum+1 ;clear checksum mov FSR,#$10 mov W,#$14 ; length of IP header mov lengthL,W ; set length of clr lengthH ; checksum calculation mov FSR,#$30 mov W,#packet+ip_verlen ; displacement to of IP header call ___cksum ; calculate the checksum mov FSR,#$30 mov packet+ip_cksum ,valueH ;set new checksum mov packet+ip_cksum+1,valueL ; Send UDP packet call ___Send_PacketHeader call __Send_UDPDATAFromRAM ;Write from RAM retp org $E00 ; JMP table __ReadRAM jmp @ReadRAM ; Interrupt routine interrupt_ mov FSR,#$10 test HandCheckCountH snz jmp :interrupt_endif1 decsz HandCheckCountL jmp :interrupt_nextif2 dec HandCheckCountH mov HandCheckCountL,#255 jmp :interrupt_endif2 :interrupt_nextif2 dec HandCheckCountL :interrupt_endif2 :interrupt_endif1 mov w,#-255 ;1 ;interrupt every 255 clocks (1.3 ms for 50megas) retiw ;3 Send_PacketHeader Doutput clrb RD.4 mov W,#TX_CMD_START_ALL iow portTxCmd clr W iow portTxCmd+1 mov FSR,#$20 ; Something wird here, packet MUST be even !! sb (packet+pktLenL).0 jmp :Send_PacketHeader_next1 inc packet+pktLenL snz inc packet+pktLenH :Send_PacketHeader_next1 mov W,packet+pktLenL ; send length to CS8900 iow portTxLength mov W,packet+pktLenH iow portTxLength+1 UDPGetStat ppRD ppBusSt ; get BusStatus sb valueH.0 ; is BUS_ST_RDY4TXNOW (ready for transmit) jmp UDPGetStat ; no, wait for it mov ValueL,#44 ; set it for the final loop mov FSR,#packet+pktDest0H Doutput WriteUDP ; writes DATA to cs8900 mov W,INDF ;get next byte iow portRxTxData inc FSR mov W,INDF ;get next byte iow portRxTxData+1 inc FSR dec valueL decsz valueL jmp WriteUDP ;not zero, continue retp Send_PacketData mov FSR,#$20 mov ValueL,packet+pktLenL ; set it for the final loop stc sub ValueL,#44 mov FSR,#packet+u_data+2 WriteUDPDATA ; writes DATA to cs8900 mov W,INDF ;get next byte iow portRxTxData inc FSR mov W,INDF ;get next byte iow portRxTxData+1 inc FSR dec valueL decsz valueL jmp WriteUDPDATA ;not zero, continue DInput retp Send_UDPDataFromRAM ;Write from RAM mov FSR,#$20 mov TempH,packet+pktLenH ; set it for the final loop mov TempL,packet+pktLenL ; set it for the final loop stc sub TempL,#44 sc dec TempH clr OffsetH clr OffsetL mov FSR,#$F0 WriteUDPFromRAM call __ReadRAM doutput ;Optimisation mov RB,ValueH ; writes W to the port B mov RA,#portRxTxData nop clrb RC._IOW ; Add nops here to make 1 nop=20ns inc OffsetL snz inc OffsetH nop nop nop nop setb RC._IOW call __ReadRAM doutput ;Optimisation mov RB,ValueH ; writes W to the port B mov RA,#portRxTxData+1 ; Activates A address port nop clrb RC._IOW ; Add nops here to make 1 nop=20ns inc OffsetL snz inc OffsetH stc sub TempL,#2 sc dec TempH setb RC._IOW Test TempL jnz WriteUDPFromRAM Test TempH jnz WriteUDPFromRAM retp