2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
5 * Copyright (C) 2005 Neil Cafferkey
6 * Copyright (C) 2005 Pavel Fedin
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26 #include <aros/asmcall.h>
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/malloc.h>
32 #include <sys/socket.h>
33 #include <sys/socketvar.h>
34 #include <sys/syslog.h>
35 #include <sys/synch.h>
40 #include <netinet/in.h>
41 #include <netinet/in_systm.h>
42 #include <netinet/in_var.h>
43 #include <netinet/ip.h>
46 #include <net/if_sana.h>
47 #include <api/amiga_raf.h>
48 #define bcopy(a,b,c) CopyMem((APTR)(a),b,c)
51 * allocate mbufs for the size MTU at free_chain for read request
55 ioip_alloc_mbuf(struct IOIPReq
*s2rp
, ULONG MTU
)
57 register struct mbuf
*m
, *n
;
60 n
= s2rp
->ioip_reserved
;
62 /* Check for packet header */
63 if (n
&& (n
->m_flags
& M_PKTHDR
)) {
64 /* There is already a full packet */
68 /* Prepend by a packet header */
69 MGETHDR(m
, M_NOWAIT
, MT_HEADER
);
71 m
->m_len
= len
= MHLEN
;
72 s2rp
->ioip_reserved
= m
;
75 /* Find the end of the free chain */ /* ASSUME THAT THESE HAVE CLUSTERS */
76 while (n
= m
->m_next
) {
77 len
+= n
->m_len
; m
= n
;
81 * add new (cluster)mbufs to get the desired size
84 MGET(n
, M_NOWAIT
, MT_DATA
);
87 if (n
->m_ext
.ext_buf
!= NULL
) {
88 n
->m_len
= n
->m_ext
.ext_size
;
89 len
+= n
->m_ext
.ext_size
;
101 s2rp
->ioip_reserved
->m_pkthdr
.len
= len
;
104 m_freem(s2rp
->ioip_reserved
);
105 s2rp
->ioip_reserved
= NULL
;
113 ioip_alloc_mbuf(struct IOIPReq
*s2rp
, ULONG MTU
)
115 register struct mbuf
*m
, *n
;
119 * s2rp->ioip_reserved is either NULL, or an mbuf chain, possibly having
120 * packet header in the first one.
122 n
= s2rp
->ioip_reserved
;
124 /* Check for packet header */
125 if (n
&& (n
->m_flags
& M_PKTHDR
)) {
127 * chain already has the packet header
133 /* Prepend by a packet header */
134 MGETHDR(m
, M_NOWAIT
, MT_HEADER
);
136 m
->m_len
= len
= MHLEN
;
137 s2rp
->ioip_reserved
= m
;
144 * Now m points to the start of the mbuf chain. The first mbuf has
148 /* Find the end of the free chain */ /* ASSUME THAT THESE HAVE CLUSTERS */
149 while (n
= m
->m_next
) {
150 len
+= n
->m_len
; m
= n
;
154 * Now len has the total length of the mbuf chain, add new
155 * (cluster)mbufs to get the desired size (MTU).
158 MGET(n
, M_NOWAIT
, MT_DATA
);
161 if (n
->m_ext
.ext_buf
!= NULL
) {
162 len
+= n
->m_len
= n
->m_ext
.ext_size
;
173 s2rp
->ioip_reserved
->m_pkthdr
.len
= len
;
177 m_freem(s2rp
->ioip_reserved
);
178 s2rp
->ioip_reserved
= NULL
;
184 * Copy data from an mbuf chain starting from the beginning,
185 * continuing for "n" bytes, into the indicated continuous buffer.
187 * NOTE: this WILL be called from INTERRUPTS, so compile with stack checking
188 * disabled and use __saveds if near data is needed.
190 /*static SAVEDS BOOL m_copy_from_mbuf(
192 REG(a1, struct IOIPReq *from),
194 AROS_UFH3(BOOL
, m_copy_from_mbuf
,
195 AROS_UFHA(BYTE
*, to
, A0
),
196 AROS_UFHA(struct IOIPReq
*, from
, A1
),
197 AROS_UFHA(ULONG
, n
, D0
))
200 register struct mbuf
*m
= from
->ioip_packet
;
201 register unsigned count
;
206 log(LOG_ERR
, "m_copy_from_buff: mbuf chain short");
210 count
= MIN(m
->m_len
, n
);
211 bcopy(mtod(m
, caddr_t
), to
, count
);
221 * Copy data from an continuous buffer 'from' to preallocated mbuf chain
222 * starting from the beginning, continuing for "n" bytes.
223 * Mbufs in the preallocated chain must have their m_len field set to maximum
224 * amount of data that they can have.
226 * NOTE: this WILL be called from INTERRUPTS, so compile with stack checking
227 * disabled and use __saveds if near data is needed.
229 /*static SAVEDS BOOL m_copy_to_mbuf(
230 REG(a0, struct IOIPReq* to),
233 AROS_UFH3(BOOL
, m_copy_to_mbuf
,
234 AROS_UFHA(struct IOIPReq
*, to
, A0
),
235 AROS_UFHA(BYTE
*, from
, A1
),
236 AROS_UFHA(ULONG
, n
, D0
))
239 register struct mbuf
*f
, *m
= to
->ioip_reserved
;
243 if (!(m
->m_flags
& M_PKTHDR
)) {
244 log(LOG_ERR
, "m_copy_to_buff: mbuf chain has no header");
252 log(LOG_ERR
, "m_copy_to_buff: mbuf chain short, "
253 "packet len =%lu, reserved =%lu, "
254 "wiretype =%lu, mtu =%lu",
255 totlen
, to
->ioip_reserved
->m_pkthdr
.len
,
256 to
->ioip_s2
.ios2_PacketType
,
257 (ULONG
)to
->ioip_if
->ss_if
.if_mtu
);
263 bcopy(from
, mtod(m
, caddr_t
), m
->m_len
);
271 * move the packet to the field 'ioip_packet',
272 * set total length of the packet and terminate it.
274 f
= m
->m_next
; /* first free mbuf */
275 m
->m_next
= NULL
; /* terminate the chain */
277 to
->ioip_packet
= to
->ioip_reserved
;
278 to
->ioip_packet
->m_pkthdr
.len
= totlen
; /* set packet length */
279 to
->ioip_reserved
= f
; /* leftover mbufs */
282 * More mbuf flags and interface pointer must be set later
288 struct TagItem buffermanagement
[3] = {
289 { S2_CopyToBuff
, (IPTR
)AROS_ASMSYMNAME(m_copy_to_mbuf
) },
290 { S2_CopyFromBuff
, (IPTR
)AROS_ASMSYMNAME(m_copy_from_mbuf
) },