From 37c20faa6f989ae42a04687c24c0f6302bd4bbbe Mon Sep 17 00:00:00 2001 From: jonnosan Date: Sat, 28 Mar 2009 12:57:24 +0000 Subject: [PATCH] nb65 API now mostly working for dhcp+tftp git-svn-id: http://svn.code.sf.net/p/netboot65/code@70 93682198-c243-4bdb-bd91-e943c89aac3b --- client/clients/rrnetboot.s | 126 +++++++++++++++++------------- client/inc/commonprint.i | 15 ---- client/inc/nb65_constants.i | 40 ++++++++-- client/ip65/config.s | 6 +- client/ip65/function_dispatcher.s | 96 ++++++++++++++++++++++- client/ip65/tftp.s | 28 ++++++- 6 files changed, 226 insertions(+), 85 deletions(-) diff --git a/client/clients/rrnetboot.s b/client/clients/rrnetboot.s index 25c7d5f..1104085 100644 --- a/client/clients/rrnetboot.s +++ b/client/clients/rrnetboot.s @@ -17,7 +17,7 @@ NB65_VBL_VECTOR =$8013 .include "../inc/common.i" .include "../inc/commonprint.i" .include "../inc/menu.i" - .include "../inc/net.i" +; .include "../inc/net.i" .include "../inc/c64keycodes.i" .import cls @@ -25,15 +25,15 @@ NB65_VBL_VECTOR =$8013 .import beep .import exit_to_basic .import timer_vbl_handler - .import ip65_dispatcher + .import nb65_dispatcher .import ip65_process - .importzp tftp_filename - .import tftp_load_address - .import tftp_ip - .import tftp_download - .import tftp_directory_listing - .import tftp_set_download_callback +; .importzp tftp_filename +; .import tftp_load_address +; .import tftp_ip +; .import tftp_download +; .import tftp_directory_listing +; .import tftp_set_download_callback .import copymem .importzp copy_src @@ -45,7 +45,7 @@ NB65_VBL_VECTOR =$8013 .bss -ip65_param_buffer: .res $10 +nb65_param_buffer: .res $10 bin_file_jmp: .res 3 tftp_dir_buffer: .res 2000 @@ -57,7 +57,7 @@ tftp_dir_buffer: .res 2000 .word init ;warm start vector .byte $C3,$C2,$CD,$38,$30 ; "CBM80" .byte "NB65" ;netboot 65 signature -jmp ip65_dispatcher ; NB65_DISPATCH_VECTOR : entry point for IP65 functions +jmp nb65_dispatcher ; NB65_DISPATCH_VECTOR : entry point for NB65 functions jmp ip65_process ;NB65_PERIODIC_PROCESSING_VECTOR : routine to be periodically called to check for arrival of ethernet packects jmp timer_vbl_handler ;NB65_VBL_VECTOR : routine to be called during each vertical blank interrupt @@ -139,8 +139,9 @@ init: ldy #NB65_INIT_IP jsr NB65_DISPATCH_VECTOR - bcc :+ + bcc :+ print_failed + jsr print_errorcode jmp bad_boot : @@ -152,77 +153,64 @@ init: jsr NB65_DISPATCH_VECTOR bcc :+ print_failed + jsr print_errorcode jmp bad_boot : print_ok jsr print_ip_config - ldx #3 -: - lda cfg_tftp_server,x - sta tftp_ip,x - dex - bpl :- - ldax #press_a_key_to_continue jsr print jsr get_key - + jsr setup_param_buffer_for_tftp_call + ldax #tftp_dir_buffer - stax tftp_load_address + stax nb65_param_buffer+NB65_TFTP_POINTER ldax #getting_dir_listing_msg jsr print ldax #tftp_dir_filemask - stax tftp_filename + stax nb65_param_buffer+NB65_TFTP_FILENAME + jsr print jsr print_cr - jsr tftp_directory_listing + ldax #nb65_param_buffer + ldy #NB65_TFTP_DIRECTORY_LISTING + jsr NB65_DISPATCH_VECTOR + bcs @dir_failed lda tftp_dir_buffer ;get the first byte that was downloaded bne :+ jmp @no_files_on_server : - ldax #$0000 ;load address will be first 2 bytes of file we dowload (LO/HI order) - stax tftp_load_address ;switch to lower case charset lda #23 sta $d018 + + ldax #tftp_dir_buffer jsr select_option_from_menu - stax tftp_filename - - ldax #downloading_msg - jsr print - - - ldax tftp_filename +@tftp_filename_set: jsr download bcc @file_downloaded_ok + jmp bad_boot @dir_failed: ldax #tftp_dir_listing_fail_msg jsr print + jsr print_errorcode + jsr print_cr - ldax #$0000 ;load address will be first 2 bytes of file we download (LO/HI order) - stax tftp_load_address - - ldax #downloading_msg - jsr print - ldax #tftp_file - jsr download - - bcc @file_downloaded_ok - jmp bad_boot + jmp @tftp_filename_set @no_files_on_server: ldax #no_files_on_server @@ -233,11 +221,11 @@ init: @file_downloaded_ok: jsr remove_irq_handler - ;check whether the file we just downloaded was a BASIC prg - lda tftp_load_address + ;check whether the file we just downloaded was a BASIC prg + lda nb65_param_buffer+NB65_TFTP_POINTER cmp #01 bne @not_a_basic_file - lda tftp_load_address+1 + lda nb65_param_buffer+NB65_TFTP_POINTER+1 cmp #$08 bne @not_a_basic_file @@ -255,11 +243,30 @@ init: @not_a_basic_file: lda #$4C ;opcode for JMP sta bin_file_jmp - ldax tftp_load_address + ldax nb65_param_buffer+NB65_TFTP_POINTER stax bin_file_jmp+1 - jsr bin_file_jmp - rts + jmp bin_file_jmp +print_errorcode: + ldax #error_code + jsr print + ldy #NB65_GET_LAST_ERROR + jsr NB65_DISPATCH_VECTOR + jsr print_hex + jmp print_cr + + +setup_param_buffer_for_tftp_call: + lda #$00 ;'normal' tftp call mode, i.e. TFTP_POINTER is where data should be written to + sta nb65_param_buffer+NB65_TFTP_CALL_MODE + + ldx #3 + lda #$ff ;255.255.255.255 = broadcast address +: + sta nb65_param_buffer+NB65_TFTP_IP,x + dex + bpl :- + rts bad_boot: ldax #press_a_key_to_continue @@ -268,16 +275,26 @@ bad_boot: jsr remove_irq_handler jmp $fe66 ;do a wam start -download: - stax tftp_filename - jsr print - jsr print_cr +download: ;AX should point at filename to download + stax nb65_param_buffer+NB65_TFTP_FILENAME + ldax #$0000 ;load address will be first 2 bytes of file we download (LO/HI order) + stax nb65_param_buffer+NB65_TFTP_POINTER - jsr tftp_download + ldax #downloading_msg + jsr print + ldax nb65_param_buffer+NB65_TFTP_FILENAME + jsr print + jsr print_cr + + jsr setup_param_buffer_for_tftp_call + ldy #NB65_TFTP_DOWNLOAD + ldax #nb65_param_buffer + jsr NB65_DISPATCH_VECTOR bcc :+ - ldax #tftp_download_fail_msg + ldax #tftp_download_fail_msg jsr print + jsr print_errorcode sec rts @@ -307,6 +324,9 @@ tftp_download_fail_msg: tftp_download_ok_msg: .byte "DOWNLOAD OK", 13, 0 +error_code: + .asciiz "ERROR CODE: " + tftp_dir_filemask: .asciiz "*.PRG" diff --git a/client/inc/commonprint.i b/client/inc/commonprint.i index 631f4c6..bf48ba8 100644 --- a/client/inc/commonprint.i +++ b/client/inc/commonprint.i @@ -1,6 +1,4 @@ -.ifndef NB65_API_VERSION .include "../inc/nb65_constants.i" -.endif .zeropage pptr: .res 2 @@ -95,16 +93,6 @@ print_ip_config: jsr print_dotted_quad jsr print_cr - ldax #tftp_server_msg - jsr print - jsr cfg_get_configuration_ptr ;ax=base config, carry flag clear - adc #NB65_CFG_TFTP_SERVER - bcc :+ - inx -: - jsr print_dotted_quad - jsr print_cr - rts print: @@ -242,9 +230,6 @@ dns_server_msg: dhcp_server_msg: .byte "DHCP SERVER:", 0 -tftp_server_msg: - .byte "TFTP SERVER: ", 0 - dhcp_msg: .byte "DHCP",0 diff --git a/client/inc/nb65_constants.i b/client/inc/nb65_constants.i index 49f57a8..762b8f8 100644 --- a/client/inc/nb65_constants.i +++ b/client/inc/nb65_constants.i @@ -1,3 +1,4 @@ +.ifndef NB65_API_VERSION NB65_API_VERSION=$0001 @@ -7,11 +8,36 @@ NB65_CFG_IP = NB65_CFG_MAC+$06 ;4 byte local IP address (will b NB65_CFG_NETMASK = NB65_CFG_IP+$04 ;4 byte local netmask (will be overwritten by DHCP) NB65_CFG_GATEWAY = NB65_CFG_NETMASK+$04 ;4 byte local gateway (will be overwritten by DHCP) NB65_CFG_DNS_SERVER = NB65_CFG_GATEWAY+$04 ;4 byte IP address of DNS server (will be overwritten by DHCP) -NB65_CFG_TFTP_SERVER = NB65_CFG_DNS_SERVER+$04 ;4 byte IP address of TFTP server (can be broadcast address e.g. 255.255.255.255) -NB65_CFG_DHCP_SERVER = NB65_CFG_TFTP_SERVER+$04 ;4 byte IP address of DHCP server (will only be set by DHCP initialisation) +NB65_CFG_DHCP_SERVER = NB65_CFG_DNS_SERVER+$04 ;4 byte IP address of DHCP server (will only be set by DHCP initialisation) -NB65_GET_API_VERSION =0 ;no inputs, outputs X=major version number, A=minor version number -NB65_GET_DRIVER_NAME =1 ;no inputs, AX=pointer to asciiz driver name -NB65_GET_IP_CONFIG_PTR =2 ;no inputs, AX=pointer to IP configuration structure (which can be modified) -NB65_INIT_IP =3 ;no inputs or outputs -NB65_INIT_DHCP =4 ;no inputs or outputs +;offsets in TFTP paramater structure +NB65_TFTP_CALL_MODE = $00 ;1 byte for 'mode' : $00 means read/write from RAM, (and TFTP_POINTER is address to read from + ; or write to), any other value means use callbacks (and TFTP_POINTER is the address of a routine + ;to be called whenever data arrives, or needs to be sent) +NB65_TFTP_IP = $01 ;4 byte IP address of TFTP server +NB65_TFTP_FILENAME = $05 ;2 byte pointer to asciiz filename (or filemask in case of NB65_TFTP_DIRECTORY_LISTING) +NB65_TFTP_POINTER = $07 ;2 byte pointer to memory location data to be stored in OR address of tftp callback + + +;function numbers +NB65_GET_API_VERSION =$00 ;no inputs, outputs X=major version number, A=minor version number +NB65_GET_DRIVER_NAME =$01 ;no inputs, outputs AX=pointer to asciiz driver name +NB65_GET_IP_CONFIG_PTR =$02 ;no inputs, outputs AX=pointer to IP configuration structure (which can be modified) +NB65_INIT_IP =$03 ;no inputs or outputs +NB65_INIT_DHCP =$04 ;no inputs or outputs (NB65_INIT_IP should be called first, and NB65_VBL_VECTOR should be called @ 60hz) +NB65_TFTP_DIRECTORY_LISTING =$05 ;inputs: AX points to a TFTP paramater structure, outputs: none +NB65_TFTP_DOWNLOAD =$06 ;inputs: AX points to a TFTP paramater structure, outputs: TFTP param structure updated with + ;NB65_TFTP_POINTER updated to reflect actual load address (if load address $0000 originally passed in) + +NB65_GET_LAST_ERROR =$FF ;no inputs, outputs A = error code (from last function that set the global error value, not necessarily the + ;last function that was called) + +;error codes (as returned by NB65_GET_LAST_ERROR) +NB65_ERROR_PORT_IN_USE = $80 +NB65_ERROR_TIMEOUT_ON_RECEIVE = $81 +NB65_ERROR_TRANSMIT_FAILED = $82 +NB65_ERROR_TRANSMISSION_REJECTED_BY_PEER = $83 +NB65_ERROR_OPTION_NOT_SUPPORTED = $FE +NB65_ERROR_FUNCTION_NOT_SUPPORTED = $FF + +.endif \ No newline at end of file diff --git a/client/ip65/config.s b/client/ip65/config.s index 14edefb..309bb3e 100644 --- a/client/ip65/config.s +++ b/client/ip65/config.s @@ -34,6 +34,6 @@ cfg_mac: .byte $00, $80, $10, $6d, $76, $30 ;mac address to be assigned to loca cfg_ip: .byte 0,0,0,0 ;ip address of local machine (will be overwritten if dhcp_init is called) cfg_netmask: .byte 255, 255, 255, 0; netmask of local network (will be overwritten if dhcp_init is called) cfg_gateway: .byte 0, 0, 0, 0 ;ip address of router on local network (will be overwritten if dhcp_init is called) -cfg_dns: .byte 0, 0, 0, 0; ip address of dns server to use (will be overwritten if dhcp_init is called) -cfg_tftp_server: .byte $ff,$ff,$ff,$ff ; ip address of server to send tftp requests to (can be a broadcast address) -dhcp_server: .res 4 ;will be set address of dhcp server that configuration was obtained from \ No newline at end of file +cfg_dns: .byte 0, 0, 0, 0; ip address of dns server to use (will be overwritten if dhcp_init is called) +dhcp_server: .res 4 ;will be set address of dhcp server that configuration was obtained from +cfg_tftp_server: .byte $ff,$ff,$ff,$ff ; ip address of server to send tftp requests to (can be a broadcast address) \ No newline at end of file diff --git a/client/ip65/function_dispatcher.s b/client/ip65/function_dispatcher.s index dee5a01..00428c9 100644 --- a/client/ip65/function_dispatcher.s +++ b/client/ip65/function_dispatcher.s @@ -2,16 +2,71 @@ .include "../inc/nb65_constants.i" .include "../inc/common.i" +.export nb65_dispatcher + .import ip65_init .import dhcp_init .import cs_driver_name .import cfg_get_configuration_ptr -.export ip65_dispatcher +.import tftp_load_address +.importzp tftp_filename +.import tftp_ip +.import tftp_directory_listing +.import ip65_error +.import tftp_clear_callbacks +.import tftp_download +.zeropage +nb65_params: .res 2 .code -ip65_dispatcher: + +set_tftp_params: + stax nb65_params + ldy #NB65_TFTP_IP + lda (nb65_params),y + sta tftp_ip + iny + lda (nb65_params),y + sta tftp_ip+1 + iny + lda (nb65_params),y + sta tftp_ip+2 + iny + lda (nb65_params),y + sta tftp_ip+3 + + ldy #NB65_TFTP_FILENAME + lda (nb65_params),y + sta tftp_filename + iny + lda (nb65_params),y + sta tftp_filename+1 + + ldy #NB65_TFTP_CALL_MODE + lda (nb65_params),y + + bne @callback_mode + ;direct mode + ldy #NB65_TFTP_POINTER + lda (nb65_params),y + sta tftp_load_address + iny + lda (nb65_params),y + sta tftp_load_address+1 + + jsr tftp_clear_callbacks + + clc + rts +@callback_mode: ;FIXME: callback mode not supported yet + lda #NB65_ERROR_OPTION_NOT_SUPPORTED + sta ip65_error + sec + rts + +nb65_dispatcher: cpy #NB65_GET_API_VERSION bne :+ @@ -42,7 +97,42 @@ ip65_dispatcher: jmp dhcp_init : + cpy #NB65_TFTP_DIRECTORY_LISTING + bne :+ + jsr set_tftp_params + bcs @tftp_error + jsr tftp_directory_listing + +@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) + bcs @tftp_error + ldy #NB65_TFTP_POINTER + lda tftp_load_address + sta (nb65_params),y + iny + lda tftp_load_address+1 + sta (nb65_params),y + clc +@tftp_error: + rts +: + + cpy #NB65_TFTP_DOWNLOAD + bne :+ + jsr set_tftp_params + bcs @tftp_error + jsr tftp_download + jmp @after_tftp_call +: + + cpy #NB65_GET_LAST_ERROR + bne :+ + lda ip65_error + clc + rts +: + ;default function handler - lda #$ff ;function undefined + lda #NB65_ERROR_FUNCTION_NOT_SUPPORTED + sta ip65_error sec ;carry flag set = error rts \ No newline at end of file diff --git a/client/ip65/tftp.s b/client/ip65/tftp.s index f6434c1..5089d01 100644 --- a/client/ip65/tftp.s +++ b/client/ip65/tftp.s @@ -1,11 +1,14 @@ ;minimal tftp implementation (client only) ;supports file download (not upload) and custom directory listing (using non-standard tftp opcode of 0x65) + TFTP_MAX_RESENDS=10 TFTP_TIMER_MASK=$F8 ;mask lower two bits, means we wait for 8 x1/4 seconds .include "../inc/common.i" - + .include "../inc/nb65_constants.i" + + .exportzp tftp_filename .export tftp_load_address .export tftp_ip @@ -14,9 +17,11 @@ .export tftp_data_block_length .export tftp_set_download_callback .export tftp_data_block_length + .export tftp_clear_callbacks .import ip65_process - + .import ip65_error + .import udp_add_listener .import udp_remove_listener @@ -140,6 +145,8 @@ set_tftp_opcode: jsr udp_add_listener bcc :+ ;bail if we couldn't listen on the port we want + lda #NB65_ERROR_PORT_IN_USE + sta ip65_error rts : @@ -200,6 +207,8 @@ set_tftp_opcode: dec tftp_resend_counter bne @outer_delay_loop + lda #NB65_ERROR_TIMEOUT_ON_RECEIVE + sta ip65_error jmp @exit_with_error send_request_packet: @@ -250,7 +259,8 @@ send_request_packet: sta tftp_state rts @error_in_send: - + lda #NB65_ERROR_TRANSMIT_FAILED + sta ip65_error sec rts @@ -289,7 +299,9 @@ tftp_in: bne @not_an_error @recv_error: lda #tftp_error - sta tftp_state + sta tftp_state + lda #NB65_ERROR_TRANSMISSION_REJECTED_BY_PEER + sta ip65_error rts @not_an_error: @@ -415,7 +427,15 @@ copy_tftp_block_to_ram: ; outputs: none tftp_set_download_callback: stax tftp_download_callback+1 + rts +;clear callback vectors, i.e. all future transfers read from/write to RAM +;inputs: none +;outputs: none +tftp_clear_callbacks: + ldax #copy_tftp_block_to_ram + jmp tftp_set_download_callback + .rodata tftp_octet_mode: .asciiz "OCTET"