freebsd compat. layer: added swi taskqueue and a couple more methods that if_xl needs. also marked some as unimplemented so its clearer what is left to be done.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21080 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -326,6 +326,21 @@ bus_generic_resume(device_t dev)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
bus_generic_print_child(device_t dev, device_t child)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bus_generic_driver_added(device_t dev, driver_t *driver)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
|
||||
#define DEBUG_BUS_SPACE_RW
|
||||
|
||||
#ifdef DEBUG_BUS_SPACE_RW
|
||||
|
||||
@@ -225,6 +225,15 @@ device_get_softc(device_t dev)
|
||||
int
|
||||
device_delete_child(device_t dev, device_t child)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
device_is_attached(device_t dev)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,9 @@ void device_set_desc_copy(device_t dev, const char *desc);
|
||||
|
||||
device_t device_add_child(device_t dev, const char *name, int unit);
|
||||
int device_delete_child(device_t dev, device_t child);
|
||||
int device_is_attached(device_t dev);
|
||||
int bus_generic_print_child(device_t dev, device_t child);
|
||||
void bus_generic_driver_added(device_t dev, driver_t *driver);
|
||||
|
||||
static inline struct sysctl_ctx_list *
|
||||
device_get_sysctl_ctx(device_t dev)
|
||||
|
||||
@@ -90,6 +90,7 @@ extern int __haiku_driver_requirements;
|
||||
enum {
|
||||
FBSD_TASKQUEUES = 1 << 0,
|
||||
FBSD_FAST_TASKQUEUE = 1 << 1,
|
||||
FBSD_SWI_TASKQUEUE = 1 << 2,
|
||||
};
|
||||
|
||||
#define HAIKU_DRIVER_REQUIREMENTS(flags) \
|
||||
|
||||
@@ -24,6 +24,8 @@ int taskqueue_enqueue(struct taskqueue *tq, struct task *task);
|
||||
void taskqueue_thread_enqueue(void *context);
|
||||
|
||||
extern struct taskqueue *taskqueue_fast;
|
||||
extern struct taskqueue *taskqueue_swi;
|
||||
|
||||
int taskqueue_enqueue_fast(struct taskqueue *queue, struct task *task);
|
||||
struct taskqueue *taskqueue_create_fast(const char *name, int mflags,
|
||||
taskqueue_enqueue_fn enqueue, void *context);
|
||||
|
||||
@@ -190,380 +190,6 @@ m_free(struct mbuf *m)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
m_adj(struct mbuf *mp, int req_len)
|
||||
{
|
||||
int len = req_len;
|
||||
struct mbuf *m;
|
||||
int count;
|
||||
|
||||
if ((m = mp) == NULL)
|
||||
return;
|
||||
if (len >= 0) {
|
||||
/*
|
||||
* Trim from head.
|
||||
*/
|
||||
while (m != NULL && len > 0) {
|
||||
if (m->m_len <= len) {
|
||||
len -= m->m_len;
|
||||
m->m_len = 0;
|
||||
m = m->m_next;
|
||||
} else {
|
||||
m->m_len -= len;
|
||||
m->m_data += len;
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
m = mp;
|
||||
if (mp->m_flags & M_PKTHDR)
|
||||
m->m_pkthdr.len -= (req_len - len);
|
||||
} else {
|
||||
/*
|
||||
* Trim from tail. Scan the mbuf chain,
|
||||
* calculating its length and finding the last mbuf.
|
||||
* If the adjustment only affects this mbuf, then just
|
||||
* adjust and return. Otherwise, rescan and truncate
|
||||
* after the remaining size.
|
||||
*/
|
||||
len = -len;
|
||||
count = 0;
|
||||
for (;;) {
|
||||
count += m->m_len;
|
||||
if (m->m_next == (struct mbuf *)0)
|
||||
break;
|
||||
m = m->m_next;
|
||||
}
|
||||
if (m->m_len >= len) {
|
||||
m->m_len -= len;
|
||||
if (mp->m_flags & M_PKTHDR)
|
||||
mp->m_pkthdr.len -= len;
|
||||
return;
|
||||
}
|
||||
count -= len;
|
||||
if (count < 0)
|
||||
count = 0;
|
||||
/*
|
||||
* Correct length for chain is "count".
|
||||
* Find the mbuf with last data, adjust its length,
|
||||
* and toss data from remaining mbufs on chain.
|
||||
*/
|
||||
m = mp;
|
||||
if (m->m_flags & M_PKTHDR)
|
||||
m->m_pkthdr.len = count;
|
||||
for (; m; m = m->m_next) {
|
||||
if (m->m_len >= count) {
|
||||
m->m_len = count;
|
||||
if (m->m_next != NULL) {
|
||||
m_freem(m->m_next);
|
||||
m->m_next = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
count -= m->m_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Rearange an mbuf chain so that len bytes are contiguous
|
||||
* and in the data area of an mbuf (so that mtod and dtom
|
||||
* will work for a structure of size len). Returns the resulting
|
||||
* mbuf chain on success, frees it and returns null on failure.
|
||||
* If there is room, it will add up to max_protohdr-len extra bytes to the
|
||||
* contiguous region in an attempt to avoid being called next time.
|
||||
*/
|
||||
struct mbuf *
|
||||
m_pullup(struct mbuf *n, int len)
|
||||
{
|
||||
struct mbuf *m;
|
||||
int count;
|
||||
int space;
|
||||
|
||||
/*
|
||||
* If first mbuf has no cluster, and has room for len bytes
|
||||
* without shifting current data, pullup into it,
|
||||
* otherwise allocate a new mbuf to prepend to the chain.
|
||||
*/
|
||||
if ((n->m_flags & M_EXT) == 0 &&
|
||||
n->m_data + len < &n->m_dat[MLEN] && n->m_next) {
|
||||
if (n->m_len >= len)
|
||||
return (n);
|
||||
m = n;
|
||||
n = n->m_next;
|
||||
len -= m->m_len;
|
||||
} else {
|
||||
if (len > MHLEN)
|
||||
goto bad;
|
||||
MGET(m, M_DONTWAIT, n->m_type);
|
||||
if (m == NULL)
|
||||
goto bad;
|
||||
m->m_len = 0;
|
||||
if (n->m_flags & M_PKTHDR)
|
||||
M_MOVE_PKTHDR(m, n);
|
||||
}
|
||||
space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
|
||||
do {
|
||||
count = min(min(max(len, max_protohdr), space), n->m_len);
|
||||
bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
|
||||
(u_int)count);
|
||||
len -= count;
|
||||
m->m_len += count;
|
||||
n->m_len -= count;
|
||||
space -= count;
|
||||
if (n->m_len)
|
||||
n->m_data += count;
|
||||
else
|
||||
n = m_free(n);
|
||||
} while (len > 0 && n);
|
||||
if (len > 0) {
|
||||
(void) m_free(m);
|
||||
goto bad;
|
||||
}
|
||||
m->m_next = n;
|
||||
return (m);
|
||||
bad:
|
||||
m_freem(n);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Lesser-used path for M_PREPEND:
|
||||
* allocate new mbuf to prepend to chain,
|
||||
* copy junk along.
|
||||
*/
|
||||
struct mbuf *
|
||||
m_prepend(struct mbuf *m, int len, int how)
|
||||
{
|
||||
struct mbuf *mn;
|
||||
|
||||
if (m->m_flags & M_PKTHDR)
|
||||
MGETHDR(mn, how, m->m_type);
|
||||
else
|
||||
MGET(mn, how, m->m_type);
|
||||
if (mn == NULL) {
|
||||
m_freem(m);
|
||||
return (NULL);
|
||||
}
|
||||
if (m->m_flags & M_PKTHDR)
|
||||
M_MOVE_PKTHDR(mn, m);
|
||||
mn->m_next = m;
|
||||
m = mn;
|
||||
if (len < MHLEN)
|
||||
MH_ALIGN(m, len);
|
||||
m->m_len = len;
|
||||
return (m);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* "Move" mbuf pkthdr from "from" to "to".
|
||||
* "from" must have M_PKTHDR set, and "to" must be empty.
|
||||
*/
|
||||
void
|
||||
m_move_pkthdr(struct mbuf *to, struct mbuf *from)
|
||||
{
|
||||
#ifdef MAC
|
||||
/*
|
||||
* XXXMAC: It could be this should also occur for non-MAC?
|
||||
*/
|
||||
if (to->m_flags & M_PKTHDR)
|
||||
m_tag_delete_chain(to, NULL);
|
||||
#endif
|
||||
/* to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT); */
|
||||
/* we don't have M_COPYFLAGS -hugo */
|
||||
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; /* especially tags */
|
||||
/* we don't have tags -hugo */
|
||||
#if 0
|
||||
SLIST_INIT(&from->m_pkthdr.tags); /* purge tags from src */
|
||||
#endif
|
||||
from->m_flags &= ~M_PKTHDR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
init_mbufs()
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@ int
|
||||
mii_phy_probe(device_t dev, device_t *miiDev, ifm_change_cb_t change,
|
||||
ifm_stat_cb_t stat)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -30,11 +31,13 @@ mii_phy_probe(device_t dev, device_t *miiDev, ifm_change_cb_t change,
|
||||
void
|
||||
mii_tick(struct mii_data *data)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
int
|
||||
mii_mediachg(struct mii_data *data)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -42,4 +45,5 @@ mii_mediachg(struct mii_data *data)
|
||||
void
|
||||
mii_pollstat(struct mii_data *data)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ struct taskqueue {
|
||||
|
||||
|
||||
struct taskqueue *taskqueue_fast = NULL;
|
||||
struct taskqueue *taskqueue_swi = NULL;
|
||||
|
||||
|
||||
static struct taskqueue *
|
||||
@@ -296,26 +297,54 @@ task_init(struct task *t, int prio, task_handler_t handler, void *context)
|
||||
status_t
|
||||
init_taskqueues()
|
||||
{
|
||||
status_t status = B_NO_MEMORY;
|
||||
|
||||
if (HAIKU_DRIVER_REQUIRES(FBSD_FAST_TASKQUEUE)) {
|
||||
taskqueue_fast = taskqueue_create_fast("fast taskq", 0,
|
||||
taskqueue_thread_enqueue, NULL);
|
||||
taskqueue_thread_enqueue, &taskqueue_fast);
|
||||
if (taskqueue_fast == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
if (taskqueue_start_threads(&taskqueue_fast, 1, B_REAL_TIME_PRIORITY,
|
||||
"fast taskq") < 0) {
|
||||
taskqueue_free(taskqueue_fast);
|
||||
return B_ERROR;
|
||||
status = taskqueue_start_threads(&taskqueue_fast, 1,
|
||||
B_REAL_TIME_PRIORITY, "fast taskq");
|
||||
if (status < B_OK)
|
||||
goto err_1;
|
||||
}
|
||||
|
||||
if (HAIKU_DRIVER_REQUIRES(FBSD_SWI_TASKQUEUE)) {
|
||||
taskqueue_swi = taskqueue_create_fast("swi taskq", 0,
|
||||
taskqueue_thread_enqueue, &taskqueue_swi);
|
||||
if (taskqueue_swi == NULL) {
|
||||
status = B_NO_MEMORY;
|
||||
goto err_1;
|
||||
}
|
||||
|
||||
status = taskqueue_start_threads(&taskqueue_swi, 1,
|
||||
B_REAL_TIME_PRIORITY, "swi taskq");
|
||||
if (status < B_OK)
|
||||
goto err_2;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
|
||||
err_2:
|
||||
if (taskqueue_swi)
|
||||
taskqueue_free(taskqueue_swi);
|
||||
|
||||
err_1:
|
||||
if (taskqueue_fast)
|
||||
taskqueue_free(taskqueue_fast);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uninit_taskqueues()
|
||||
{
|
||||
if (HAIKU_DRIVER_REQUIRES(FBSD_SWI_TASKQUEUE))
|
||||
taskqueue_free(taskqueue_swi);
|
||||
|
||||
if (HAIKU_DRIVER_REQUIRES(FBSD_FAST_TASKQUEUE))
|
||||
taskqueue_free(taskqueue_fast);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user