From 6d043beb03c572d3fd2f6995c83e13516913790a Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Thu, 3 May 2007 21:18:21 +0000 Subject: [PATCH] freebsd compat. layer: added mii placeholders, callout implementation. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21006 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/net/net_stack.h | 10 + src/libs/compat/freebsd_network/Jamfile | 2 + src/libs/compat/freebsd_network/callout.c | 64 ++++ src/libs/compat/freebsd_network/compat.c | 9 + .../freebsd_network/compat/sys/callout.h | 98 ++---- .../compat/freebsd_network/compat/sys/mbuf.h | 19 +- .../compat/freebsd_network/compat/sys/mutex.h | 2 +- src/libs/compat/freebsd_network/device.h | 3 + src/libs/compat/freebsd_network/mbuf.c | 327 +++++++++++++++++- src/libs/compat/freebsd_network/mii.c | 40 +++ src/libs/compat/freebsd_network/mutex.c | 2 +- 11 files changed, 476 insertions(+), 100 deletions(-) create mode 100644 src/libs/compat/freebsd_network/callout.c create mode 100644 src/libs/compat/freebsd_network/mii.c diff --git a/headers/private/net/net_stack.h b/headers/private/net/net_stack.h index 4b6eb36ce4..539d9b00a0 100644 --- a/headers/private/net/net_stack.h +++ b/headers/private/net/net_stack.h @@ -14,6 +14,16 @@ #define NET_STACK_MODULE_NAME "network/stack/v1" + +struct net_address_module_info; +struct net_protocol_module_info; + +struct net_buffer; +struct net_device; +struct net_domain; +struct net_socket; +struct net_timer; + struct net_fifo { benaphore lock; sem_id notify; diff --git a/src/libs/compat/freebsd_network/Jamfile b/src/libs/compat/freebsd_network/Jamfile index 9bfc4d236a..badd43bf63 100644 --- a/src/libs/compat/freebsd_network/Jamfile +++ b/src/libs/compat/freebsd_network/Jamfile @@ -10,10 +10,12 @@ SubDirCcFlags [ FDefines _KERNEL=1 ] ; Library libfreebsd_network.a : bus.c busdma_machdep.c + callout.c compat.c device.c if.c if_media.c mbuf.c + mii.c mutex.c ; diff --git a/src/libs/compat/freebsd_network/callout.c b/src/libs/compat/freebsd_network/callout.c new file mode 100644 index 0000000000..a34eabdffd --- /dev/null +++ b/src/libs/compat/freebsd_network/callout.c @@ -0,0 +1,64 @@ +/* + * Copyright 2007, Hugo Santos. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Hugo Santos, hugosantos@gmail.com + */ + +#include "device.h" + +#include + + +static void +handle_callout(struct net_timer *timer, void *data) +{ + struct callout *c = data; + struct mtx *c_mtx = c->c_mtx; + + if (c_mtx) + mtx_lock(c_mtx); + + /* FreeBSD 6.2 uses THREAD_NO_SLEEPING/THREAD_SLEEPING_OK when calling the + * callback */ + + c->c_func(c->c_arg); + + if (c_mtx) + mtx_unlock(c_mtx); +} + + +void +callout_init_mtx(struct callout *c, struct mtx *mtx, int flags) +{ + gStack->init_timer(&c->c_timer, handle_callout, c); + + c->c_arg = NULL; + c->c_func = NULL; + c->c_mtx = mtx; + c->c_flags = flags; +} + + +int +callout_reset(struct callout *c, int when, void (*func)(void *), void *arg) +{ + int canceled = gStack->cancel_timer(&c->c_timer) ? 1 : 0; + + c->c_func = func; + c->c_arg = arg; + + gStack->set_timer(&c->c_timer, when); + + return canceled; +} + + +int +_callout_stop_safe(struct callout *c, int safe) +{ + return gStack->cancel_timer(&c->c_timer) ? 1 : 0; +} + diff --git a/src/libs/compat/freebsd_network/compat.c b/src/libs/compat/freebsd_network/compat.c index 1006f8fb23..6dc4673a56 100644 --- a/src/libs/compat/freebsd_network/compat.c +++ b/src/libs/compat/freebsd_network/compat.c @@ -21,6 +21,7 @@ status_t init_compat_layer(void); +struct net_stack_module_info *gStack; pci_module_info *gPci; uint32_t @@ -143,6 +144,13 @@ device_get_softc(device_t dev) } +int +device_delete_child(device_t dev, device_t child) +{ + return -1; +} + + int printf(const char *format, ...) { @@ -222,6 +230,7 @@ init_compat_layer() } module_dependency module_dependencies[] = { + {NET_STACK_MODULE_NAME, (module_info **)&gStack}, {B_PCI_MODULE_NAME, (module_info **)&gPci}, {} }; diff --git a/src/libs/compat/freebsd_network/compat/sys/callout.h b/src/libs/compat/freebsd_network/compat/sys/callout.h index 428008ff1b..9fe4e530bb 100644 --- a/src/libs/compat/freebsd_network/compat/sys/callout.h +++ b/src/libs/compat/freebsd_network/compat/sys/callout.h @@ -1,90 +1,36 @@ -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)callout.h 8.2 (Berkeley) 1/21/94 - * $FreeBSD: src/sys/sys/callout.h,v 1.28.2.1 2005/09/12 13:43:34 glebius Exp $ - */ +#ifndef _FBSD_COMPAT_SYS_CALLOUT_H_ +#define _FBSD_COMPAT_SYS_CALLOUT_H_ -#ifndef _SYS_CALLOUT_H_ -#define _SYS_CALLOUT_H_ +#include +#include #include -struct mtx; - -SLIST_HEAD(callout_list, callout); -TAILQ_HEAD(callout_tailq, callout); struct callout { - union { - SLIST_ENTRY(callout) sle; - TAILQ_ENTRY(callout) tqe; - } c_links; - int c_time; /* ticks to the event */ - void *c_arg; /* function argument */ - void (*c_func)(void *); /* function to call */ - struct mtx *c_mtx; /* mutex to lock */ - int c_flags; /* state of this entry */ + struct net_timer c_timer; + void * c_arg; + void (*c_func)(void *); + struct mtx * c_mtx; + int c_flags; }; -#define CALLOUT_LOCAL_ALLOC 0x0001 /* was allocated from callfree */ -#define CALLOUT_ACTIVE 0x0002 /* callout is currently active */ -#define CALLOUT_PENDING 0x0004 /* callout is waiting for timeout */ -#define CALLOUT_MPSAFE 0x0008 /* callout handler is mp safe */ -#define CALLOUT_RETURNUNLOCKED 0x0010 /* handler returns with mtx unlocked */ -struct callout_handle { - struct callout *callout; -}; - -#ifdef _KERNEL -extern struct callout_list callfree; -extern struct callout *callout; -extern int ncallout; -extern struct callout_tailq *callwheel; -extern int callwheelsize, callwheelbits, callwheelmask, softticks; -extern struct mtx callout_lock; - -#define callout_active(c) ((c)->c_flags & CALLOUT_ACTIVE) -#define callout_deactivate(c) ((c)->c_flags &= ~CALLOUT_ACTIVE) -#define callout_drain(c) _callout_stop_safe(c, 1) -void callout_init(struct callout *, int); -void callout_init_mtx(struct callout *, struct mtx *, int); -#define callout_pending(c) ((c)->c_flags & CALLOUT_PENDING) +void callout_init_mtx(struct callout *, struct mtx *, int); int callout_reset(struct callout *, int, void (*)(void *), void *); + +#define callout_drain(c) _callout_stop_safe(c, 1) #define callout_stop(c) _callout_stop_safe(c, 0) int _callout_stop_safe(struct callout *, int); -#endif -#endif /* _SYS_CALLOUT_H_ */ +static inline void +callout_init(struct callout *c, int mpsafe) +{ + if (mpsafe) + callout_init_mtx(c, NULL, 0); + else + callout_init_mtx(c, &Giant, 0); +} + +#endif diff --git a/src/libs/compat/freebsd_network/compat/sys/mbuf.h b/src/libs/compat/freebsd_network/compat/sys/mbuf.h index 3692db1a84..bca639d086 100644 --- a/src/libs/compat/freebsd_network/compat/sys/mbuf.h +++ b/src/libs/compat/freebsd_network/compat/sys/mbuf.h @@ -4,15 +4,15 @@ #include #include -#define MLEN (MSIZE - sizeof(struct m_hdr)) -#define MHLEN (MSIZE - sizeof(struct pkthdr)) +#define MLEN ((int)(MSIZE - sizeof(struct m_hdr))) +#define MHLEN ((int)(MSIZE - sizeof(struct pkthdr))) #ifdef _KERNEL struct m_hdr { struct mbuf * mh_next; struct mbuf * mh_nextpkt; - void * mh_data; + caddr_t mh_data; int mh_len; int mh_flags; short mh_type; @@ -28,6 +28,7 @@ struct pkthdr { struct m_ext { void * ext_buf; unsigned int ext_size; + int ext_type; }; struct mbuf { @@ -66,6 +67,9 @@ struct mbuf { #define M_EXT 0x0001 #define M_PKTHDR 0x0002 +#define EXT_CLUSTER 1 +#define EXT_PACKET 3 + #define M_BCAST 0x0200 #define M_MCAST 0x0400 @@ -80,8 +84,17 @@ struct mbuf { struct mbuf *m_getcl(int how, short type, int flags); void m_freem(struct mbuf *mbuf); +struct mbuf *m_free(struct mbuf *m); struct mbuf *m_defrag(struct mbuf *m, int); +u_int m_length(struct mbuf *m, struct mbuf **last); +u_int m_fixhdr(struct mbuf *m); +void m_cat(struct mbuf *m, struct mbuf *n); +void m_copydata(const struct mbuf *m, int off, int len, caddr_t cp); + +struct mbuf *m_get(int how, short type); +struct mbuf *m_gethdr(int how, short type); + #define mtod(m, type) (type)((m)->m_data) /* Check if the supplied mbuf has a packet header, or else panic. */ diff --git a/src/libs/compat/freebsd_network/compat/sys/mutex.h b/src/libs/compat/freebsd_network/compat/sys/mutex.h index d01264cf7f..54d84df786 100644 --- a/src/libs/compat/freebsd_network/compat/sys/mutex.h +++ b/src/libs/compat/freebsd_network/compat/sys/mutex.h @@ -46,6 +46,6 @@ static inline void mtx_unlock(struct mtx *mtx) void mtx_init(struct mtx *m, const char *name, const char *type, int opts); void mtx_destroy(struct mtx *m); -extern struct mutex Giant; +extern struct mtx Giant; #endif diff --git a/src/libs/compat/freebsd_network/device.h b/src/libs/compat/freebsd_network/device.h index 3fa69d7938..3e794e3b5e 100644 --- a/src/libs/compat/freebsd_network/device.h +++ b/src/libs/compat/freebsd_network/device.h @@ -15,6 +15,8 @@ #include #include +#include + #include #include #include @@ -45,6 +47,7 @@ enum { }; +extern struct net_stack_module_info *gStack; extern pci_module_info *gPci; #endif diff --git a/src/libs/compat/freebsd_network/mbuf.c b/src/libs/compat/freebsd_network/mbuf.c index 32c13905f0..5f5f4985d9 100644 --- a/src/libs/compat/freebsd_network/mbuf.c +++ b/src/libs/compat/freebsd_network/mbuf.c @@ -6,12 +6,20 @@ * Hugo Santos, hugosantos@gmail.com * * Some of this code is based on previous work by Marcus Overhagen. + * + * `m_defrag' and friends are straight from FreeBSD 6.2. */ #include +#include #include #include +#include + + +#define MBUF_CHECKSLEEP(how) do { } while (0) +#define MBTOM(how) (how) status_t init_mbufs(void); @@ -24,7 +32,17 @@ static object_cache *sMBufCache; static object_cache *sChunkCache; -static void +static int +m_to_oc_flags(int how) +{ + if (how & M_NOWAIT) + return CACHE_DONT_SLEEP; + + return 0; +} + + +static int construct_mbuf(struct mbuf *mb, short type, int flags) { mb->m_next = NULL; @@ -36,22 +54,75 @@ construct_mbuf(struct mbuf *mb, short type, int flags) if (flags & M_PKTHDR) { mb->m_data = mb->m_pktdat; memset(&mb->m_pkthdr, 0, sizeof(mb->m_pkthdr)); + /* SLIST_INIT(&m->m_pkthdr.tags); */ } else { mb->m_data = mb->m_dat; } + + return 0; +} + + +static int +construct_ext_mbuf(struct mbuf *mb, int how) +{ + mb->m_ext.ext_buf = object_cache_alloc(sChunkCache, m_to_oc_flags(how)); + if (mb->m_ext.ext_buf == NULL) + return B_NO_MEMORY; + + mb->m_data = mb->m_ext.ext_buf; + mb->m_flags |= M_EXT; + /* mb->m_ext.ext_free = NULL; */ + /* mb->m_ext.ext_args = NULL; */ + mb->m_ext.ext_size = MCLBYTES; + mb->m_ext.ext_type = EXT_CLUSTER; + /* mb->m_ext.ref_cnt = NULL; */ + + return 0; +} + + +static int +construct_pkt_mbuf(int how, struct mbuf *mb, short type, int flags) +{ + construct_mbuf(mb, type, flags); + if (construct_ext_mbuf(mb, how) < 0) + return -1; + mb->m_ext.ext_type = EXT_PACKET; + return 0; +} + + +static void +destruct_pkt_mbuf(struct mbuf *mb) +{ + object_cache_free(sChunkCache, mb->m_ext.ext_buf); + mb->m_ext.ext_buf = NULL; } struct mbuf * m_getcl(int how, short type, int flags) { - uint32 cacheFlags = 0; - struct mbuf *mb; + struct mbuf *mb = + (struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how)); + if (mb == NULL) + return NULL; - if (how & M_NOWAIT) - cacheFlags = CACHE_DONT_SLEEP; + if (construct_pkt_mbuf(how, mb, type, flags) < 0) { + object_cache_free(sMBufCache, mb); + return NULL; + } - mb = (struct mbuf *)object_cache_alloc(sMBufCache, cacheFlags); + return mb; +} + + +static struct mbuf * +_m_get(int how, short type, int flags) +{ + struct mbuf *mb = + (struct mbuf *)object_cache_alloc(sMBufCache, m_to_oc_flags(how)); if (mb == NULL) return NULL; @@ -61,31 +132,249 @@ m_getcl(int how, short type, int flags) } -void -m_freem(struct mbuf *mp) +struct mbuf * +m_get(int how, short type) { - struct mbuf *next = mp; + return _m_get(how, type, 0); +} - do { - mp = next; - next = next->m_next; - if (mp->m_flags & M_EXT) - object_cache_free(sChunkCache, mp->m_ext.ext_buf); - object_cache_free(sMBufCache, mp); - } while (next); +struct mbuf * +m_gethdr(int how, short type) +{ + return _m_get(how, type, M_PKTHDR); +} + + +void +m_freem(struct mbuf *mb) +{ + while (mb) + mb = m_free(mb); +} + + +static void +mb_free_ext(struct mbuf *m) +{ + /* + if (m->m_ext.ref_count != NULL) + panic("unsupported"); + */ + + if (m->m_ext.ext_type == EXT_PACKET) + destruct_pkt_mbuf(m); + else if (m->m_ext.ext_type == EXT_CLUSTER) { + object_cache_free(sChunkCache, m->m_ext.ext_buf); + m->m_ext.ext_buf = NULL; + } else + panic("unknown type"); + + object_cache_free(sMBufCache, m); +} + + +struct mbuf * +m_free(struct mbuf *m) +{ + struct mbuf *next = m->m_next; + + if (m->m_flags & M_EXT) + mb_free_ext(m); + else + object_cache_free(sMBufCache, m); + + return next; +} + + +/* + * Copy data from an mbuf chain starting "off" bytes from the beginning, + * continuing for "len" bytes, into the indicated buffer. + */ +void +m_copydata(const struct mbuf *m, int off, int len, caddr_t cp) +{ + u_int count; + + KASSERT(off >= 0, ("m_copydata, negative off %d", off)); + KASSERT(len >= 0, ("m_copydata, negative len %d", len)); + while (off > 0) { + KASSERT(m != NULL, ("m_copydata, offset > size of mbuf chain")); + if (off < m->m_len) + break; + off -= m->m_len; + m = m->m_next; + } + while (len > 0) { + KASSERT(m != NULL, ("m_copydata, length > size of mbuf chain")); + count = min(m->m_len - off, len); + bcopy(mtod(m, caddr_t) + off, cp, count); + len -= count; + cp += count; + off = 0; + m = m->m_next; + } +} + + +/* + * Concatenate mbuf chain n to m. + * Both chains must be of the same type (e.g. MT_DATA). + * Any m_pkthdr is not updated. + */ +void +m_cat(struct mbuf *m, struct mbuf *n) +{ + while (m->m_next) + m = m->m_next; + while (n) { + if (m->m_flags & M_EXT || + m->m_data + m->m_len + n->m_len >= &m->m_dat[MLEN]) { + /* just join the two chains */ + m->m_next = n; + return; + } + /* splat the data from one into the other */ + bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len, + (u_int)n->m_len); + m->m_len += n->m_len; + n = m_free(n); + } +} + + +u_int +m_length(struct mbuf *m0, struct mbuf **last) +{ + struct mbuf *m; + u_int len; + + len = 0; + for (m = m0; m != NULL; m = m->m_next) { + len += m->m_len; + if (m->m_next == NULL) + break; + } + if (last != NULL) + *last = m; + return (len); +} + + +u_int +m_fixhdr(struct mbuf *m0) +{ + u_int len; + + len = m_length(m0, NULL); + m0->m_pkthdr.len = len; + return (len); +} + + +static int +m_tag_copy_chain(struct mbuf *to, struct mbuf *from, int how) +{ + return 1; +} + + +/* + * Duplicate "from"'s mbuf pkthdr in "to". + * "from" must have M_PKTHDR set, and "to" must be empty. + * In particular, this does a deep copy of the packet tags. + */ +static int +m_dup_pkthdr(struct mbuf *to, struct mbuf *from, int how) +{ + MBUF_CHECKSLEEP(how); + /* to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT); */ + to->m_flags = (to->m_flags & M_EXT); + if ((to->m_flags & M_EXT) == 0) + to->m_data = to->m_pktdat; + to->m_pkthdr = from->m_pkthdr; + /* SLIST_INIT(&to->m_pkthdr.tags); */ + return (m_tag_copy_chain(to, from, MBTOM(how))); +} + + +/* + * Defragment a mbuf chain, returning the shortest possible + * chain of mbufs and clusters. If allocation fails and + * this cannot be completed, NULL will be returned, but + * the passed in chain will be unchanged. Upon success, + * the original chain will be freed, and the new chain + * will be returned. + * + * If a non-packet header is passed in, the original + * mbuf (chain?) will be returned unharmed. + */ +struct mbuf * +m_defrag(struct mbuf *m0, int how) +{ + struct mbuf *m_new = NULL, *m_final = NULL; + int progress = 0, length; + + MBUF_CHECKSLEEP(how); + if (!(m0->m_flags & M_PKTHDR)) + return (m0); + + m_fixhdr(m0); /* Needed sanity check */ + + if (m0->m_pkthdr.len > MHLEN) + m_final = m_getcl(how, MT_DATA, M_PKTHDR); + else + m_final = m_gethdr(how, MT_DATA); + + if (m_final == NULL) + goto nospace; + + if (m_dup_pkthdr(m_final, m0, how) == 0) + goto nospace; + + m_new = m_final; + + while (progress < m0->m_pkthdr.len) { + length = m0->m_pkthdr.len - progress; + if (length > MCLBYTES) + length = MCLBYTES; + + if (m_new == NULL) { + if (length > MLEN) + m_new = m_getcl(how, MT_DATA, 0); + else + m_new = m_get(how, MT_DATA); + if (m_new == NULL) + goto nospace; + } + + m_copydata(m0, progress, length, mtod(m_new, caddr_t)); + progress += length; + m_new->m_len = length; + if (m_new != m_final) + m_cat(m_final, m_new); + m_new = NULL; + } + + m_freem(m0); + m0 = m_final; + return (m0); +nospace: + if (m_final) + m_freem(m_final); + return (NULL); } status_t init_mbufs() { - sMBufCache = create_object_cache("mbufs", sizeof(struct mbuf), 8, NULL, - NULL, NULL); + sMBufCache = create_object_cache("mbufs", MSIZE, 8, NULL, NULL, NULL); if (sMBufCache == NULL) return B_NO_MEMORY; - sChunkCache = create_object_cache("mbuf chunks", CHUNK_SIZE, 0, NULL, NULL, + sChunkCache = create_object_cache("mbuf chunks", MCLBYTES, 0, NULL, NULL, NULL); if (sChunkCache == NULL) { delete_object_cache(sMBufCache); diff --git a/src/libs/compat/freebsd_network/mii.c b/src/libs/compat/freebsd_network/mii.c new file mode 100644 index 0000000000..b0e376c037 --- /dev/null +++ b/src/libs/compat/freebsd_network/mii.c @@ -0,0 +1,40 @@ +/* + * Copyright 2007, Hugo Santos. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Hugo Santos, hugosantos@gmail.com + */ + +#include "device.h" + +#include + +#include +#include + + +int +mii_phy_probe(device_t dev, device_t *miiDev, ifm_change_cb_t change, + ifm_stat_cb_t stat) +{ + return -1; +} + + +void +mii_tick(struct mii_data *data) +{ +} + +int +mii_mediachg(struct mii_data *data) +{ + return -1; +} + + +void +mii_pollstat(struct mii_data *data) +{ +} diff --git a/src/libs/compat/freebsd_network/mutex.c b/src/libs/compat/freebsd_network/mutex.c index b03a6f645a..300d961016 100644 --- a/src/libs/compat/freebsd_network/mutex.c +++ b/src/libs/compat/freebsd_network/mutex.c @@ -17,7 +17,7 @@ void uninit_mutexes(void); // these methods are bit unfriendly, a bit too much panic() around -struct mutex Giant; +struct mtx Giant; void