diff --git a/src/libs/compat/freebsd_network/Jamfile b/src/libs/compat/freebsd_network/Jamfile index 8bf6fc7698..4dc9b1a43a 100644 --- a/src/libs/compat/freebsd_network/Jamfile +++ b/src/libs/compat/freebsd_network/Jamfile @@ -18,4 +18,5 @@ Library libfreebsd_network.a : mbuf.c mii.c mutex.c + taskqueue.c ; diff --git a/src/libs/compat/freebsd_network/bus.c b/src/libs/compat/freebsd_network/bus.c index f08249eb9a..00d6942049 100644 --- a/src/libs/compat/freebsd_network/bus.c +++ b/src/libs/compat/freebsd_network/bus.c @@ -186,6 +186,18 @@ intr_wrapper(void *data) } +static int32 +intr_fast_wrapper(void *data) +{ + struct internal_intr *intr = data; + + intr->handler(intr->arg); + + /* no way to know, so let other devices get it as well */ + return B_UNHANDLED_INTERRUPT; +} + + static int32 intr_handler(void *data) { @@ -209,9 +221,12 @@ intr_handler(void *data) static void free_internal_intr(struct internal_intr *intr) { - status_t status; - delete_sem(intr->sem); - wait_for_thread(intr->thread, &status); + if (intr->sem >= B_OK) { + status_t status; + delete_sem(intr->sem); + wait_for_thread(intr->thread, &status); + } + free(intr); } @@ -235,25 +250,35 @@ bus_setup_intr(device_t dev, struct resource *res, int flags, intr->arg = arg; intr->irq = res->handle; - snprintf(semName, sizeof(semName), "%s intr", dev->dev_name); + if (flags & INTR_FAST) { + intr->sem = -1; + intr->thread = -1; - intr->sem = create_sem(0, semName); - if (intr->sem < B_OK) { - free(intr); - return B_NO_MEMORY; + status = install_io_interrupt_handler(intr->irq, + intr_fast_wrapper, intr, 0); + } else { + snprintf(semName, sizeof(semName), "%s intr", dev->dev_name); + + intr->sem = create_sem(0, semName); + if (intr->sem < B_OK) { + free(intr); + return B_NO_MEMORY; + } + + snprintf(semName, sizeof(semName), "%s intr handler", dev->dev_name); + + intr->thread = spawn_kernel_thread(intr_handler, semName, + B_REAL_TIME_DISPLAY_PRIORITY, intr); + if (intr->thread < B_OK) { + delete_sem(intr->sem); + free(intr); + return B_NO_MEMORY; + } + + status = install_io_interrupt_handler(intr->irq, + intr_wrapper, intr, 0); } - snprintf(semName, sizeof(semName), "%s intr handler", dev->dev_name); - - intr->thread = spawn_kernel_thread(intr_handler, semName, - B_REAL_TIME_DISPLAY_PRIORITY, intr); - if (intr->thread < B_OK) { - delete_sem(intr->sem); - free(intr); - return B_NO_MEMORY; - } - - status = install_io_interrupt_handler(intr->irq, intr_wrapper, intr, 0); if (status < B_OK) { free_internal_intr(intr); return status; @@ -280,8 +305,23 @@ bus_teardown_intr(device_t dev, struct resource *res, void *arg) int bus_generic_detach(device_t dev) { - /* TODO */ + UNIMPLEMENTED(); + return B_ERROR; +} + +int +bus_generic_suspend(device_t dev) +{ + UNIMPLEMENTED(); + return B_ERROR; +} + + +int +bus_generic_resume(device_t dev) +{ + UNIMPLEMENTED(); return B_ERROR; } diff --git a/src/libs/compat/freebsd_network/compat.c b/src/libs/compat/freebsd_network/compat.c index c7674459a6..af2ed1ef7d 100644 --- a/src/libs/compat/freebsd_network/compat.c +++ b/src/libs/compat/freebsd_network/compat.c @@ -184,6 +184,14 @@ device_set_desc(device_t dev, const char *desc) } +void +device_set_desc_copy(device_t dev, const char *desc) +{ + dev->description = strdup(desc); + dev->flags |= DEVICE_DESC_ALLOCED; +} + + const char * device_get_name(device_t dev) { @@ -297,7 +305,7 @@ _kernel_contigmalloc(const char *file, int line, size_t size, int flags, if (area < 0) return NULL; - driver_printf("(%s) addr = %p, area = %d, size = %lu\n", + driver_printf("(%s) addr = %p, area = %ld, size = %lu\n", name, addr, area, size); return addr; diff --git a/src/libs/compat/freebsd_network/compat/dev/pci/pcireg.h b/src/libs/compat/freebsd_network/compat/dev/pci/pcireg.h index d24511b7a9..2a4c374b5a 100644 --- a/src/libs/compat/freebsd_network/compat/dev/pci/pcireg.h +++ b/src/libs/compat/freebsd_network/compat/dev/pci/pcireg.h @@ -7,11 +7,13 @@ #define PCIR_SUBVEND_0 0x2c #define PCIR_SUBDEV_0 0x2e -#define PCIM_CMD_PORTEN 0x0001 -#define PCIM_CMD_MEMEN 0x0002 -#define PCIM_CMD_MWRICEN 0x0010 +#define PCIM_CMD_PORTEN 0x0001 +#define PCIM_CMD_MEMEN 0x0002 +#define PCIM_CMD_BUSMASTEREN 0x0004 +#define PCIM_CMD_MWRICEN 0x0010 #define PCIR_BARS 0x10 #define PCIR_BAR(x) (PCIR_BARS + (x) * 4) +#define PCIR_CIS 0x28 #endif diff --git a/src/libs/compat/freebsd_network/compat/machine/in_cksum.h b/src/libs/compat/freebsd_network/compat/machine/in_cksum.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/libs/compat/freebsd_network/compat/net/if_vlan_var.h b/src/libs/compat/freebsd_network/compat/net/if_vlan_var.h index 107885adfa..38216f5ec7 100644 --- a/src/libs/compat/freebsd_network/compat/net/if_vlan_var.h +++ b/src/libs/compat/freebsd_network/compat/net/if_vlan_var.h @@ -59,6 +59,11 @@ struct vlanreq { #define SIOCGETVLAN SIOCGIFGENERIC #ifdef _KERNEL +#if 1 +#define VLAN_INPUT_TAG_NEW(_ifp, _m, _t) do { } while (0) +#define VLAN_OUTPUT_TAG(_ifp, _m) NULL +#define VLAN_TAG_VALUE(_mt) 0 +#else /* * Drivers that are capable of adding and removing the VLAN header * in hardware indicate they support this by marking IFCAP_VLAN_HWTAGGING @@ -141,6 +146,7 @@ struct vlanreq { #define VLAN_OUTPUT_TAG(_ifp, _m) \ ((_m)->m_flags & M_VLANTAG ? \ m_tag_locate((_m), MTAG_VLAN, MTAG_VLAN_TAG, NULL) : NULL) +#endif #endif /* _KERNEL */ #endif /* _NET_IF_VLAN_VAR_H_ */ diff --git a/src/libs/compat/freebsd_network/compat/netinet/if_ether.h b/src/libs/compat/freebsd_network/compat/netinet/if_ether.h new file mode 100644 index 0000000000..f3affc16c0 --- /dev/null +++ b/src/libs/compat/freebsd_network/compat/netinet/if_ether.h @@ -0,0 +1,8 @@ +#ifndef _FBSD_COMPAT_NETINET_IF_ETHER_H_ +#define _FBSD_COMPAT_NETINET_IF_ETHER_H_ + +/* Haiku does it's own ARP management */ + +#define arp_ifinit(ifp, ifa) + +#endif diff --git a/src/libs/compat/freebsd_network/compat/netinet/in_systm.h b/src/libs/compat/freebsd_network/compat/netinet/in_systm.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/libs/compat/freebsd_network/compat/sys/bus.h b/src/libs/compat/freebsd_network/compat/sys/bus.h index aff36e231a..a755d9e019 100644 --- a/src/libs/compat/freebsd_network/compat/sys/bus.h +++ b/src/libs/compat/freebsd_network/compat/sys/bus.h @@ -54,10 +54,13 @@ bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t handle, enum intr_type { INTR_TYPE_NET = 4, + INTR_FAST = 128, INTR_MPSAFE = 512, }; int bus_generic_detach(device_t dev); +int bus_generic_suspend(device_t dev); +int bus_generic_resume(device_t dev); typedef void (*driver_intr_t)(void *); @@ -86,6 +89,7 @@ int device_get_unit(device_t dev); void *device_get_softc(device_t dev); int device_printf(device_t dev, const char *, ...) __printflike(2, 3); void device_set_desc(device_t dev, const char *desc); +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); diff --git a/src/libs/compat/freebsd_network/compat/sys/haiku-module.h b/src/libs/compat/freebsd_network/compat/sys/haiku-module.h index cc9800366f..b9b8efff3a 100644 --- a/src/libs/compat/freebsd_network/compat/sys/haiku-module.h +++ b/src/libs/compat/freebsd_network/compat/sys/haiku-module.h @@ -79,6 +79,12 @@ extern int __haiku_disable_interrupts(device_t dev); #define HAIKU_CHECK_DISABLE_INTERRUPTS __haiku_disable_interrupts +#define NO_HAIKU_CHECK_DISABLE_INTERRUPTS() \ + int HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) { \ + panic("should never be called."); \ + return -1; \ + } + #define HAIKU_INTR_REGISTER_ENTER(status) do { \ status = disable_interrupts(); \ acquire_spinlock(&__haiku_intr_spinlock); \ diff --git a/src/libs/compat/freebsd_network/compat/sys/kernel.h b/src/libs/compat/freebsd_network/compat/sys/kernel.h index 715ea1086a..3409d7fdf1 100644 --- a/src/libs/compat/freebsd_network/compat/sys/kernel.h +++ b/src/libs/compat/freebsd_network/compat/sys/kernel.h @@ -28,6 +28,8 @@ struct __system_init { #define SYSINIT(uniquifier, subsystem, order, func, ident) \ struct __system_init __init_##uniquifier = { func } +#define TUNABLE_INT(path, var) + #define __packed __attribute__ ((packed)) #define __printflike(a, b) __attribute__ ((format (__printf__, a, b))) diff --git a/src/libs/compat/freebsd_network/compat/sys/kthread.h b/src/libs/compat/freebsd_network/compat/sys/kthread.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/libs/compat/freebsd_network/compat/sys/malloc.h b/src/libs/compat/freebsd_network/compat/sys/malloc.h index e5569a875e..c240b0c193 100644 --- a/src/libs/compat/freebsd_network/compat/sys/malloc.h +++ b/src/libs/compat/freebsd_network/compat/sys/malloc.h @@ -31,4 +31,9 @@ void _kernel_contigfree(void *addr, unsigned long size); #define kernel_contigfree(addr, size, base) \ _kernel_contigfree(addr, size) +#ifdef FBSD_DRIVER +#define malloc(size, tag, flags) kernel_malloc(size, tag, flags) +#define free(pointer, tag) kernel_free(pointer, tag) +#endif + #endif diff --git a/src/libs/compat/freebsd_network/compat/sys/mbuf.h b/src/libs/compat/freebsd_network/compat/sys/mbuf.h index 643080a828..5584e5fede 100644 --- a/src/libs/compat/freebsd_network/compat/sys/mbuf.h +++ b/src/libs/compat/freebsd_network/compat/sys/mbuf.h @@ -28,7 +28,7 @@ struct pkthdr { }; struct m_ext { - void * ext_buf; + caddr_t ext_buf; unsigned int ext_size; int ext_type; }; @@ -84,6 +84,7 @@ struct mbuf { #define CSUM_PSEUDO_HDR 0x0800 #define CSUM_DELAY_DATA (CSUM_TCP | CSUM_UDP) +#define M_MOVE_PKTHDR(to, from) m_move_pkthdr((to), (from)) #define MGET(m, how, type) ((m) = m_get((how), (type))) #define MGETHDR(m, how, type) ((m) = m_gethdr((how), (type))) #define MCLGET(m, how) m_clget((m), (how)) @@ -92,6 +93,10 @@ 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); +void m_adj(struct mbuf *m, int); +struct mbuf *m_pullup(struct mbuf *m, int len); +struct mbuf *m_prepend(struct mbuf *m, int, int); +void m_move_pkthdr(struct mbuf *, struct mbuf *); u_int m_length(struct mbuf *m, struct mbuf **last); u_int m_fixhdr(struct mbuf *m); @@ -104,11 +109,88 @@ void m_clget(struct mbuf *m, int how); #define mtod(m, type) (type)((m)->m_data) +#define m_tag_delete(mb, tag) \ + panic("m_tag_delete unsupported."); + /* Check if the supplied mbuf has a packet header, or else panic. */ #define M_ASSERTPKTHDR(m) \ KASSERT(m != NULL && m->m_flags & M_PKTHDR, \ ("%s: no mbuf packet header!", __func__)) +#define MBUF_CHECKSLEEP(how) do { } while (0) + + +/* + * Set the m_data pointer of a newly-allocated mbuf (m_get/MGET) to place + * an object of the specified size at the end of the mbuf, longword aligned. + */ +#define M_ALIGN(m, len) do { \ + (m)->m_data += (MLEN - (len)) & ~(sizeof(long) - 1); \ +} while (0) + +/* + * As above, for mbufs allocated with m_gethdr/MGETHDR + * or initialized by M_COPY_PKTHDR. + */ +#define MH_ALIGN(m, len) do { \ + (m)->m_data += (MHLEN - (len)) & ~(sizeof(long) - 1); \ +} while (0) + + +/* +#define MEXT_IS_REF(m) (((m)->m_ext.ref_cnt != NULL) \ + && (*((m)->m_ext.ref_cnt) > 1)) + */ +#define MEXT_IS_REF(m) 0 + +/* + * Evaluate TRUE if it's safe to write to the mbuf m's data region (this + * can be both the local data payload, or an external buffer area, + * depending on whether M_EXT is set). + */ + +/* +#define M_WRITABLE(m) (!((m)->m_flags & M_RDONLY) && (!((m)->m_flags \ + & M_EXT) || !MEXT_IS_REF(m))) + */ +#define M_WRITABLE(m) (!((m)->m_flags & M_EXT) || !MEXT_IS_REF(m)) + +/* + * Compute the amount of space available + * before the current start of data in an mbuf. + * + * The M_WRITABLE() is a temporary, conservative safety measure: the burden + * of checking writability of the mbuf data area rests solely with the caller. + */ +#define M_LEADINGSPACE(m) \ + ((m)->m_flags & M_EXT ? \ + (M_WRITABLE(m) ? (m)->m_data - (m)->m_ext.ext_buf : 0): \ + (m)->m_flags & M_PKTHDR ? (m)->m_data - (m)->m_pktdat : \ + (m)->m_data - (m)->m_dat) + +/* + * Arrange to prepend space of size plen to mbuf m. + * If a new mbuf must be allocated, how specifies whether to wait. + * If the allocation fails, the original mbuf chain is freed and m is + * set to NULL. + */ +#define M_PREPEND(m, plen, how) do { \ + struct mbuf **_mmp = &(m); \ + struct mbuf *_mm = *_mmp; \ + int _mplen = (plen); \ + int __mhow = (how); \ + \ + MBUF_CHECKSLEEP(how); \ + if (M_LEADINGSPACE(_mm) >= _mplen) { \ + _mm->m_data -= _mplen; \ + _mm->m_len += _mplen; \ + } else \ + _mm = m_prepend(_mm, _mplen, __mhow); \ + if (_mm != NULL && _mm->m_flags & M_PKTHDR) \ + _mm->m_pkthdr.len += _mplen; \ + *_mmp = _mm; \ +} while (0) + #endif #endif diff --git a/src/libs/compat/freebsd_network/compat/sys/mutex.h b/src/libs/compat/freebsd_network/compat/sys/mutex.h index d7be3d34ec..3a8f908de6 100644 --- a/src/libs/compat/freebsd_network/compat/sys/mutex.h +++ b/src/libs/compat/freebsd_network/compat/sys/mutex.h @@ -53,6 +53,9 @@ static inline int mtx_initialized(struct mtx *mtx) void mtx_init(struct mtx *m, const char *name, const char *type, int opts); void mtx_destroy(struct mtx *m); +#define NET_LOCK_GIANT() +#define NET_UNLOCK_GIANT() + extern struct mtx Giant; #endif diff --git a/src/libs/compat/freebsd_network/compat/sys/param.h b/src/libs/compat/freebsd_network/compat/sys/param.h index 10dfecf593..1816d57030 100644 --- a/src/libs/compat/freebsd_network/compat/sys/param.h +++ b/src/libs/compat/freebsd_network/compat/sys/param.h @@ -33,4 +33,6 @@ #define ALIGN_BYTES (sizeof(int) - 1) #define ALIGN(x) ((((unsigned)x) + ALIGN_BYTES) & ~ALIGN_BYTES) +#define roundup2(x, y) (((x) + ((y) - 1)) & (~((y) - 1))) + #endif diff --git a/src/libs/compat/freebsd_network/compat/sys/protosw.h b/src/libs/compat/freebsd_network/compat/sys/protosw.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/libs/compat/freebsd_network/compat/sys/taskqueue.h b/src/libs/compat/freebsd_network/compat/sys/taskqueue.h new file mode 100644 index 0000000000..2e39caaf1e --- /dev/null +++ b/src/libs/compat/freebsd_network/compat/sys/taskqueue.h @@ -0,0 +1,35 @@ +#ifndef _FBSD_COMPAT_SYS_TASKQUEUE_H_ +#define _FBSD_COMPAT_SYS_TASKQUEUE_H_ + +#include + +#define PI_NET 0 + +struct task; +struct taskqueue; + +typedef void (*task_handler_t)(void *context, int pending); + +#define TASK_INIT(taskp, prio, hand, arg) task_init(taskp, prio, hand, arg) + +typedef void (*taskqueue_enqueue_fn)(void *context); + +struct taskqueue *taskqueue_create(const char *name, int mflags, + taskqueue_enqueue_fn enqueue, void *context, void **); +int taskqueue_start_threads(struct taskqueue **tq, int count, int pri, + const char *name, ...) __printflike(4, 5); +void taskqueue_free(struct taskqueue *tq); +void taskqueue_drain(struct taskqueue *tq, struct task *task); + +int taskqueue_enqueue(struct taskqueue *tq, struct task *task); + +void taskqueue_thread_enqueue(void *context); + +extern struct taskqueue *taskqueue_fast; +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); + +void task_init(struct task *, int prio, task_handler_t handler, void *arg); + +#endif diff --git a/src/libs/compat/freebsd_network/compat/sys/types.h b/src/libs/compat/freebsd_network/compat/sys/types.h new file mode 100644 index 0000000000..a29de0df68 --- /dev/null +++ b/src/libs/compat/freebsd_network/compat/sys/types.h @@ -0,0 +1,8 @@ +#ifndef _FBSD_COMPAT_SYS_TYPES_H_ +#define _FBSD_COMPAT_SYS_TYPES_H_ + +#include + +typedef int boolean_t; + +#endif diff --git a/src/libs/compat/freebsd_network/compat/vm/pmap.h b/src/libs/compat/freebsd_network/compat/vm/pmap.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/libs/compat/freebsd_network/device.c b/src/libs/compat/freebsd_network/device.c index 60a1eeefcd..0ce1ee0eb6 100644 --- a/src/libs/compat/freebsd_network/device.c +++ b/src/libs/compat/freebsd_network/device.c @@ -75,6 +75,8 @@ free_device(device_t dev) delete_sem(dev->receive_sem); ifq_uninit(&dev->receive_queue); free(dev->softc); + if (dev->flags & DEVICE_DESC_ALLOCED) + free((char *)dev->description); free(dev); } @@ -131,7 +133,7 @@ compat_open(const char *name, uint32 flags, void **cookie) memset(&ifr, 0, sizeof(ifr)); ifr.ifr_media = IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0); - ifp->if_ioctl(ifp, SIOCSIFMEDIA, &ifr); + ifp->if_ioctl(ifp, SIOCSIFMEDIA, (caddr_t)&ifr); ifp->if_flags = IFF_UP; ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); @@ -300,7 +302,7 @@ compat_control(void *cookie, uint32 op, void *arg, size_t len) return EINVAL; memset(&mediareq, 0, sizeof(mediareq)); - status = ifp->if_ioctl(ifp, SIOCGIFMEDIA, &mediareq); + status = ifp->if_ioctl(ifp, SIOCGIFMEDIA, (caddr_t)&mediareq); if (status < B_OK) return status; @@ -358,10 +360,14 @@ _fbsd_init_hardware(driver_t *driver) return B_ERROR; } - memset(&fakeDevice, 0, sizeof(struct device)); for (i = 0; gPci->get_nth_pci_info(i, &fakeDevice.pci_info) == B_OK; i++) { - if (probe(&fakeDevice) >= 0) { + int result; + memset(&fakeDevice, 0, sizeof(struct device)); + result = probe(&fakeDevice); + if (fakeDevice.flags & DEVICE_DESC_ALLOCED) + free((char *)fakeDevice.description); + if (result >= 0) { dprintf("%s, found %s at %d\n", gDriverName, fakeDevice.description, i); put_module(B_PCI_MODULE_NAME); diff --git a/src/libs/compat/freebsd_network/device.h b/src/libs/compat/freebsd_network/device.h index 928de881c7..294acfd118 100644 --- a/src/libs/compat/freebsd_network/device.h +++ b/src/libs/compat/freebsd_network/device.h @@ -47,9 +47,13 @@ enum { DEVICE_OPEN = 1 << 0, DEVICE_CLOSED = 1 << 1, DEVICE_NON_BLOCK = 1 << 2, + DEVICE_DESC_ALLOCED = 1 << 3, }; +#define UNIMPLEMENTED() \ + panic("fbsd compat, unimplemented: " __FUNCTION__) + status_t init_mbufs(void); void uninit_mbufs(void); diff --git a/src/libs/compat/freebsd_network/mbuf.c b/src/libs/compat/freebsd_network/mbuf.c index be933eec47..fd39af41fe 100644 --- a/src/libs/compat/freebsd_network/mbuf.c +++ b/src/libs/compat/freebsd_network/mbuf.c @@ -20,15 +20,13 @@ #include -#define MBUF_CHECKSLEEP(how) do { } while (0) #define MBTOM(how) (how) - -#define CHUNK_SIZE 2048 - static object_cache *sMBufCache; static object_cache *sChunkCache; +static const int max_protohdr = 40 + 20; /* ip6 + tcp */ + static int m_to_oc_flags(int how) @@ -374,6 +372,201 @@ nospace: } +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() { diff --git a/src/libs/compat/freebsd_network/taskqueue.c b/src/libs/compat/freebsd_network/taskqueue.c new file mode 100644 index 0000000000..e75d0d14c1 --- /dev/null +++ b/src/libs/compat/freebsd_network/taskqueue.c @@ -0,0 +1,95 @@ +/* + * 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 + +struct task { + int priority; + task_handler_t handler; + void *argument; +}; + +struct taskqueue { +}; + +struct taskqueue *taskqueue_fast; + +struct taskqueue * +taskqueue_create(const char *name, int mflags, taskqueue_enqueue_fn enqueue, + void *context, void **unused) +{ + UNIMPLEMENTED(); + return NULL; +} + + +int +taskqueue_start_threads(struct taskqueue **tq, int count, int pri, + const char *name, ...) +{ + UNIMPLEMENTED(); + return -1; +} + + +void +taskqueue_free(struct taskqueue *tq) +{ + UNIMPLEMENTED(); +} + + +void +taskqueue_drain(struct taskqueue *tq, struct task *task) +{ + UNIMPLEMENTED(); +} + + +int +taskqueue_enqueue(struct taskqueue *tq, struct task *task) +{ + UNIMPLEMENTED(); + return -1; +} + + +void +taskqueue_thread_enqueue(void *context) +{ + UNIMPLEMENTED(); +} + + +int +taskqueue_enqueue_fast(struct taskqueue *queue, struct task *task) +{ + UNIMPLEMENTED(); + return -1; +} + + +struct taskqueue * +taskqueue_create_fast(const char *name, int mflags, + taskqueue_enqueue_fn enqueue, void *context) +{ + UNIMPLEMENTED(); + return NULL; +} + + +void +task_init(struct task *t, int prio, task_handler_t handler, void *context) +{ + t->priority = prio; + t->handler = handler; + t->argument = context; +} +