freebsd compat. layer: a few more definitions, preparing for a DMA-using driver.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21067 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos 2007-05-08 13:10:02 +00:00
parent d00539e3ba
commit 25d42ceb99
24 changed files with 543 additions and 33 deletions

View File

@ -18,4 +18,5 @@ Library libfreebsd_network.a :
mbuf.c
mii.c
mutex.c
taskqueue.c
;

View File

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

View File

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

View File

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

View File

@ -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_ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,35 @@
#ifndef _FBSD_COMPAT_SYS_TASKQUEUE_H_
#define _FBSD_COMPAT_SYS_TASKQUEUE_H_
#include <sys/kernel.h>
#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

View File

@ -0,0 +1,8 @@
#ifndef _FBSD_COMPAT_SYS_TYPES_H_
#define _FBSD_COMPAT_SYS_TYPES_H_
#include <posix/sys/types.h>
typedef int boolean_t;
#endif

View File

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

View File

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

View File

@ -20,15 +20,13 @@
#include <compat/sys/kernel.h>
#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()
{

View File

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