Subversion Repositories Spectranet

[/] [branches/] [gnubinutils/] [rom/] [w5100_rxtx.asm] - Blame information for rev 384

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 winston
;The MIT License
2
;
3
;Copyright (c) 2008 Dylan Smith
4
;
5
;Permission is hereby granted, free of charge, to any person obtaining a copy
6
;of this software and associated documentation files (the "Software"), to deal
7
;in the Software without restriction, including without limitation the rights
8
;to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
;copies of the Software, and to permit persons to whom the Software is
10
;furnished to do so, subject to the following conditions:
11
;
12
;The above copyright notice and this permission notice shall be included in
13
;all copies or substantial portions of the Software.
14
;
15
;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
;THE SOFTWARE.
22
;
23 384 winston
.include        "w5100_defs.inc"
24
.include        "sysvars.inc"
25
.include        "sockdefs.inc"
26
 
27 25 winston
;
28
; send/sendto and recv/recvfrom send data to a socket and get data
29
; from it.
30
;
31
; F_send:
32
; Sends data to a socket (that should be a SOCK_STREAM).
33
; Parameters: A  = file descriptor to send data to
34
;             DE = source buffer to copy to hardware
35
;             BC = size of source buffer
36
; On return,  BC = number of bytes sent
37
; Carry flag is set on error and A contains error code.
38 384 winston
.text
39
.globl F_send
40
F_send:
41 25 winston
        call F_gethwsock        ; H is socket reg. MSB address
42 142 winston
        jp c, J_leavesockfn     ; error finding socket if carry set
43 25 winston
        ld a, b                 ; MSB of send buffer size
44
        cp 0x08                 ; greater than 2K if compare result is pos.
45 384 winston
        jp p, .multisend1       ; TODO: send buffers >2k
46 25 winston
        call F_copytxbuf
47 142 winston
        jp J_leavesockfn
48 384 winston
.multisend1:                    ; see TODO above!
49 25 winston
        ld bc, 0x7FF            ; send as much as possible for now.
50
        call F_copytxbuf
51 142 winston
        jp J_leavesockfn
52 25 winston
 
53
; F_recv:
54
; Receive data from a socket. Note - this function blocks if no data
55
; is available. Use poll to check if data is available if you don't want
56
; this to happen.
57
;
58
; Parameters : A  = file descriptor
59
;              DE = address of memory to fill with data
60
;              BC = number of bytes to get
61 384 winston
.globl F_recv
62
F_recv:
63 25 winston
        call F_gethwsock        ; H is socket reg MSB
64 142 winston
        jp c, J_leavesockfn     ; carry is set if the fd is not valid
65 27 winston
        ld l, Sn_IR % 256       ; get the interrupt register
66 41 winston
 
67 384 winston
.waitforrecv2:
68 41 winston
        ld a, (hl)
69
        bit BIT_IR_RECV, a      ; see if the recv bit is set
70 384 winston
        jr nz, .rxdata2         ; Data is ready
71 41 winston
        bit BIT_IR_DISCON, a    ; check for RST condition
72 384 winston
        jr z, .waitforrecv2     ; no, so keep waiting
73 41 winston
        ld a, ECONNRESET        ; connection reset by peer
74
        scf
75 142 winston
        jp J_leavesockfn
76 27 winston
 
77 384 winston
.rxdata2:
78 41 winston
        set BIT_IR_RECV, (hl)   ; clear recv interrupt bit
79 25 winston
        call F_copyrxbuf        ; if BC >2k it'll get downsized by W5100
80 142 winston
        jp J_leavesockfn
81 25 winston
 
82 46 winston
;=========================================================================
83
; Sendto:
84 384 winston
; send data to a non-stream socket (i.e2. SOCK_DGRAM, a UDP socket).
85 46 winston
;
86
; Parameters:  A = file descriptor
87
;             HL = address of 8 byte socket info structure
88
;             DE = address of buffer to send
89
;             BC = size of buffer to send
90 384 winston
.globl F_sendto
91
F_sendto:
92 48 winston
        ld (v_bufptr), hl       ; save socket info buffer pointer
