emailler/client/ip65/function_dispatcher.s

664 lines
12 KiB
ArmAsm
Raw Normal View History

;this is some very quick and dirty glue to make the most useful IP65 functions available via a single entry point.
;this allows user applications to be developed that don't link ip65 in directly, rather they use an instance of ip65 that is preloaded (or in a cartridge/ROM)
;this whole file could (and should) be greatly optimised by making it all table driven, but since this file is probably only going to be used in a bankswitched ROM where
;space is not at such a premium, I'll go with the gross hack for now.
.ifndef KPR_API_VERSION_NUMBER
.define EQU =
.include "../inc/kipper_constants.i"
.endif
.include "../inc/common.i"
.include "../inc/commonprint.i"
.export kipper_dispatcher
.import ip65_init
.import dhcp_init
.import cfg_get_configuration_ptr
.import tftp_load_address
.importzp tftp_filename
.import tftp_ip
.import ip65_error
.import tftp_clear_callbacks
.import tftp_download
.import tftp_upload
.import tftp_set_callback_vector
.import tftp_filesize
.import dns_ip
.import dns_resolve
.import dns_set_hostname
.import udp_callback
.import udp_add_listener
.import udp_remove_listener
.import ip_inp
.import udp_inp
.import udp_send
.import udp_send_src
.import udp_send_src_port
.import udp_send_dest
.import udp_send_dest_port
.import udp_send_len
.import copymem
.import cfg_mac
.import cfg_tftp_server
.importzp copy_src
.importzp copy_dest
;reuse the copy_src zero page location
kipper_params = copy_src
buffer_ptr= copy_dest
.data
ip_configured_flag:
.byte 0
.code
set_tftp_params:
ldx #$03
:
lda cfg_tftp_server,x
sta tftp_ip,x
dex
bpl :-
ldy #KPR_TFTP_FILENAME
lda (kipper_params),y
sta tftp_filename
iny
lda (kipper_params),y
sta tftp_filename+1
ldy #KPR_TFTP_POINTER
lda (kipper_params),y
sta tftp_load_address
iny
lda (kipper_params),y
sta tftp_load_address+1
jsr tftp_clear_callbacks
rts
set_tftp_callback_vector:
ldy #KPR_TFTP_POINTER+1
lda (kipper_params),y
tax
dey
lda (kipper_params),y
jmp tftp_set_callback_vector
kipper_dispatcher:
stax kipper_params
cpy #KPR_INITIALIZE
bne :+
lda ip_configured_flag
bne ip_configured
jsr ip65_init
bcs init_failed
jsr dhcp_init
bcc dhcp_ok
jsr ip65_init ;if DHCP failed, then reinit the IP stack (which will reset IP address etc that DHCP messed with to cartridge default values)
dhcp_ok:
lda #1
sta ip_configured_flag
clc
init_failed:
rts
ip_configured:
clc
rts
:
cpy #KPR_GET_IP_CONFIG
bne :+
ldax #cfg_mac
clc
rts
:
cpy #KPR_DNS_RESOLVE
bne :+
phax
ldy #KPR_DNS_HOSTNAME+1
lda (kipper_params),y
tax
dey
lda (kipper_params),y
jsr dns_set_hostname
bcs @dns_error
jsr dns_resolve
bcs @dns_error
ldy #KPR_DNS_HOSTNAME_IP
plax
stax kipper_params
ldx #4
@copy_dns_ip:
lda dns_ip,y
sta (kipper_params),y
iny
dex
bne @copy_dns_ip
rts
@dns_error:
plax
rts
:
cpy #KPR_UDP_ADD_LISTENER
bne :+
ldy #KPR_UDP_LISTENER_CALLBACK
lda (kipper_params),y
sta udp_callback
iny
lda (kipper_params),y
sta udp_callback+1
ldy #KPR_UDP_LISTENER_PORT+1
lda (kipper_params),y
tax
dey
lda (kipper_params),y
jmp udp_add_listener
:
cpy #KPR_GET_INPUT_PACKET_INFO
bne :+
ldy #3
@copy_src_ip:
lda ip_inp+12,y ;src IP
sta (kipper_params),y
dey
bpl @copy_src_ip
ldy #KPR_REMOTE_PORT
lda udp_inp+1 ;src port (lo byte)
sta (kipper_params),y
iny
lda udp_inp+0 ;src port (high byte)
sta (kipper_params),y
iny
lda udp_inp+3 ;dest port (lo byte)
sta (kipper_params),y
iny
lda udp_inp+2 ;dest port (high byte)
sta (kipper_params),y
iny
sec
lda udp_inp+5 ;payload length (lo byte)
sbc #8 ;to remove length of header
sta (kipper_params),y
iny
lda udp_inp+4 ;payload length (hi byte)
sbc #0 ;in case there was a carry from the lo byte
sta (kipper_params),y
iny
lda #<(udp_inp+8) ;payload ptr (lo byte)
sta (kipper_params),y
iny
lda #>(udp_inp+8) ;payload ptr (hi byte)
sta (kipper_params),y
.import tcp_inbound_data_ptr
.import tcp_inbound_data_length
lda ip_inp+9 ;proto number
cmp #6 ;TCP
bne @not_tcp
ldy #KPR_PAYLOAD_LENGTH
lda tcp_inbound_data_length
sta (kipper_params),y
iny
lda tcp_inbound_data_length+1
sta (kipper_params),y
ldy #KPR_PAYLOAD_POINTER
lda tcp_inbound_data_ptr
sta (kipper_params),y
iny
lda tcp_inbound_data_ptr+1
sta (kipper_params),y
@not_tcp:
clc
rts
:
cpy #KPR_SEND_UDP_PACKET
bne :+
ldy #3
@copy_dest_ip:
lda (kipper_params),y
sta udp_send_dest,y
dey
bpl @copy_dest_ip
ldy #KPR_REMOTE_PORT
lda (kipper_params),y
sta udp_send_dest_port
iny
lda (kipper_params),y
sta udp_send_dest_port+1
iny
lda (kipper_params),y
sta udp_send_src_port
iny
lda (kipper_params),y
sta udp_send_src_port+1
iny
lda (kipper_params),y
sta udp_send_len
iny
lda (kipper_params),y
sta udp_send_len+1
iny
;AX should point at data to send
lda (kipper_params),y
pha
iny
lda (kipper_params),y
tax
pla
jmp udp_send
:
cpy #KPR_UDP_REMOVE_LISTENER
bne :+
jmp udp_remove_listener
:
cpy #KPR_DEACTIVATE
;nothing to do now we don't use IRQ
bne :+
clc
rts
:
cpy #KPR_TFTP_SET_SERVER
bne :+
ldy #3
@copy_tftp_server_ip:
lda (kipper_params),y
sta cfg_tftp_server,y
dey
bpl @copy_tftp_server_ip
clc
rts
:
cpy #KPR_TFTP_DOWNLOAD
bne :+
phax
jsr set_tftp_params
jsr tftp_download
@after_tftp_call: ;write the current load address back to the param buffer (so if $0000 was passed in, the caller can find out the actual value used)
plax
bcs @tftp_error
stax kipper_params
ldy #KPR_TFTP_POINTER
lda tftp_load_address
sta (kipper_params),y
iny
lda tftp_load_address+1
sta (kipper_params),y
ldy #KPR_TFTP_FILESIZE
lda tftp_filesize
sta (kipper_params),y
iny
lda tftp_filesize+1
sta (kipper_params),y
clc
@tftp_error:
rts
:
cpy #KPR_TFTP_CALLBACK_DOWNLOAD
bne :+
phax
jsr set_tftp_params
jsr set_tftp_callback_vector
jsr tftp_download
jmp @after_tftp_call
:
cpy #KPR_TFTP_UPLOAD
bne :+
phax
jsr set_tftp_params
ldy #KPR_TFTP_POINTER
lda (kipper_params),y
sta tftp_filesize
iny
lda (kipper_params),y
sta tftp_filesize+1
jsr tftp_download
jmp @after_tftp_call
:
cpy #KPR_TFTP_CALLBACK_UPLOAD
bne :+
jsr set_tftp_params
jsr set_tftp_callback_vector
jmp tftp_upload
:
cpy #KPR_PRINT_ASCIIZ
bne :+
jsr print
clc
rts
:
cpy #KPR_PRINT_HEX
bne :+
jsr print_hex
clc
rts
:
cpy #KPR_PRINT_DOTTED_QUAD
bne :+
jsr print_dotted_quad
clc
rts
:
cpy #KPR_PRINT_IP_CONFIG
bne :+
jsr print_ip_config
clc
rts
:
cpy #KPR_PRINT_INTEGER
bne :+
jsr print_integer
clc
rts
:
.segment "TCP_VARS"
port_number: .res 2
nonzero_octets: .res 1
.code
cpy #KPR_DOWNLOAD_RESOURCE
bne :+
.import url_download
.import url_download_buffer
.import url_download_buffer_length
ldy #KPR_URL_DOWNLOAD_BUFFER
lda (kipper_params),y
sta url_download_buffer
iny
lda (kipper_params),y
sta url_download_buffer+1
ldy #KPR_URL_DOWNLOAD_BUFFER_LENGTH
lda (kipper_params),y
sta url_download_buffer_length
iny
lda (kipper_params),y
sta url_download_buffer_length+1
ldy #KPR_URL+1
lda (kipper_params),y
tax
dey
lda (kipper_params),y
jmp url_download
:
cpy #KPR_FILE_LOAD
bne :+
.import io_device_no
.import io_read_file
.import io_filename
.import io_filesize
.import io_load_address
phax
ldy #KPR_FILE_ACCESS_FILENAME
lda (kipper_params),y
sta io_filename
iny
lda (kipper_params),y
sta io_filename+1
ldy #KPR_FILE_ACCESS_DEVICE
lda (kipper_params),y
sta io_device_no
ldy #KPR_FILE_ACCESS_POINTER+1
lda (kipper_params),y
tax
dey
lda (kipper_params),y
jsr io_read_file
plax
bcc @read_file_ok
rts
@read_file_ok:
stax kipper_params
ldy #KPR_FILE_ACCESS_POINTER
lda io_load_address
sta (kipper_params),y
iny
lda io_load_address+1
sta (kipper_params),y
ldy #KPR_FILE_ACCESS_FILESIZE
lda io_filesize
sta (kipper_params),y
iny
lda io_filesize+1
sta (kipper_params),y
rts
:
cpy #KPR_PING_HOST
.import icmp_echo_ip
.import icmp_ping
bne :+
ldy #3
@copy_ping_ip_loop:
lda (kipper_params),y
sta icmp_echo_ip,y
dey
bpl @copy_ping_ip_loop
jmp icmp_ping
:
cpy #KPR_TCP_CONNECT
bne :+
.import tcp_connect
.import tcp_callback
.import tcp_connect_ip
.import tcp_listen
ldy #3
lda #0
sta nonzero_octets
@copy_dest_ip:
lda (kipper_params),y
beq @octet_was_zero
inc nonzero_octets
@octet_was_zero:
sta tcp_connect_ip,y
dey
bpl @copy_dest_ip
ldy #KPR_TCP_CALLBACK
lda (kipper_params),y
sta tcp_callback
iny
lda (kipper_params),y
sta tcp_callback+1
ldy #KPR_TCP_PORT+1
lda (kipper_params),y
tax
dey
lda (kipper_params),y
ldy nonzero_octets
bne @outbound_tcp_connection
jmp tcp_listen
@outbound_tcp_connection:
jmp tcp_connect
:
.import tcp_send
.import tcp_send_data_len
cpy #KPR_SEND_TCP_PACKET
bne :+
ldy #KPR_TCP_PAYLOAD_LENGTH
lda (kipper_params),y
sta tcp_send_data_len
iny
lda (kipper_params),y
sta tcp_send_data_len+1
ldy #KPR_TCP_PAYLOAD_POINTER+1
lda (kipper_params),y
tax
dey
lda (kipper_params),y
jmp tcp_send
:
.import tcp_close
cpy #KPR_TCP_CLOSE_CONNECTION
bne :+
jmp tcp_close
:
.import filter_dns
.import get_filtered_input
.import filter_number
cpy #KPR_INPUT_STRING
bne :+
ldy #40 ;max chars
ldax #$0000
jmp get_filtered_input
:
cpy #KPR_INPUT_HOSTNAME
bne :+
ldy #40 ;max chars
ldax #filter_dns
jmp get_filtered_input
:
cpy #KPR_INPUT_PORT_NUMBER
bne :+
ldy #5 ;max chars
ldax #filter_number
jsr get_filtered_input
bcs @no_port_entered
;AX now points a string containing port number
.import parse_integer
jmp parse_integer
@no_port_entered:
rts
:
cpy #KPR_BLOCK_COPY
bne :+
;this is where we pay the price for trying to save a few 'zero page' pointers
;by reusing the 'copy_src' and 'copy_dest' addresses!
.segment "TCP_VARS"
tmp_copy_src: .res 2
tmp_copy_dest: .res 2
tmp_copy_length: .res 2
.code
ldy #KPR_BLOCK_SRC
lda (kipper_params),y
sta tmp_copy_src
iny
lda (kipper_params),y
sta tmp_copy_src+1
ldy #KPR_BLOCK_DEST
lda (kipper_params),y
sta tmp_copy_dest
iny
lda (kipper_params),y
sta tmp_copy_dest+1
ldy #KPR_BLOCK_SIZE
lda (kipper_params),y
sta tmp_copy_length
iny
lda (kipper_params),y
sta tmp_copy_length+1
ldax tmp_copy_src
stax copy_src
ldax tmp_copy_dest
stax copy_dest
ldax tmp_copy_length
jmp copymem
:
cpy #KPR_PARSER_INIT
bne :+
.import parser_init
jmp parser_init
:
cpy #KPR_PARSER_SKIP_NEXT
bne :+
.import parser_skip_next
jmp parser_skip_next
:
cpy #KPR_GET_LAST_ERROR
bne :+
lda ip65_error
clc
rts
:
;default function handler
lda #KPR_ERROR_FUNCTION_NOT_SUPPORTED
sta ip65_error
sec ;carry flag set = error
rts