'********************************* ' Very basic IP implementation ' ' by john.timmins@link.co.nz ' ' This file is IP_GENERIC.BAS ' ' Please let me know the bugs! ' '********************************* ' ' 'UDP offset constants Const Offset_udp_src_port = 17 Const Offset_udp_dst_port = 18 Const Offset_udp_length = 19 Const Offset_udp_checksum = 20 Const Offset_udp_data = 21 'ICMP offset constants Const Offset_icmp_typecode = 17 Const Offset_icmp_checksum = 18 Const Offset_icmp_identifier = 19 Const Offset_icmp_sequence = 20 Const Offset_icmp_data = 21 'IP Header Offset Constants Const Offset_ip_ver_len_tos = 7 Const Offset_ip_len = 8 Const Offset_ip_id = 9 Const Offset_ip_fragoffset = 10 Const Offset_ip_ttl_proto = 11 Const Offset_ip_hdr_chksum = 12 Const Offset_ip_srcadd_1 = 13 Const Offset_ip_srcadd_2 = 14 Const Offset_ip_dstadd_1 = 15 Const Offset_ip_dstadd_2 = 16 'Frame Data Offset Constants Const Offset_frame_dst_mac_1 = 0 Const Offset_frame_dst_mac_2 = 1 Const Offset_frame_dst_mac_3 = 2 Const Offset_frame_src_mac_1 = 3 Const Offset_frame_src_mac_2 = 4 Const Offset_frame_src_mac_3 = 5 Const Offset_frame_type = 6 'ARP frame offset constants Const Offset_ar_hwtype = 7 Const Offset_ar_prtype = 8 Const Offset_ar_hwlen_prlen = 9 Const Offset_ar_op = 10 Const Offset_ar_sha_1 = 11 Const Offset_ar_sha_2 = 12 Const Offset_ar_sha_3 = 13 Const Offset_ar_spa_1 = 14 Const Offset_ar_spa_2 = 15 'PacketPage constants Const Rx_tx_data_port_0 = &H00 Const Tx_command_port = &H04 Const Tx_length_port = &H06 Const Packet_page_pointer_port = &H0A Const Packet_page_data_port_0 = &H0C 'PacketPage Offset constants Const Pp_eisa_registration_number = &H0000 Const Pp_product_identification_code = &H0002 Const Pp_receiver_configuration = &H0102 Const Pp_receiver_control = &H0104 Const Pp_transmitter_configuration = &H0106 Const Pp_buffer_configuration = &H010A Const Pp_line_control = &H0112 Const Pp_self_control = &H0114 Const Pp_test_control = &H0118 Const Pp_receiver_event = &H0124 Const Pp_transmitter_event = &H0128 Const Pp_buffer_event = &H012C Const Pp_line_status = &H0134 Const Pp_self_status = &H0136 Const Pp_bus_status = &H0138 Const Pp_transmit_command_request = &H0144 Const Pp_transmit_length = &H0146 Const Pp_individual_address = &H0158 'Receiver Event masks Const Rx_event_receive_ok = &H0100 'Self Control masks Const Self_control_reset = &H0040 'Self Status masks Const Self_status_init_complete = &H0080 'Bus Status masks Const Bus_status_transmit_bid_error = &H0080 Const Bus_status_rdy4txnow = &H0100 'Line Control masks Const Line_control_receiver_on = &H0040 Const Line_control_transmitter_on = &H0080 Const Line_control_10baset = &H0000 'Test Control masks Const Test_control_half_duplex = &H0000 'RX Config reg Const Receiver_configuration_skip = &H0040 'RX Control reg Const Rx_ctl_promiscuous = &H0080 Const Rx_ctl_rx_ok_a = &H0100 Const Rx_ctl_ind_addr = &H0400 Const Rx_ctl_bcast_a = &H0800 'TX Event reg Const Tx_event_tx_ok = &H0100 Const Tx_event_out_win = &H0200 Const Tx_event_jabber = &H0400 Const Tx_event_16_coll = &H1000 'TX Command reg Const Tx_cmd_start_all = &H00C0 'Buffer Config reg Const Buf_cfg_sw_int = &H0040 Const Buf_cfg_rdy4tx_ie = &H0100 Const Buf_cfg_tx_undr_ie = &H0200 'Subroutine declarations Declare Sub Chipver Declare Sub Chipread Declare Sub Chipwrite Declare Sub Ppread Declare Sub Ppwrite Declare Sub Setpppointer Declare Sub Swapvalue16 Declare Sub Resetcs8900 Declare Sub Initcs8900 Declare Sub Purge_frame Declare Sub Txword Declare Sub Rxword Declare Sub Settxlen Declare Sub Starttx Declare Sub Wait_for_frame Declare Sub Receive_frame Declare Sub Transmit_frame Declare Sub Arp_reply Declare Sub Linkstatus 'Dimension variables Dim Addr As Word Dim Ppoffset As Word Dim Value8 As Byte Dim Temp8 As Byte Dim Value16 As Word Dim Temp16 As Word Dim Temp16_2 As Word Dim Srcmac1 As Word Dim Srcmac2 As Word Dim Srcmac3 As Word Dim Srcip1 As Word Dim Srcip2 As Word Dim Frame_length As Word Dim Frame_type As Word Dim Ip_protocol As Byte Dim Ip_data_start As Word Dim Ip_data_length As Word Dim Ip_header_length As Word Dim Srcport As Word Dim Destport As Word Dim Rx_packet(759) As Word 'RX & TX Packet buffers. Dim Tx_packet(759) As Word '759 Words = 1518 bytes. Dim Byte_count As Word Dim Word_count As Word Dim Icmp_type As Word Dim Checksum As Long Dim Checksum16 As Word Dim Udp_port As Word Dim S As String * 1 Dim Ip1 As Byte Dim Ip2 As Byte Dim Ip3 As Byte Dim Ip4 As Byte Dim Individual_address_enable As Bit Dim Promiscuous_enable As Bit Dim Broadcast_enable As Bit Sub Starttx 'Command to start transmission after all bytes have been sent to the CS8900 TX/RX port Value16 = Tx_cmd_start_all Addr = Tx_command_port Value8 = Low(value16) Chipwrite Addr = Tx_command_port + 1 Value8 = High(value16) Chipwrite End Sub Sub Settxlen 'Set length of data to send Addr = Tx_length_port Value8 = Low(value16) Chipwrite Addr = Tx_length_port + 1 Value8 = High(value16) Chipwrite End Sub Sub Rxword 'Receive word from TX/RX data port into Value16 Addr = Rx_tx_data_port_0 Chipread Value16 = Value8 * 256 Addr = Rx_tx_data_port_0 + 1 Chipread Value16 = Value16 + Value8 End Sub Sub Txword 'Send word in Value16 to TX/RX data port Addr = Rx_tx_data_port_0 Value8 = High(value16) Chipwrite Addr = Rx_tx_data_port_0 + 1 Value8 = Low(value16) Chipwrite End Sub Sub Purge_frame 'Purges current received frame from CS8900 internal buffer Ppoffset = Pp_receiver_control 'Get RX status Ppread Value16 = Value16 Or Receiver_configuration_skip 'Set Skip_1_Frame bit Ppoffset = Pp_receiver_control 'Get RX status Ppwrite End Sub Sub Resetcs8900 'Reset the CS8900 Print "Resetting CS8900..." ; Ppoffset = Pp_self_control 'Send a soft-reset Ppread Value16 = Value16 Or Self_control_reset Ppwrite Wait_for_cs8900_reset: Ppoffset = Pp_self_control 'Get self control status Ppread Value16 = Value16 And &H40 'Mask bit 6 If Value16 = &H40 Then Goto Wait_for_cs8900_reset 'Is it clear? Ppoffset = Pp_self_status Ppread Value16 = Value16 And &H80 'Mask bit 7 If Value16 = 0 Then Goto Wait_for_cs8900_reset 'Is it set? Print " Complete." End Sub Sub Initcs8900 'Initialise the CS8900 Print "Initialising CS8900 parameters." Ppoffset = Pp_line_control 'Set 10BaseT interface Ppread Value16 = Value16 Or Line_control_10baset Ppwrite Ppoffset = Pp_test_control 'Set half-duplex operation Ppread Value16 = Value16 Or Test_control_half_duplex Ppwrite Ppoffset = Pp_receiver_control Ppread Value16 = Value16 Or Rx_ctl_rx_ok_a 'Enable reception of valid frames Print "Broadcast Reception - "; If Broadcast_enable = 1 Then Value16 = Value16 Or Rx_ctl_bcast_a 'Enable reception of broadcast packets Print "Enabled" Else Print "Disabled" End If Print "This MAC Address Reception - "; If Individual_address_enable = 1 Then Value16 = Value16 Or Rx_ctl_ind_addr 'Enable reception when Dest MAC = this MAC Print "Enabled" Else Print "Disabled" End If Print "Promiscuous Reception - "; If Promiscuous_enable = 1 Then Value16 = Value16 Or Rx_ctl_promiscuous 'Enable reception of frames for any destination Print "Enabled" Else Print "Disabled" End If Ppwrite 'Write the settings Ppoffset = Pp_individual_address 'Set first MAC word Value16 = Mac1 'Get first MAC word Swapvalue16 'reverse the bytes Ppwrite Ppoffset = Pp_individual_address + 2 'Set second MAC word Value16 = Mac2 'Get second MAC word Swapvalue16 Ppwrite Ppoffset = Pp_individual_address + 4 'Set third MAC word Value16 = Mac3 'Get third MAC word Swapvalue16 Ppwrite Ppoffset = Pp_line_control 'Get line control status Ppread Value16 = Value16 Or &B0000000001000000 'Serial RX on Value16 = Value16 Or &B0000000010000000 'Serial TX on Ppwrite 'Update line control status End Sub Sub Chipver 'Get CS8900 version 'Get EISA info Ppoffset = Pp_eisa_registration_number 'Point to EISA PPage address Ppread 'Get EISA info If Value16 = &H630E Then 'Check for Product ID code Print "CS8900 found, Great!" Else Print "*** CS8900 NOT found ***" Print "EISA data="; Printhex Value16 'Get product ID Ppoffset = Pp_product_identification_code Ppread Swapvalue16 Print "Product ID="; Printhex Value16 End If End Sub Sub Chipread '8-bit I/O Read from CS8900 'Result in Value8 Addr = Addr + Cs8900base Value8 = Inp(addr) End Sub Sub Chipwrite '8-bit I/O Write to CS8900 'Data in Value8 Addr = Addr + Cs8900base Out Addr , Value8 End Sub Sub Ppread 'PPread from CS8900 'PacketPage offset in PPoffset 'Low,High byte read order Setpppointer Value16 = 0 'Clear value Addr = Packet_page_data_port_0 'Locate PPdata LOW address Chipread 'Get low byte Value16 = Value8 'Store lower byte Addr = Packet_page_data_port_0 + 1 'Locate PPdata HIGH address Chipread 'Get high byte Temp16 = Value8 * 256 'Move to higher byte Value16 = Value16 + Temp16 'Add high byte to low byte End Sub Sub Ppwrite 'PPwrite to CS8900 'PacketPage offset in PPoffset 'Low,High byte write order Setpppointer Value8 = Low(value16) 'Get LOW byte to be written Addr = Packet_page_data_port_0 'Locate PPdata LOW address Chipwrite 'Write LOW byte to PP Value8 = High(value16) 'Get HIGH byte to be written Addr = Packet_page_data_port_0 + 1 'Locate PPdata HIGH address Chipwrite 'Write HIGH byte to PP End Sub Sub Setpppointer 'Set PP pointer Value8 = Low(ppoffset) 'Get LOW offset byte Addr = Packet_page_pointer_port 'Locate PPportPointer Chipwrite 'Write LOW byte to PPportPointer Value8 = High(ppoffset) 'Get HIGH offset byte Addr = Packet_page_pointer_port + 1 'Locate next PPpointerAddress Chipwrite 'Write HIGH byte to PPportPointer End Sub Sub Swapvalue16 'Swap high & low bytes in value16 Temp16 = Low(value16) 'Save high byte to low byte Temp8 = High(value16) 'Move & save high byte Value16 = Temp16 * 256 'Move low byte to high byte Value16 = Value16 + Temp8 'Add low byte End Sub Sub Linkstatus Ppoffset = Pp_line_status Ppread 'Get line status Value16 = Value16 And &B0000000010000000 'Mask LinkOK bit Print "Link "; If Value16 = 0 Then Print "DOWN" Else Print "UP" End If End Sub Sub Wait_for_frame 'Wait for valid frame to be received Wait_for_frame_1: Ppoffset = Pp_receiver_event Ppread Temp16 = Value16 Value16 = Value16 And Rx_event_receive_ok 'Mask Rx OK bit If Value16 = 0 Then Goto Wait_for_frame_1 'Is an 'OK' frame there? End Sub Sub Receive_frame 'Read RxStatus word. Read these high byte first! 'These will always be of zero value because of previous RX Event read operation resets them. Addr = Rx_tx_data_port_0 + 1 'Read RX status high byte Chipread Addr = Rx_tx_data_port_0 'Read RX status low byte Chipread 'Read frame length. Read these high byte first! Addr = Rx_tx_data_port_0 + 1 'Read frame length high byte Chipread Value16 = Value8 * 256 'And save it Addr = Rx_tx_data_port_0 'Read frame length low byte Chipread Value16 = Value16 + Value8 'And save it Frame_length = Value16 'Save length for later Byte_count = Frame_length Word_count = 0 'Loop back to here Receive_frame_1: Rxword 'Read in packet data as Words Rx_packet(word_count) = Value16 'Save word to array Incr Word_count 'update array counter Decr Byte_count 'Update counter Decr Byte_count 'Dual-byte (word) read If Byte_count > 1 Then Goto Receive_frame_1 'Get the next frame byte Rxword 'Get last word / byte Rx_packet(word_count) = Value16 'Save word to array End Sub Sub Arp_reply Value16 = Rx_packet(offset_ar_hwtype) If Value16 <> 1 Then Goto Arp_drop Value16 = Rx_packet(offset_ar_prtype) If Value16 <> &H0800 Then Goto Arp_drop 'IP ARP? Value16 = Rx_packet(offset_ar_hwlen_prlen) If Value16 <> &H0604 Then Goto Arp_drop Value16 = Rx_packet(offset_ar_op) If Value16 <> 1 Then Goto Arp_drop 'ARP Request? 'Build ARP frame to be sent Value16 = Rx_packet(offset_frame_src_mac_1) 'Frame Destination MAC Tx_packet(0) = Value16 Value16 = Rx_packet(offset_frame_src_mac_2) Tx_packet(1) = Value16 Value16 = Rx_packet(offset_frame_src_mac_3) Tx_packet(2) = Value16 Tx_packet(3) = Mac1 'Frame Source MAC Tx_packet(4) = Mac1 Tx_packet(5) = Mac1 Tx_packet(6) = &H0806 'Frame Type Tx_packet(7) = &H0001 'offset_Ar_hwtype Tx_packet(8) = &H0800 'offset_Ar_prtype Tx_packet(9) = &H0604 'ar_hwlen=6 ar_prlen=4 Tx_packet(10) = &H0002 'offset_Ar_op 2=ARP Reply Tx_packet(11) = Mac1 'ar_sha Tx_packet(12) = Mac2 Tx_packet(13) = Mac3 Value16 = Ip1 * 256 'ar_spa Value16 = Value16 + Ip2 Tx_packet(14) = Value16 Value16 = Ip3 * 256 Value16 = Value16 + Ip4 Tx_packet(15) = Value16 Value16 = Rx_packet(offset_ar_sha_1) 'ar_tha Tx_packet(16) = Value16 Value16 = Rx_packet(offset_ar_sha_2) Tx_packet(17) = Value16 Value16 = Rx_packet(offset_ar_sha_3) Tx_packet(18) = Value16 Value16 = Rx_packet(offset_ar_spa_1) 'ar_tpa Tx_packet(19) = Value16 Value16 = Rx_packet(offset_ar_spa_2) Tx_packet(20) = Value16 Value16 = 42 'Set packet length Transmit_frame 'Send packet Temp8 = 0 Goto Arp_reply_ok Arp_drop: Temp8 = 255 Arp_reply_ok: End Sub Sub Transmit_frame 'Sends frame from buffer, length in Value16 Temp16 = Value16 'Save packet length Starttx 'Send start TX command Value16 = Temp16 'Restore packet length Settxlen 'Wait for CS8900 to be ready for frame TX... 'May lock up in here due to lack of on-chip buffer space. 'Needs a timeout timer. Arp_wait_for_tx: Ppoffset = Pp_bus_status 'Get status Ppread Value16 = Value16 And Bus_status_rdy4txnow 'Mask bit 8 If Value16 = 0 Then Goto Arp_wait_for_tx Byte_count = Temp16 Word_count = 0 'Loop back to here Transmit_frame_1: Value16 = Tx_packet(word_count) 'Save word to array Txword Incr Word_count 'update array counter Decr Byte_count 'Update counter Decr Byte_count 'Dual-byte (word) read If Byte_count > 1 Then Goto Transmit_frame_1 'Get the next frame byte Value16 = Tx_packet(word_count) Txword End Sub Set_ip_address: 'Set IP address from data stored in ROM. Ip1 = Ip1c Ip2 = Ip2c Ip3 = Ip3c Ip4 = Ip4c Return ' ' ' ' ' '