93 46 winston
        call F_gethwsock        ; H is socket reg. MSB address
94 142 winston
        jp c, J_leavesockfn     ; error finding socket if carry set
95 46 winston
        push de                 ; save data buffer
96
        push bc                 ; save buffer length
97
        ld de, (v_bufptr)       ; get sock info ptr
98
        call F_setsockinfo
99
        pop bc                  ; retrieve buffer length
100
        pop de                  ; retrieve data buffer
101
        ld a, b                 ; MSB of send buffer size
102
        cp 0x08                 ; greater than 2K if compare result is pos.
103 384 winston
        jp p, .multisend3       ; TODO: send buffers >2k
104 46 winston
        call F_copytxbuf
105 142 winston
        jp J_leavesockfn
106 384 winston
.multisend3:                    ; see TODO above!
107 46 winston
        ld bc, 0x7FF            ; send as much as possible for now.
108
        call F_copytxbuf
109 142 winston
        jp J_leavesockfn
110 46 winston
 
111
;=========================================================================
112
; Recvfrom - receive data from a socket. Usually used for a SOCK_DGRAM
113 384 winston
; socket, i.e3. UDP.
114 46 winston
;
115
; Parameters:  A = file descriptor
116
;             HL = address of buffer to fill with connection information
117
;             DE = address of buffer to fill with return data
118
;             BC = maximum bytes to get
119
;
120
; On error, the carry flag is set and the return code is returned in A.
121
; On successful return, BC contains the number of bytes transferred.
122 384 winston
.globl F_recvfrom
123
F_recvfrom:
124 46 winston
        ld (v_bufptr), hl       ; save the connection buffer ptr
125
        call F_gethwsock        ; H is socket reg MSB
126 142 winston
        jp c, J_leavesockfn     ; carry is set if the fd is not valid
127 46 winston
        ld l, Sn_IR % 256       ; get the interrupt register
128
 
129 384 winston
.waitforrecv4:
130 46 winston
        ld a, (hl)
131
        bit BIT_IR_RECV, a      ; see if the recv bit is set
132 384 winston
        jr nz, .rxdata4         ; Data is ready
133 46 winston
        bit BIT_IR_DISCON, a    ; check for RST condition
134 384 winston
        jr z, .waitforrecv4     ; no, so keep waiting
135 46 winston
        ld a, ECONNRESET        ; connection reset by peer
136
        scf
137 142 winston
        jp J_leavesockfn
138 25 winston
 
139 384 winston
.rxdata4:
140 46 winston
        set BIT_IR_RECV, (hl)   ; clear recv interrupt bit
141
        ld l, Sn_MR % 256       ; inspect mode register
142
        ld a, (hl)
143
        cp SOCK_DGRAM           ; Is this a SOCK_DGRAM (UDP) socket?
144 384 winston
        jr z, .rxudp4
145 46 winston
        call F_copyrxbuf        ; if BC >2k it'll get downsized by W5100
146
        ld de, (v_bufptr)       ; retrieve the buffer pointer
147
        call F_sockinfo         ; get socket information
148 142 winston
        jp J_leavesockfn
149 46 winston
 
150
        ; UDP data comes with an 8 byte header stuck to the front.
151
        ; To avoid having to shift the entire receive data buffer around,
152
        ; first we pull off this 8 byte header and put it into the
153
        ; socket info buffer. Then we receive the data proper.
154
        ; The structure of the socket info buffer is documented in
155 384 winston
        ; w5100_sockinfo.asm4.
156
.rxudp4:
157 46 winston
        push bc                 ; save the max length requested
158
        push de                 ; save the data buffer address
159
        ld bc, 8                ; length of the header
160
        ld de, (v_bufptr)       ; retrieve the header buffer pointer
161
        call F_copyrxbuf        ; fetch the header
162 89 winston
        ld l, Sn_IR % 256       ; the IR needs resetting again
163
        set BIT_IR_RECV, (hl)   ; since the W5100 sees it still has data
