freebsd compat. layer: added mii placeholders, callout implementation.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21006 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos 2007-05-03 21:18:21 +00:00
parent 835ec57dc2
commit 6d043beb03
11 changed files with 476 additions and 100 deletions

View File

@ -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;

View File

@ -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
;

View File

@ -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 <compat/sys/callout.h>
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;
}

View File

@ -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},
{}
};

View File

@ -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 <net_stack.h>
#include <sys/mutex.h>
#include <sys/queue.h>
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

View File

@ -4,15 +4,15 @@
#include <sys/malloc.h>
#include <sys/param.h>
#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. */

View File

@ -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

View File

@ -15,6 +15,8 @@
#include <KernelExport.h>
#include <drivers/PCI.h>
#include <net_stack.h>
#include <compat/sys/kernel.h>
#include <compat/net/if.h>
#include <compat/net/if_var.h>
@ -45,6 +47,7 @@ enum {
};
extern struct net_stack_module_info *gStack;
extern pci_module_info *gPci;
#endif

View File

@ -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 <stdint.h>
#include <string.h>
#include <slab/Slab.h>
#include <compat/sys/mbuf.h>
#include <compat/sys/kernel.h>
#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);

View File

@ -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 <compat/sys/bus.h>
#include <compat/net/if_media.h>
#include <compat/dev/mii/miivar.h>
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)
{
}

View File

@ -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