Subversion Repositories Spectranet

[/] [branches/] [gnubinutils/] [rom/] [w5100_rxtx.asm] - Diff between revs 371 and 384

Show entire file | Details | Blame | View Log

Rev 371 Rev 384
Line 18... Line 18...
;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
;THE SOFTWARE.
;THE SOFTWARE.
;
;
 
.include        "w5100_defs.inc"
 
.include        "sysvars.inc"
 
.include        "sockdefs.inc"
 
 
;
;
; send/sendto and recv/recvfrom send data to a socket and get data
; send/sendto and recv/recvfrom send data to a socket and get data
; from it.
; from it.
;
;
; F_send:
; F_send:
Line 29... Line 33...
; Parameters: A  = file descriptor to send data to
; Parameters: A  = file descriptor to send data to
;             DE = source buffer to copy to hardware
;             DE = source buffer to copy to hardware
;             BC = size of source buffer
;             BC = size of source buffer
; On return,  BC = number of bytes sent
; On return,  BC = number of bytes sent
; Carry flag is set on error and A contains error code.
; Carry flag is set on error and A contains error code.
F_send
.text
 
.globl F_send
 
F_send:
        call F_gethwsock        ; H is socket reg. MSB address
        call F_gethwsock        ; H is socket reg. MSB address
        jp c, J_leavesockfn     ; error finding socket if carry set
        jp c, J_leavesockfn     ; error finding socket if carry set
        ld a, b                 ; MSB of send buffer size
        ld a, b                 ; MSB of send buffer size
        cp 0x08                 ; greater than 2K if compare result is pos.
        cp 0x08                 ; greater than 2K if compare result is pos.
        jp p, .multisend        ; TODO: send buffers >2k
        jp p, .multisend1       ; TODO: send buffers >2k
        call F_copytxbuf
        call F_copytxbuf
        jp J_leavesockfn
        jp J_leavesockfn
.multisend                      ; see TODO above!
.multisend1:                    ; see TODO above!
        ld bc, 0x7FF            ; send as much as possible for now.
        ld bc, 0x7FF            ; send as much as possible for now.
        call F_copytxbuf
        call F_copytxbuf
        jp J_leavesockfn
        jp J_leavesockfn
 
 
; F_recv:
; F_recv:
Line 50... Line 56...
; this to happen.
; this to happen.
;
;
; Parameters : A  = file descriptor
; Parameters : A  = file descriptor
;              DE = address of memory to fill with data
;              DE = address of memory to fill with data
;              BC = number of bytes to get
;              BC = number of bytes to get
F_recv
.globl F_recv
 
F_recv:
        call F_gethwsock        ; H is socket reg MSB
        call F_gethwsock        ; H is socket reg MSB
        jp c, J_leavesockfn     ; carry is set if the fd is not valid
        jp c, J_leavesockfn     ; carry is set if the fd is not valid
        ld l, Sn_IR % 256       ; get the interrupt register
        ld l, Sn_IR % 256       ; get the interrupt register
 
 
.waitforrecv
.waitforrecv2:
        ld a, (hl)
        ld a, (hl)
        bit BIT_IR_RECV, a      ; see if the recv bit is set
        bit BIT_IR_RECV, a      ; see if the recv bit is set
        jr nz, .rxdata          ; Data is ready
        jr nz, .rxdata2         ; Data is ready
        bit BIT_IR_DISCON, a    ; check for RST condition
        bit BIT_IR_DISCON, a    ; check for RST condition
        jr z, .waitforrecv      ; no, so keep waiting
        jr z, .waitforrecv2     ; no, so keep waiting
        ld a, ECONNRESET        ; connection reset by peer
        ld a, ECONNRESET        ; connection reset by peer
        scf
        scf
        jp J_leavesockfn
        jp J_leavesockfn
 
 
