; initial W5100 support
; at the lowest level 3 routines are required
; Initialise the W5100
; Write W5100 memory
; Read W5100 memory

; W5100 ised in indirect mode, accessed through 4 I/O ports
net_mode             EQU &A0
net_msb              EQU &A1             ;data sheet says use big-endian mode only, high byte is first
net_lsb              EQU &A2
net_data             EQU &A3

;mode bits for register 0
mode_reset           EQU %10000000
mode_pingBlock       EQU %00010000
mode_pppoeEnable     EQU %00001000
mode_increment       EQU %00000010
mode_indirect        EQU %00000001
;we need indirect and increment for the most part
mode_indInc          EQU %00000011

;Wiznet memory locations
; common registers
wiz_mode             EQU &0000
wiz_gateway          EQU &0001
wiz_subnet           EQU &0005
wiz_source_mac       EQU &0009
wiz_source_ip        EQU &000F
wiz_interrupt        EQU &0015
wiz_interrupt_mask   EQU &0016
wiz_retry_time       EQU &0017  
wiz_retry_count      EQU &0019
wiz_rx_memory        EQU &001A
wiz_tx_memory        EQU &001B
wiz_unreachable_ip   EQU &002A
wiz_unreachable_port EQU &002E

; socket registers for socket 0
socket_mode          EQU &0400
socket_command       EQU &0401
socket_interrupt     EQU &0402
socket_status        EQU &0403
socket_source_port   EQU &0404
socket_target_mac    EQU &0406
socket_target_ip     EQU &040C
socket_target_port   EQU &0410
socket_max_size      EQU 04012
socket_protocol_raw  EQU &0414
socket_tos           EQU &0415
socket_ttl           EQU &0416
socket_tx_free       EQU &0420
socket_tx_read       EQU &0422
socket_tx_write      EQU &0424
socket_rx_size       EQU &0426
socket_rx_read       EQU &0428


;initialise the card
;entry registers
;  - none
;exit registers
;  - A = 0 >> success
;    A <>0 >> failed would allow non net enabled expansions to report failure (with XOR A: DEC A: RET in place of the vector)

.do_net_init
ld a,mode_indInc      ;set indirect access mode with auto pointer increment
out (net_mode),A
ld HL,wiz_interrupt_mask
xor a
call net_write_byte   ;turn off all interrupts - INT isn't connected to the Z80
ld hl,wiz_rx_memory
ld a,%00000011        ;allocate all 8k of the receive buffer to socket 0
call net_write_byte
out (net_data),A      ;do the same transmit buffer
xor a                 ;signal success
ret              





;sent bytes to the W5100 memory
;Entry registers
; - HL source in MTX memory
;   DE destination in W5100 memory
;   BC byte count
;exit registers
; - HL first byte after the source data
;   DE unchanged
;   BC &0000
;   A = 0 >> success
;   a <>0 >> failure
.do_net_write
ld a,d
out (net_msb),a
ld a,e
out (net_lsb),a
.net_write_loop
ld a,(hl)
out (net_data),A
inc HL
dec BC
ld a,B
or C
jr nz,net_write_loop
;  xor A              ;not required, as set by the count check
ret


;sent bytes to the W5100 memory
;Entry registers
; - HL source in W5100 memory
;   DE destination in MTX memory
;   BC byte count
;exit registers
; - HL unchanged
;   DE first byte beyond end of destination buffer
;   BC &0000
;   A = 0 >> success
;   a <>0 >> failure
.do_net_read
ld a,h
out (net_msb),a
ld a,l
out (net_lsb),a
.net_read_loop
in a,(net_data)
ld (hl),A
inc HL
dec BC
ld a,B
or C
jr nz,net_read_loop
;  xor A           
ret

; set the wiznet memory pointer the HL, and write the A register
; address high gets written first
.net_write_byte
push bc
ld c,net_msb
out (c),h
inc c
out (c),l
inc c
out (c),a
pop bc
ret

; set the wiznet memory pointer the HL, and read into the A register
.net_read_byte
push bc
ld c,net_msb
out (c),h
inc c
out (c),l
inc c
in a,(c)
pop bc
ret

;mid level main routine enteres with A holding a routine number
;HL and DE are pointer addresses, BC or B for counter as required

.net_main
cp net_count
ret hs              ;exit if there is no such routine, will also be NZ A<>0

push HL             ;need HL do calculate the indirect jump
ld HL,net_jump      ;add the jump table start to
add a,a             ;2 x A
add a,l
ld l,a
ld a,0
adc a,h
ld h,A              ;HL now has the vector pointer
ld a,(hl)           ;retrieve the vector
inc HL
ld h,(hl)
ld L,A
ex (sp),HL          ;now get HL back, and put the computed address on the stack
ret                 ;and jump to it indirectly



net_count equ 3
.net_jump
DW net_set_mac
DW net_set_gateway
dw net_set_ip


.net_set_mac
ret

.net_set_gateway
ret

.net_set_ip
ret


;get rid of the skew table at FFA0 not used by CF area can be used by secondary
;net entry points, data etc
ORG &3fA0
.mac
DB &4D,&54,&58,&4D,&54,&58        ;6 byte MAC address for the card (MTXMTX)
.IP
EQUD 0               ;4 byte IP address for MTX
.gateway
EQUD 0               ;4 byte IP address of the router

org &3FB0
jp net_main

END