164 46 winston
        pop de                  ; retrieve the data buffer address
165
        pop bc                  ; retrieve the length argument
166
        call F_copyrxbuf        ; get the data
167
        push hl                 ; save the W5100 register pointer
168
        ld ix, (v_bufptr)       ; now convert the big endian port to
169
        ld h, (ix+4)            ; little endian. Byte 4 is the high order
170
        ld l, (ix+5)            ; and 5 is the low order byte.
171
        ld (ix+4), l
172
        ld (ix+5), h
173
        pop hl                  ; get the register pointer back
174
        ld l, Sn_PORT0 % 256    ; point it at the source port register
175
        ld a, (hl)
176
        ld (ix+7), a            ; high order of the source port
177
        inc l
178
        ld a, (hl)
179
        ld (ix+6), a            ; low order of the source port
180 142 winston
        jp J_leavesockfn
181 46 winston
 
182 27 winston
;--------------------------------------------------------------------------
183
; F_poll:
184
; Check an array of open file descriptors to see if one has data ready
185
; to read (or in the case of a listening socket, if someone connected).
186
; This function doesn't provide a timeout (the BSD version does). The
187
; C wrapper will provide a timeout.
188
;
189
; Parameters: DE = address of file descriptor list
190
;             B  = number of file descriptors to poll
191
;
192
; If an fd is found that is ready (data can be read, or a connection can
193 84 winston
; be accepted), the first fd to be found ready is returned in A and the
194
; flags that caused the condition in B. If no sockets are ready, A is 0
195
; and the zero flag is set. On error, the carry flag is set and A is set
196
; to the error.
197 384 winston
.globl F_poll
198
F_poll:
199 142 winston
        ld a, (v_pga)           ; save original page A
200
        ld (v_buf_pga), a
201 110 winston
        ld a, REGPAGE
202 27 winston
        call F_setpageA
203
 
204 384 winston
.sockloop5:
205 27 winston
        ld a, (de)              ; get the first socket
206
        ld c, a                 ; save the file descriptor
207
        ld h, v_fd1hwsock / 256 ; set (hl) to point at fd map
208
        ld l, a                 ; (hl) = fd address
209
        ld a, (hl)              ; a = hw socket MSB
210
        and SOCKMASK            ; mask out closed/virtual bits
211 384 winston
        jr nz, .poll5           ; nonzero means it's an open hw socket
212 27 winston
        inc de                  ; next socket
213 384 winston
        djnz .sockloop5
214
        jr .noneready5
215
.poll5:
216 27 winston
        ld h, a                 ; (hl) = socket register
217
        ld l, Sn_IR % 256       ; interrupt register
218 84 winston
        ld a, (hl)
219
        and S_IR_CON|S_IR_RECV|S_IR_DISCON
220 384 winston
        jr nz, .ready5          ; an event has occurred
221 27 winston
        inc de                  ; next file descriptor
222 384 winston
        djnz .sockloop5
223
.noneready5:
224 27 winston
        xor a                   ; loop finished, no sockets were ready
225 142 winston
        jp J_leavesockfn
226 384 winston
.ready5:
227 84 winston
        ld b, a                 ; save flags
228 27 winston
        ld a, c                 ; retrieve fd
229 142 winston
        jp J_leavesockfn
230 27 winston
 
231
;---------------------------------------------------------------------------
232
; F_pollall:
233
; This is not a BSD socket library function. However, there are many
234
; (perhaps most?) instances where you just want to poll all open sockets.
235
; Given there can never be very many file descriptors in the first place,
236
; unless you're polling a subset of your file descriptors, it's probably
237
; best to use this function (it will be a lot easier, since you won't
238
; need to shuffle things in and out of an array of file descriptors)
239
;
240
; To make the program (if written in C) compatible with a modern OS, it
241
; would be quite easy to provide an #ifdef'd pollall() function.
242
;
243
; No parameters. The first file descriptor found to be ready will be returned
244 84 winston
; in A. If none are ready, A=0 and the zero flag is set. If an fd is ready,
245
; it is returned in A, and C contains the flags that triggered the condition.
246 384 winston
.globl F_pollall
247
F_pollall:
248 142 winston
        ld a, (v_pga)           ; save current page A