.rxdata
.rxdata2:
        set BIT_IR_RECV, (hl)   ; clear recv interrupt bit
        set BIT_IR_RECV, (hl)   ; clear recv interrupt bit
        call F_copyrxbuf        ; if BC >2k it'll get downsized by W5100
        call F_copyrxbuf        ; if BC >2k it'll get downsized by W5100
        jp J_leavesockfn
        jp J_leavesockfn
 
 
;=========================================================================
;=========================================================================
; Sendto:
; Sendto:
; send data to a non-stream socket (i.e. SOCK_DGRAM, a UDP socket).
; send data to a non-stream socket (i.e2. SOCK_DGRAM, a UDP socket).
;
;
; Parameters:  A = file descriptor
; Parameters:  A = file descriptor
;             HL = address of 8 byte socket info structure
;             HL = address of 8 byte socket info structure
;             DE = address of buffer to send
;             DE = address of buffer to send
;             BC = size of buffer to send
;             BC = size of buffer to send
F_sendto
.globl F_sendto
 
F_sendto:
        ld (v_bufptr), hl       ; save socket info buffer pointer
        ld (v_bufptr), hl       ; save socket info buffer pointer
        call F_gethwsock        ; H is socket reg. MSB address
        call F_gethwsock        ; H is socket reg. MSB address
        jp c, J_leavesockfn     ; error finding socket if carry set
        jp c, J_leavesockfn     ; error finding socket if carry set
        push de                 ; save data buffer
        push de                 ; save data buffer
        push bc                 ; save buffer length
        push bc                 ; save buffer length
Line 90... Line 98...
        call F_setsockinfo
        call F_setsockinfo
        pop bc                  ; retrieve buffer length
        pop bc                  ; retrieve buffer length
        pop de                  ; retrieve data buffer
        pop de                  ; retrieve data buffer
        ld a, b                 ; MSB of send buffer size
        ld a, b                 ; MSB of send buffer size
        cp 0x08                 ; greater than 2K if compare result is pos.
        cp 0x08                 ; greater than 2K if compare result is pos.
        jp p, .multisend        ; TODO: send buffers >2k
        jp p, .multisend3       ; TODO: send buffers >2k
        call F_copytxbuf
        call F_copytxbuf
        jp J_leavesockfn
        jp J_leavesockfn
.multisend                      ; see TODO above!
.multisend3:                    ; see TODO above!
        ld bc, 0x7FF            ; send as much as possible for now.
        ld bc, 0x7FF            ; send as much as possible for now.
        call F_copytxbuf
        call F_copytxbuf
        jp J_leavesockfn
        jp J_leavesockfn
 
 
;=========================================================================
;=========================================================================
; Recvfrom - receive data from a socket. Usually used for a SOCK_DGRAM
; Recvfrom - receive data from a socket. Usually used for a SOCK_DGRAM
; socket, i.e. UDP.
; socket, i.e3. UDP.
;
;
; Parameters:  A = file descriptor
; Parameters:  A = file descriptor
;             HL = address of buffer to fill with connection information
;             HL = address of buffer to fill with connection information
;             DE = address of buffer to fill with return data
;             DE = address of buffer to fill with return data
;             BC = maximum bytes to get
;             BC = maximum bytes to get
;
;
; On error, the carry flag is set and the return code is returned in A.
; On error, the carry flag is set and the return code is returned in A.
; On successful return, BC contains the number of bytes transferred.
; On successful return, BC contains the number of bytes transferred.
F_recvfrom
.globl F_recvfrom
 
F_recvfrom:
        ld (v_bufptr), hl       ; save the connection buffer ptr
        ld (v_bufptr), hl       ; save the connection buffer ptr
        call F_gethwsock        ; H is socket reg MSB
        call F_gethwsock        ; H is socket reg MSB
        jp c, J_leavesockfn     ; carry is set if the fd is not valid
        jp c, J_leavesockfn     ; carry is set if the fd is not valid
        ld l, Sn_IR % 256       ; get the interrupt register
        ld l, Sn_IR % 256       ; get the interrupt register
 
 
