diff --git a/src/libs/compat/freebsd_network/Jamfile b/src/libs/compat/freebsd_network/Jamfile index ada8c37e3a..7629f56505 100644 --- a/src/libs/compat/freebsd_network/Jamfile +++ b/src/libs/compat/freebsd_network/Jamfile @@ -3,10 +3,13 @@ SubDir HAIKU_TOP src libs compat freebsd_network ; UsePrivateHeaders kernel net ; UseHeaders [ FDirName $(SUBDIR) ] : true ; -UseHeaders [ FDirName $(SUBDIR) headers ] : true ; +UseHeaders [ FDirName $(SUBDIR) compat ] : true ; SubDirCcFlags [ FDefines _KERNEL=1 ] ; Library libfreebsd_network.a : compat.c + device.c + mbuf.c + mutex.c ; diff --git a/src/libs/compat/freebsd_network/compat.c b/src/libs/compat/freebsd_network/compat.c index 319b094f01..e3d6b05fe1 100644 --- a/src/libs/compat/freebsd_network/compat.c +++ b/src/libs/compat/freebsd_network/compat.c @@ -8,9 +8,11 @@ * Some of this code is based on previous work by Marcus Overhagen. */ +#include "device.h" + +#include #include -#include #include #include @@ -21,28 +23,54 @@ status_t init_compat_layer(void); pci_module_info *gPci; -struct device { - int devId; - pci_info * pciInfo; - - uint8 pciBus; - uint8 pciDev; - uint8 pciFunc; -}; - uint32_t pci_read_config(device_t dev, int offset, int size) { - return gPci->read_pci_config(dev->pciBus, dev->pciDev, dev->pciFunc, - offset, size); + return gPci->read_pci_config(dev->pciInfo->bus, dev->pciInfo->device, + dev->pciInfo->function, offset, size); } void pci_write_config(device_t dev, int offset, uint32_t value, int size) { - gPci->write_pci_config(dev->pciBus, dev->pciDev, dev->pciFunc, offset, - size, value); + gPci->write_pci_config(dev->pciInfo->bus, dev->pciInfo->device, + dev->pciInfo->function, offset, size, value); +} + + +uint16_t +pci_get_vendor(device_t dev) +{ + return pci_read_config(dev, PCI_vendor_id, 2); +} + + +uint16_t +pci_get_device(device_t dev) +{ + return pci_read_config(dev, PCI_device_id, 2); +} + + +uint8_t +pci_get_revid(device_t dev) +{ + return pci_read_config(dev, PCI_revision, 1); +} + + +int +device_printf(device_t dev, const char *format, ...) +{ + char buf[256]; + va_list vl; + va_start(vl, format); + vsnprintf(buf, sizeof(buf), format, vl); + va_end(vl); + + dprintf("[...] %s", buf); + return 0; } diff --git a/src/libs/compat/freebsd_network/device.c b/src/libs/compat/freebsd_network/device.c new file mode 100644 index 0000000000..060c92cc71 --- /dev/null +++ b/src/libs/compat/freebsd_network/device.c @@ -0,0 +1,96 @@ +/* + * Copyright 2007, Hugo Santos. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Hugo Santos, hugosantos@gmail.com + * + * Some of this code is based on previous work by Marcus Overhagen. + */ + +#include "device.h" + +#include + +#include +#include + + +static status_t +compat_open(const char *name, uint32 flags, void **cookie) +{ + return B_ERROR; +} + + +static status_t +compat_close(void *cookie) +{ + device_t dev = cookie; + return B_ERROR; +} + + +static status_t +compat_free(void *cookie) +{ + device_t dev = cookie; + free(dev); + return B_ERROR; +} + + +static status_t +compat_read(void *cookie, off_t position, void *buf, size_t *numBytes) +{ + uint32 semFlags = B_CAN_INTERRUPT; + device_t dev = cookie; + status_t status; + struct mbuf *mb; + size_t len; + + if (atomic_or(&dev->flags, 0) & DEVICE_CLOSED) + return B_INTERRUPTED; + + if (atomic_or(&dev->flags, 0) & DEVICE_NON_BLOCK) + semFlags |= B_RELATIVE_TIMEOUT; + + + do { + status = acquire_sem_etc(dev->receive_sem, 1, semFlags, 0); + if (atomic_or(&dev->flags, 0) & DEVICE_CLOSED) + return B_INTERRUPTED; + + if (status == B_WOULD_BLOCK) { + *numBytes = 0; + return B_OK; + } else if (status < B_OK) + return status; + + IF_DEQUEUE(&dev->receive_queue, mb); + } while (mb == NULL); + + len = min_c(max_c(mb->m_len, 0), *numBytes); + + // TODO we need something that cna join various chunks + memcpy(buf, mtod(mb, const void *), len); + *numBytes = len; + + m_freem(mb); + return B_OK; +} + + +static status_t +compat_write(void *cookie, off_t position, const void *buffer, + size_t *numBytes) +{ + return B_ERROR; +} + + +static status_t +compat_control(void *cookie, uint32 op, void *arg, size_t len) +{ + return B_ERROR; +} diff --git a/src/libs/compat/freebsd_network/device.h b/src/libs/compat/freebsd_network/device.h new file mode 100644 index 0000000000..af4b3823ae --- /dev/null +++ b/src/libs/compat/freebsd_network/device.h @@ -0,0 +1,45 @@ +/* + * Copyright 2007, Hugo Santos. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Hugo Santos, hugosantos@gmail.com + * + * Some of this code is based on previous work by Marcus Overhagen. + */ +#ifndef _DEVICE_H_ +#define _DEVICE_H_ + +#include + +#include +#include + +#include +#include +#include + +struct ifnet; + +struct device { + int devId; + pci_info * pciInfo; + + int32 flags; + + struct ifqueue receive_queue; + sem_id receive_sem; + + struct ifnet * ifp; +}; + + +enum { + DEVICE_CLOSED = 1 << 0, + DEVICE_NON_BLOCK = 1 << 1, +}; + + +extern pci_module_info *gPci; + +#endif diff --git a/src/libs/compat/freebsd_network/mbuf.c b/src/libs/compat/freebsd_network/mbuf.c new file mode 100644 index 0000000000..8343c721ae --- /dev/null +++ b/src/libs/compat/freebsd_network/mbuf.c @@ -0,0 +1,68 @@ +/* + * Copyright 2007, Hugo Santos. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Hugo Santos, hugosantos@gmail.com + * + * Some of this code is based on previous work by Marcus Overhagen. + */ + +#include +#include + +#include + + +status_t init_mbufs(void); +void uninit_mbufs(void); + + +#define CHUNK_SIZE 2048 + +static object_cache *sMBufCache; +static object_cache *sChunkCache; + + +void +m_freem(struct mbuf *mp) +{ + struct mbuf *next = mp; + + 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); +} + + +status_t +init_mbufs() +{ + sMBufCache = create_object_cache("mbufs", sizeof(struct mbuf), 8, NULL, + NULL, NULL); + if (sMBufCache == NULL) + return B_NO_MEMORY; + + sChunkCache = create_object_cache("mbuf chunks", CHUNK_SIZE, 0, NULL, NULL, + NULL); + if (sChunkCache == NULL) { + delete_object_cache(sMBufCache); + return B_NO_MEMORY; + } + + return B_OK; +} + + +void +uninit_mbufs() +{ + delete_object_cache(sMBufCache); + delete_object_cache(sChunkCache); +} + diff --git a/src/libs/compat/freebsd_network/mutex.c b/src/libs/compat/freebsd_network/mutex.c new file mode 100644 index 0000000000..b03a6f645a --- /dev/null +++ b/src/libs/compat/freebsd_network/mutex.c @@ -0,0 +1,62 @@ +/* + * Copyright 2007, Hugo Santos. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Hugo Santos, hugosantos@gmail.com + */ + +#include + +#include + + +status_t init_mutexes(void); +void uninit_mutexes(void); + + +// these methods are bit unfriendly, a bit too much panic() around + +struct mutex Giant; + + +void +mtx_init(struct mtx *m, const char *name, const char *type, int opts) +{ + if (opts == MTX_DEF) { + if (mutex_init(&m->u.mutex, name) < B_OK) + panic("Panic! Dance like it's 1979, we ran out of semaphores"); + } else if (opts == MTX_RECURSE) { + if (recursive_lock_init(&m->u.recursive, name) < B_OK) + panic("Hell just froze as someone was trying to init a recursive mutex."); + } else + panic("Uh-oh, someone is pressing the wrong buttons"); + + m->type = opts; +} + + +void +mtx_destroy(struct mtx *m) +{ + if (m->type == MTX_DEF) { + mutex_destroy(&m->u.mutex); + } else if (m->type == MTX_RECURSE) { + recursive_lock_destroy(&m->u.recursive); + } else + panic("Uh-oh, someone is pressing the wrong buttons"); +} + + +status_t +init_mutexes() +{ + return B_ERROR; +} + + +void +uninit_mutexes() +{ +} +