249
        ld (v_buf_pga), a
250 110 winston
        ld a, REGPAGE
251 27 winston
        call F_setpageA
252 84 winston
        ld d, v_fd1hwsock / 256
253
        ld a, (v_lastpolled)    ; get addr. of socket to start at
254 85 winston
        cp MAX_FD_NUMBER+1      ; wrap if this puts us off the end
255 384 winston
        jr nz, .setaddr6
256 84 winston
        ld a, v_fd1hwsock % 256 ; wrap
257 384 winston
.setaddr6:
258 84 winston
        ld e, a                 ; (de) points at socket to poll
259 27 winston
        ld b, MAX_FDS
260 384 winston
.sockloop6:
261 27 winston
        ld a, (de)              ; get hardware socket register ptr
262
        and SOCKMASK            ; check it's a real socket
263 384 winston
        jr nz, .poll6
264
.nextsock6:
265 84 winston
        inc e                   ; next socket
266
        ld a, MAX_FD_NUMBER+1
267
        cp e                    ; wrap around to first fd?
268 384 winston
        jr nz, .continue6       ; no
269 84 winston
        ld e, v_fd1hwsock % 256 ; wrap back to first file descriptor
270 384 winston
.continue6:
271
        djnz .sockloop6
272
        jr .noneready6
273
.poll6:
274 27 winston
        ld h, a                 ; (hl) = socket register
275 307 winston
        call F_checksock
276 384 winston
        jr z, .nextsock6                ; advance to next socket fd
277
.ready6:
278 84 winston
        ld c, a                 ; copy flags into C
279 27 winston
        ld a, e                 ; ready fd in e
280 85 winston
        inc a
281
        ld (v_lastpolled), a    ; save last polled sockfd+1
282
        dec a                   ; restore A to proper value
283 142 winston
        jp J_leavesockfn
284 384 winston
.noneready6:
285 307 winston
        xor a                   ; A=0, zero flag set
286
        jp J_leavesockfn
287 27 winston
 
288 76 winston
;-------------------------------------------------------------------------
289
; F_pollfd
290
; Poll a single file descriptor.
291
; Again, not a BSD socket function. However, in many instances all you
292
; need to do is poll a single socket, and this will be the most efficient
293
; way to do it.
294
; Parameters: A = socket file descriptor
295
; Zero flag is set if not ready.
296 84 winston
; For a ready fd, the reason for readiness is returned in C
297 76 winston
; Carry is set on error.
298 384 winston
.globl F_pollfd
299
F_pollfd:
300 76 winston
        call F_gethwsock        ; H is socket reg MSB
301 142 winston
        jp c, J_leavesockfn     ; carry is set if the fd is not valid
302 76 winston
 
303 307 winston
        call F_checksock
304 84 winston
        ld c, a                 ; copy flags into C
305 142 winston
        jp J_leavesockfn
306 76 winston
 
307 307 winston
; Check a socket's interrupt and status register. Register bank must
308
; be set in H prior to entry.
309 384 winston
.globl F_checksock
310
F_checksock:
311 307 winston
        ld l, Sn_IR % 256       ; check interrupt register
312
        ld a, (hl)
313
        and S_IR_CON|S_IR_RECV|S_IR_DISCON
314
        ret nz                  ; there is status to report now
315
        ld l, Sn_SR % 256       ; check status register for closedness
316
        ld a, (hl)
317
        cp S_SR_SOCK_CLOSE_WAIT
318 384 winston
        jr z, .closed8
319 307 winston
        and a                   ; 0 = S_SR_SOCK_CLOSED
320 384 winston
        jr z, .closed8
321 307 winston
        xor a                   ; return with Z set (and no status flags)
322
        ret
323 384 winston
.closed8:
324 307 winston
        ld a, S_IR_DISCON       ; set "disconnect" flag
325
        or a                    ; ensure Z flag is reset
326
        ret
327