.waitforrecv
.waitforrecv4:
        ld a, (hl)
        ld a, (hl)
        bit BIT_IR_RECV, a      ; see if the recv bit is set
        bit BIT_IR_RECV, a      ; see if the recv bit is set
        jr nz, .rxdata          ; Data is ready
        jr nz, .rxdata4         ; Data is ready
        bit BIT_IR_DISCON, a    ; check for RST condition
        bit BIT_IR_DISCON, a    ; check for RST condition
        jr z, .waitforrecv      ; no, so keep waiting
        jr z, .waitforrecv4     ; no, so keep waiting
        ld a, ECONNRESET        ; connection reset by peer
        ld a, ECONNRESET        ; connection reset by peer
        scf
        scf
        jp J_leavesockfn
        jp J_leavesockfn
 
 
.rxdata
.rxdata4:
        set BIT_IR_RECV, (hl)   ; clear recv interrupt bit
        set BIT_IR_RECV, (hl)   ; clear recv interrupt bit
        ld l, Sn_MR % 256       ; inspect mode register
        ld l, Sn_MR % 256       ; inspect mode register
        ld a, (hl)
        ld a, (hl)
        cp SOCK_DGRAM           ; Is this a SOCK_DGRAM (UDP) socket?
        cp SOCK_DGRAM           ; Is this a SOCK_DGRAM (UDP) socket?
        jr z, .rxudp
        jr z, .rxudp4
        call F_copyrxbuf        ; if BC >2k it'll get downsized by W5100
        call F_copyrxbuf        ; if BC >2k it'll get downsized by W5100
        ld de, (v_bufptr)       ; retrieve the buffer pointer
        ld de, (v_bufptr)       ; retrieve the buffer pointer
        call F_sockinfo         ; get socket information
        call F_sockinfo         ; get socket information
        jp J_leavesockfn
        jp J_leavesockfn
 
 
        ; UDP data comes with an 8 byte header stuck to the front.
        ; UDP data comes with an 8 byte header stuck to the front.
        ; To avoid having to shift the entire receive data buffer around,
        ; To avoid having to shift the entire receive data buffer around,
        ; first we pull off this 8 byte header and put it into the
        ; first we pull off this 8 byte header and put it into the
        ; socket info buffer. Then we receive the data proper.
        ; socket info buffer. Then we receive the data proper.
        ; The structure of the socket info buffer is documented in
        ; The structure of the socket info buffer is documented in
        ; w5100_sockinfo.asm.
        ; w5100_sockinfo.asm4.
.rxudp
.rxudp4:
        push bc                 ; save the max length requested
        push bc                 ; save the max length requested
        push de                 ; save the data buffer address
        push de                 ; save the data buffer address
        ld bc, 8                ; length of the header
        ld bc, 8                ; length of the header
        ld de, (v_bufptr)       ; retrieve the header buffer pointer
        ld de, (v_bufptr)       ; retrieve the header buffer pointer
        call F_copyrxbuf        ; fetch the header
        call F_copyrxbuf        ; fetch the header
Line 183... Line 192...
; If an fd is found that is ready (data can be read, or a connection can
; If an fd is found that is ready (data can be read, or a connection can
; be accepted), the first fd to be found ready is returned in A and the
; be accepted), the first fd to be found ready is returned in A and the
; flags that caused the condition in B. If no sockets are ready, A is 0
; flags that caused the condition in B. If no sockets are ready, A is 0
; and the zero flag is set. On error, the carry flag is set and A is set
; and the zero flag is set. On error, the carry flag is set and A is set
; to the error.
; to the error.
F_poll
.globl F_poll
 
F_poll:
        ld a, (v_pga)           ; save original page A
        ld a, (v_pga)           ; save original page A
        ld (v_buf_pga), a
        ld (v_buf_pga), a
        ld a, REGPAGE
        ld a, REGPAGE
        call F_setpageA
        call F_setpageA
 
 
