From 00212abe1c16a1cd1fdef6f0fddb2a67e48af934 Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Sat, 5 May 2007 00:47:20 +0000 Subject: [PATCH] freebsd compat. layer: a few more methods, preparing for pcnet git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21026 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/libs/compat/freebsd_network/compat.c | 46 +++++++- .../freebsd_network/compat/dev/pci/pcireg.h | 3 + .../freebsd_network/compat/dev/pci/pcivar.h | 1 + .../compat/freebsd_network/compat/net/if.h | 8 ++ .../freebsd_network/compat/net/if_var.h | 8 +- .../compat/freebsd_network/compat/sys/bus.h | 14 +++ .../freebsd_network/compat/sys/haiku-module.h | 17 ++- .../freebsd_network/compat/sys/kernel.h | 3 +- .../compat/freebsd_network/compat/sys/mbuf.h | 7 ++ .../compat/freebsd_network/compat/sys/mutex.h | 7 ++ .../compat/freebsd_network/compat/sys/param.h | 3 + src/libs/compat/freebsd_network/device.c | 19 +++- src/libs/compat/freebsd_network/if.c | 104 ++++++++++++++++++ src/libs/compat/freebsd_network/mbuf.c | 9 ++ 14 files changed, 241 insertions(+), 8 deletions(-) diff --git a/src/libs/compat/freebsd_network/compat.c b/src/libs/compat/freebsd_network/compat.c index 6dc4673a56..37d4e89a41 100644 --- a/src/libs/compat/freebsd_network/compat.c +++ b/src/libs/compat/freebsd_network/compat.c @@ -14,6 +14,7 @@ #include +#include #include #include @@ -91,6 +92,34 @@ pci_enable_busmaster(device_t dev) } +int +pci_enable_io(device_t dev, int space) +{ + /* adapted from FreeBSD's pci_enable_io_method */ + uint16_t command; + int bit = 0; + + switch (space) { + case SYS_RES_IOPORT: + bit = PCI_command_io; + break; + case SYS_RES_MEMORY: + bit = PCI_command_memory; + break; + default: + return EINVAL; + } + + pci_set_command_bit(dev, bit); + if (pci_read_config(dev, PCI_command, 2) & bit) + return 0; + + device_printf(dev, "pci_enable_io(%d) failed.\n", space); + + return ENXIO; +} + + int device_printf(device_t dev, const char *format, ...) { @@ -100,7 +129,7 @@ device_printf(device_t dev, const char *format, ...) vsnprintf(buf, sizeof(buf), format, vl); va_end(vl); - dprintf("[...] %s", buf); + dprintf("[%s...] %s", gDriverName, buf); return 0; } @@ -165,6 +194,21 @@ printf(const char *format, ...) } +int +ffs(int value) +{ + int i = 1; + + if (value == 0) + return 0; + + for (; !(value & 1); i++) + value >>= 1; + + return i; +} + + int resource_int_value(const char *name, int unit, const char *resname, int *result) { 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 c5044cd7ec..d24511b7a9 100644 --- a/src/libs/compat/freebsd_network/compat/dev/pci/pcireg.h +++ b/src/libs/compat/freebsd_network/compat/dev/pci/pcireg.h @@ -11,4 +11,7 @@ #define PCIM_CMD_MEMEN 0x0002 #define PCIM_CMD_MWRICEN 0x0010 +#define PCIR_BARS 0x10 +#define PCIR_BAR(x) (PCIR_BARS + (x) * 4) + #endif diff --git a/src/libs/compat/freebsd_network/compat/dev/pci/pcivar.h b/src/libs/compat/freebsd_network/compat/dev/pci/pcivar.h index 9c1fbb79e7..9c37c88c15 100644 --- a/src/libs/compat/freebsd_network/compat/dev/pci/pcivar.h +++ b/src/libs/compat/freebsd_network/compat/dev/pci/pcivar.h @@ -4,6 +4,7 @@ #include int pci_enable_busmaster(device_t dev); +int pci_enable_io(device_t dev, int reg); uint32_t pci_get_devid(device_t dev); void pci_set_intpin(device_t dev, uint8_t pin); diff --git a/src/libs/compat/freebsd_network/compat/net/if.h b/src/libs/compat/freebsd_network/compat/net/if.h index 6740ac83a7..4476c3bbce 100644 --- a/src/libs/compat/freebsd_network/compat/net/if.h +++ b/src/libs/compat/freebsd_network/compat/net/if.h @@ -28,6 +28,14 @@ #define IFF_LINK0 0x40000 +#define LINK_STATE_UNKNOWN 0 +#define LINK_STATE_DOWN 1 +#define LINK_STATE_UP 2 + + +#define IFQ_MAXLEN 50 + + struct ifmediareq { char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */ int ifm_current; /* current media options */ diff --git a/src/libs/compat/freebsd_network/compat/net/if_var.h b/src/libs/compat/freebsd_network/compat/net/if_var.h index 52338089d5..ba7b067fd6 100644 --- a/src/libs/compat/freebsd_network/compat/net/if_var.h +++ b/src/libs/compat/freebsd_network/compat/net/if_var.h @@ -86,6 +86,8 @@ struct carp_if; #include +#include /* for sockaddr_dl */ + TAILQ_HEAD(ifnethead, ifnet); /* we use TAILQs so that the order of */ TAILQ_HEAD(ifaddrhead, ifaddr); /* instantiation is preserved in the list */ TAILQ_HEAD(ifprefixhead, ifprefix); @@ -180,6 +182,9 @@ struct ifnet { struct task if_starttask; /* task for IFF_NEEDSGIANT */ struct task if_linktask; /* task for link change events */ struct mtx if_addr_mtx; /* mutex to protect address lists */ + + /* Haiku additions */ + struct sockaddr_dl if_lladdr; }; typedef void if_init_f_t(void *); @@ -657,8 +662,7 @@ typedef void if_com_free_t(void *com, u_char type); void if_register_com_alloc(u_char type, if_com_alloc_t *a, if_com_free_t *f); void if_deregister_com_alloc(u_char type); -#define IF_LLADDR(ifp) \ - LLADDR((struct sockaddr_dl *) ifaddr_byindex((ifp)->if_index)->ifa_addr) +#define IF_LLADDR(ifp) LLADDR(&ifp->if_lladdr) #ifdef DEVICE_POLLING enum poll_cmd { POLL_ONLY, POLL_AND_CHECK_STATUS }; diff --git a/src/libs/compat/freebsd_network/compat/sys/bus.h b/src/libs/compat/freebsd_network/compat/sys/bus.h index e124e73952..dfa0fcb0d8 100644 --- a/src/libs/compat/freebsd_network/compat/sys/bus.h +++ b/src/libs/compat/freebsd_network/compat/sys/bus.h @@ -87,6 +87,20 @@ bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t handle, } +#define BUS_SPACE_BARRIER_READ 1 +#define BUS_SPACE_BARRIER_WRITE 2 + +static inline void +bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t handle, + bus_size_t offset, bus_size_t len, int flags) +{ + if (flags & BUS_SPACE_BARRIER_READ) + __asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory"); + else + __asm__ __volatile__ ("" : : : "memory"); +} + + enum intr_type { INTR_TYPE_NET = 4, INTR_MPSAFE = 512, 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 bdfe50347c..5de2914227 100644 --- a/src/libs/compat/freebsd_network/compat/sys/haiku-module.h +++ b/src/libs/compat/freebsd_network/compat/sys/haiku-module.h @@ -15,6 +15,12 @@ typedef struct devclass *devclass_t; typedef int (*device_method_signature_t)(device_t dev); +typedef int device_probe_t(device_t dev); +typedef int device_attach_t(device_t dev); +typedef int device_detach_t(device_t dev); +typedef int device_resume_t(device_t dev); +typedef int device_suspend_t(device_t dev); + struct device_method { const char *name; device_method_signature_t method; @@ -22,7 +28,7 @@ struct device_method { typedef struct device_method device_method_t; -#define DEVMETHOD(name, func) { #name, (device_method_signature_t)func } +#define DEVMETHOD(name, func) { #name, (device_method_signature_t)&func } typedef struct { const char *name; @@ -30,6 +36,7 @@ typedef struct { size_t size; } driver_t; +#define BUS_PROBE_LOW_PRIORITY 10 #define BUS_PROBE_DEFAULT 20 #define DRIVER_MODULE_NAME(name, busname) \ @@ -39,15 +46,18 @@ status_t _fbsd_init_hardware(driver_t *); status_t _fbsd_init_driver(driver_t *); void _fbsd_uninit_driver(driver_t *); +extern const char gDriverName[]; + /* we define the driver methods with HAIKU_FBSD_DRIVER_GLUE to * force the rest of the stuff to be linked back with the driver. * While gcc 2.95 packs everything from the static library onto * the final binary, gcc 4.x rightfuly doesn't. */ -#define HAIKU_FBSD_DRIVER_GLUE(name, busname) \ +#define HAIKU_FBSD_DRIVER_GLUE(publicname, name, busname) \ extern char *gDevNameList[]; \ extern device_hooks gDeviceHooks; \ extern driver_t *DRIVER_MODULE_NAME(name, busname); \ + const char gDriverName[] = #publicname; \ int32 api_version = B_CUR_DRIVER_API_VERSION; \ status_t init_hardware() \ { \ @@ -64,6 +74,9 @@ void _fbsd_uninit_driver(driver_t *); const char **publish_devices() { return (const char **)gDevNameList; } \ device_hooks *find_device(const char *name) { return &gDeviceHooks; } +#define DEFINE_CLASS_0(name, driver, methods, size) \ + driver_t driver = { #name, methods, size } + #define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \ driver_t *DRIVER_MODULE_NAME(name, busname) = &(driver) diff --git a/src/libs/compat/freebsd_network/compat/sys/kernel.h b/src/libs/compat/freebsd_network/compat/sys/kernel.h index 7d77ccd8be..715ea1086a 100644 --- a/src/libs/compat/freebsd_network/compat/sys/kernel.h +++ b/src/libs/compat/freebsd_network/compat/sys/kernel.h @@ -28,7 +28,8 @@ struct __system_init { #define SYSINIT(uniquifier, subsystem, order, func, ident) \ struct __system_init __init_##uniquifier = { func } -#define __printflike(a, b) __attribute__ ((format (__printf__, a, b))) +#define __packed __attribute__ ((packed)) +#define __printflike(a, b) __attribute__ ((format (__printf__, a, b))) int printf(const char *format, ...) __printflike(1, 2); diff --git a/src/libs/compat/freebsd_network/compat/sys/mbuf.h b/src/libs/compat/freebsd_network/compat/sys/mbuf.h index bca639d086..643080a828 100644 --- a/src/libs/compat/freebsd_network/compat/sys/mbuf.h +++ b/src/libs/compat/freebsd_network/compat/sys/mbuf.h @@ -7,6 +7,8 @@ #define MLEN ((int)(MSIZE - sizeof(struct m_hdr))) #define MHLEN ((int)(MSIZE - sizeof(struct pkthdr))) +#define MINCLSIZE (MHLEN + 1) + #ifdef _KERNEL struct m_hdr { @@ -82,6 +84,10 @@ struct mbuf { #define CSUM_PSEUDO_HDR 0x0800 #define CSUM_DELAY_DATA (CSUM_TCP | CSUM_UDP) +#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)) + struct mbuf *m_getcl(int how, short type, int flags); void m_freem(struct mbuf *mbuf); struct mbuf *m_free(struct mbuf *m); @@ -94,6 +100,7 @@ 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); +void m_clget(struct mbuf *m, int how); #define mtod(m, type) (type)((m)->m_data) diff --git a/src/libs/compat/freebsd_network/compat/sys/mutex.h b/src/libs/compat/freebsd_network/compat/sys/mutex.h index 54d84df786..d7be3d34ec 100644 --- a/src/libs/compat/freebsd_network/compat/sys/mutex.h +++ b/src/libs/compat/freebsd_network/compat/sys/mutex.h @@ -43,6 +43,13 @@ static inline void mtx_unlock(struct mtx *mtx) } +static inline int mtx_initialized(struct mtx *mtx) +{ + /* XXX */ + return 1; +} + + void mtx_init(struct mtx *m, const char *name, const char *type, int opts); void mtx_destroy(struct mtx *m); diff --git a/src/libs/compat/freebsd_network/compat/sys/param.h b/src/libs/compat/freebsd_network/compat/sys/param.h index f5d99e9cd3..10dfecf593 100644 --- a/src/libs/compat/freebsd_network/compat/sys/param.h +++ b/src/libs/compat/freebsd_network/compat/sys/param.h @@ -30,4 +30,7 @@ #define MCLBYTES (1 << MCLSHIFT) +#define ALIGN_BYTES (sizeof(int) - 1) +#define ALIGN(x) ((((unsigned)x) + ALIGN_BYTES) & ~ALIGN_BYTES) + #endif diff --git a/src/libs/compat/freebsd_network/device.c b/src/libs/compat/freebsd_network/device.c index 63537d2c5f..1b0d8e8a40 100644 --- a/src/libs/compat/freebsd_network/device.c +++ b/src/libs/compat/freebsd_network/device.c @@ -122,13 +122,18 @@ _fbsd_init_hardware(driver_t *driver) pci_info info; int i; + dprintf("%s: init_hardware(%p)\n", gDriverName, driver); + + if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPci) < B_OK) + return B_ERROR; + for (i = 0; probe == NULL && driver->methods[i].name != NULL; i++) { if (strcmp(driver->methods[i].name, "device_probe") == 0) probe = driver->methods[i].method; } if (probe == NULL) { - dprintf("_fbsd_init_hardware: driver has no device_probe method.\n"); + dprintf("%s: driver has no device_probe method.\n", gDriverName); return B_ERROR; } @@ -136,10 +141,17 @@ _fbsd_init_hardware(driver_t *driver) fakeDevice.pciInfo = &info; for (i = 0; gPci->get_nth_pci_info(i, &info) == B_OK; i++) { - if (probe(&fakeDevice) >= 0) + if (probe(&fakeDevice) >= 0) { + dprintf("%s, found %s at %i\n", gDriverName, + fakeDevice.description, i); + put_module(B_PCI_MODULE_NAME); return B_OK; + } } + dprintf("%s: no hardware found.\n", gDriverName); + put_module(B_PCI_MODULE_NAME); + return B_ERROR; } @@ -147,6 +159,8 @@ _fbsd_init_hardware(driver_t *driver) status_t _fbsd_init_driver(driver_t *driver) { + dprintf("%s: init_driver(%p)\n", gDriverName, driver); + return B_ERROR; } @@ -154,4 +168,5 @@ _fbsd_init_driver(driver_t *driver) void _fbsd_uninit_driver(driver_t *driver) { + dprintf("%s: uninit_driver(%p)\n", gDriverName, driver); } diff --git a/src/libs/compat/freebsd_network/if.c b/src/libs/compat/freebsd_network/if.c index eea124dc50..5b1ced2e12 100644 --- a/src/libs/compat/freebsd_network/if.c +++ b/src/libs/compat/freebsd_network/if.c @@ -85,6 +85,33 @@ if_start(struct ifnet *ifp) } +int +if_printf(struct ifnet *ifp, const char *format, ...) +{ + char buf[256]; + va_list vl; + va_start(vl, format); + vsnprintf(buf, sizeof(buf), format, vl); + va_end(vl); + + dprintf("[%s] %s", ifp->if_xname, buf); + return 0; +} + + +void +if_link_state_change(struct ifnet *ifp, int link_state) +{ + if (ifp->if_link_state == link_state) + return; + + ifp->if_link_state = link_state; + + /* XXX */ + /* wake network stack's link state sem */ +} + + int ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt0) @@ -116,6 +143,9 @@ ether_ifattach(struct ifnet *ifp, const uint8_t *mac_address) ifp->if_input = ether_input; ifp->if_resolvemulti = NULL; /* done in the stack */ + ifp->if_lladdr.sdl_family = AF_LINK; + memcpy(IF_LLADDR(ifp), mac_address, ETHER_ADDR_LEN); + ifp->if_init(ifp->if_softc); } @@ -127,6 +157,80 @@ ether_ifdetach(struct ifnet *ifp) } +#if 0 +/* + * This is for reference. We have a table-driven version + * of the little-endian crc32 generator, which is faster + * than the double-loop. + */ +uint32_t +ether_crc32_le(const uint8_t *buf, size_t len) +{ + size_t i; + uint32_t crc; + int bit; + uint8_t data; + + crc = 0xffffffff; /* initial value */ + + for (i = 0; i < len; i++) { + for (data = *buf++, bit = 0; bit < 8; bit++, data >>= 1) + carry = (crc ^ data) & 1; + crc >>= 1; + if (carry) + crc = (crc ^ ETHER_CRC_POLY_LE); + } + + return (crc); +} +#else +uint32_t +ether_crc32_le(const uint8_t *buf, size_t len) +{ + static const uint32_t crctab[] = { + 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, + 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, + 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, + 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c + }; + size_t i; + uint32_t crc; + + crc = 0xffffffff; /* initial value */ + + for (i = 0; i < len; i++) { + crc ^= buf[i]; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + crc = (crc >> 4) ^ crctab[crc & 0xf]; + } + + return (crc); +} +#endif + +uint32_t +ether_crc32_be(const uint8_t *buf, size_t len) +{ + size_t i; + uint32_t crc, carry; + int bit; + uint8_t data; + + crc = 0xffffffff; /* initial value */ + + for (i = 0; i < len; i++) { + for (data = *buf++, bit = 0; bit < 8; bit++, data >>= 1) { + carry = ((crc & 0x80000000) ? 1 : 0) ^ (data & 0x01); + crc <<= 1; + if (carry) + crc = (crc ^ ETHER_CRC_POLY_BE) | carry; + } + } + + return (crc); +} + + int ether_ioctl(struct ifnet *ifp, int command, caddr_t data) { diff --git a/src/libs/compat/freebsd_network/mbuf.c b/src/libs/compat/freebsd_network/mbuf.c index 5f5f4985d9..6f06396766 100644 --- a/src/libs/compat/freebsd_network/mbuf.c +++ b/src/libs/compat/freebsd_network/mbuf.c @@ -146,6 +146,15 @@ m_gethdr(int how, short type) } +void +m_clget(struct mbuf *m, int how) +{ + m->m_ext.ext_buf = NULL; + /* called checks for errors by looking for M_EXT */ + construct_ext_mbuf(m, how); +} + + void m_freem(struct mbuf *mb) {