.sockloop
.sockloop5:
        ld a, (de)              ; get the first socket
        ld a, (de)              ; get the first socket
        ld c, a                 ; save the file descriptor
        ld c, a                 ; save the file descriptor
        ld h, v_fd1hwsock / 256 ; set (hl) to point at fd map
        ld h, v_fd1hwsock / 256 ; set (hl) to point at fd map
        ld l, a                 ; (hl) = fd address
        ld l, a                 ; (hl) = fd address
        ld a, (hl)              ; a = hw socket MSB
        ld a, (hl)              ; a = hw socket MSB
        and SOCKMASK            ; mask out closed/virtual bits
        and SOCKMASK            ; mask out closed/virtual bits
        jr nz, .poll            ; nonzero means it's an open hw socket
        jr nz, .poll5           ; nonzero means it's an open hw socket
        inc de                  ; next socket
        inc de                  ; next socket
        djnz .sockloop
        djnz .sockloop5
        jr .noneready
        jr .noneready5
.poll
.poll5:
        ld h, a                 ; (hl) = socket register
        ld h, a                 ; (hl) = socket register
        ld l, Sn_IR % 256       ; interrupt register
        ld l, Sn_IR % 256       ; interrupt register
        ld a, (hl)
        ld a, (hl)
        and S_IR_CON|S_IR_RECV|S_IR_DISCON
        and S_IR_CON|S_IR_RECV|S_IR_DISCON
        jr nz, .ready           ; an event has occurred
        jr nz, .ready5          ; an event has occurred
        inc de                  ; next file descriptor
        inc de                  ; next file descriptor
        djnz .sockloop
        djnz .sockloop5
.noneready
.noneready5:
        xor a                   ; loop finished, no sockets were ready
        xor a                   ; loop finished, no sockets were ready
        jp J_leavesockfn
        jp J_leavesockfn
.ready
.ready5:
        ld b, a                 ; save flags
        ld b, a                 ; save flags
        ld a, c                 ; retrieve fd
        ld a, c                 ; retrieve fd
        jp J_leavesockfn
        jp J_leavesockfn
 
 
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
Line 231... Line 241...
; would be quite easy to provide an #ifdef'd pollall() function.
; would be quite easy to provide an #ifdef'd pollall() function.
;
;
; No parameters. The first file descriptor found to be ready will be returned
; No parameters. The first file descriptor found to be ready will be returned
; in A. If none are ready, A=0 and the zero flag is set. If an fd is ready,
; in A. If none are ready, A=0 and the zero flag is set. If an fd is ready,
; it is returned in A, and C contains the flags that triggered the condition.
; it is returned in A, and C contains the flags that triggered the condition.
F_pollall
.globl F_pollall
 
F_pollall:
        ld a, (v_pga)           ; save current page A
        ld a, (v_pga)           ; save current page A
        ld (v_buf_pga), a
        ld (v_buf_pga), a
        ld a, REGPAGE
        ld a, REGPAGE
        call F_setpageA
        call F_setpageA
        ld d, v_fd1hwsock / 256
        ld d, v_fd1hwsock / 256
        ld a, (v_lastpolled)    ; get addr. of socket to start at
        ld a, (v_lastpolled)    ; get addr. of socket to start at
        cp MAX_FD_NUMBER+1      ; wrap if this puts us off the end
        cp MAX_FD_NUMBER+1      ; wrap if this puts us off the end
        jr nz, .setaddr
        jr nz, .setaddr6
        ld a, v_fd1hwsock % 256 ; wrap
        ld a, v_fd1hwsock % 256 ; wrap
.setaddr
.setaddr6:
        ld e, a                 ; (de) points at socket to poll
        ld e, a                 ; (de) points at socket to poll
        ld b, MAX_FDS
        ld b, MAX_FDS
.sockloop
.sockloop6:
        ld a, (de)              ; get hardware socket register ptr
        ld a, (de)              ; get hardware socket register ptr
        and SOCKMASK            ; check it's a real socket
        and SOCKMASK            ; check it's a real socket
        jr nz, .poll
        jr nz, .poll6
.nextsock
.nextsock6:
        inc e                   ; next socket
        inc e                   ; next socket
        ld a, MAX_FD_NUMBER+1
        ld a, MAX_FD_NUMBER+1
        cp e                    ; wrap around to first fd?
        cp e                    ; wrap around to first fd?
        jr nz, .continue        ; no
        jr nz, .continue6       ; no
        ld e, v_fd1hwsock % 256 ; wrap back to first file descriptor
        ld e, v_fd1hwsock % 256 ; wrap back to first file descriptor
.continue
.continue6:
        djnz .sockloop
        djnz .sockloop6
        jr .noneready
        jr .noneready6
.poll
.poll6:
        ld h, a                 ; (hl) = socket register
        ld h, a                 ; (hl) = socket register
        call F_checksock
        call F_checksock
        jr z, .nextsock         ; advance to next socket fd
        jr z, .nextsock6                ; advance to next socket fd
.ready
.ready6:
        ld c, a                 ; copy flags into C
        ld c, a                 ; copy flags into C
        ld a, e                 ; ready fd in e
        ld a, e                 ; ready fd in e
        inc a
        inc a
        ld (v_lastpolled), a    ; save last polled sockfd+1
        ld (v_lastpolled), a    ; save last polled sockfd+1
        dec a                   ; restore A to proper value
        dec a                   ; restore A to proper value
        jp J_leavesockfn
        jp J_leavesockfn
.noneready
.noneready6:
        xor a                   ; A=0, zero flag set
        xor a                   ; A=0, zero flag set
        jp J_leavesockfn
        jp J_leavesockfn
 
 
;-------------------------------------------------------------------------
;-------------------------------------------------------------------------
; F_pollfd
; F_pollfd
Line 282... Line 293...
; way to do it.
; way to do it.
; Parameters: A = socket file descriptor
; Parameters: A = socket file descriptor
; Zero flag is set if not ready.
; Zero flag is set if not ready.
; For a ready fd, the reason for readiness is returned in C
; For a ready fd, the reason for readiness is returned in C
; Carry is set on error.
; Carry is set on error.
F_pollfd
.globl F_pollfd
 
F_pollfd:
        call F_gethwsock        ; H is socket reg MSB
        call F_gethwsock        ; H is socket reg MSB
        jp c, J_leavesockfn     ; carry is set if the fd is not valid
        jp c, J_leavesockfn     ; carry is set if the fd is not valid
 
 
        call F_checksock
        call F_checksock
        ld c, a                 ; copy flags into C
        ld c, a                 ; copy flags into C
        jp J_leavesockfn
        jp J_leavesockfn
 
 
; Check a socket's interrupt and status register. Register bank must
; Check a socket's interrupt and status register. Register bank must
; be set in H prior to entry.
; be set in H prior to entry.
F_checksock
.globl F_checksock
 
F_checksock:
        ld l, Sn_IR % 256       ; check interrupt register
        ld l, Sn_IR % 256       ; check interrupt register
        ld a, (hl)
        ld a, (hl)
        and S_IR_CON|S_IR_RECV|S_IR_DISCON
        and S_IR_CON|S_IR_RECV|S_IR_DISCON
        ret nz                  ; there is status to report now
        ret nz                  ; there is status to report now
        ld l, Sn_SR % 256       ; check status register for closedness
        ld l, Sn_SR % 256       ; check status register for closedness
        ld a, (hl)
        ld a, (hl)
        cp S_SR_SOCK_CLOSE_WAIT
        cp S_SR_SOCK_CLOSE_WAIT
        jr z, .closed
        jr z, .closed8
        and a                   ; 0 = S_SR_SOCK_CLOSED
        and a                   ; 0 = S_SR_SOCK_CLOSED
        jr z, .closed
        jr z, .closed8
        xor a                   ; return with Z set (and no status flags)
        xor a                   ; return with Z set (and no status flags)
        ret
        ret
.closed
.closed8:
        ld a, S_IR_DISCON       ; set "disconnect" flag
        ld a, S_IR_DISCON       ; set "disconnect" flag
        or a                    ; ensure Z flag is reset
        or a                    ; ensure Z flag is reset
        ret
        ret