From b650951128733ee316bb4c9b985b99363b2e72e8 Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Wed, 9 May 2007 19:35:38 +0000 Subject: [PATCH] freebsd compat. layer: split device structure to handle for miibus devices, added a new network_device. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21094 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/libs/compat/freebsd_network/compat.c | 33 ++++-- .../compat/freebsd_network/compat/sys/bus.h | 1 + .../freebsd_network/compat/sys/haiku-module.h | 49 ++++---- src/libs/compat/freebsd_network/device.c | 108 ++++++++++-------- src/libs/compat/freebsd_network/device.h | 38 ++++-- src/libs/compat/freebsd_network/if.c | 11 +- 6 files changed, 150 insertions(+), 90 deletions(-) diff --git a/src/libs/compat/freebsd_network/compat.c b/src/libs/compat/freebsd_network/compat.c index 5c460b46fd..700c93c8b6 100644 --- a/src/libs/compat/freebsd_network/compat.c +++ b/src/libs/compat/freebsd_network/compat.c @@ -36,8 +36,9 @@ pci_module_info *gPci; uint32_t pci_read_config(device_t dev, int offset, int size) { - uint32_t value = gPci->read_pci_config(dev->pci_info.bus, - dev->pci_info.device, dev->pci_info.function, offset, size); + uint32_t value = gPci->read_pci_config(NETDEV(dev)->pci_info.bus, + NETDEV(dev)->pci_info.device, NETDEV(dev)->pci_info.function, + offset, size); TRACE_PCI(dev, "pci_read_config(%i, %i) = 0x%lx\n", offset, size, value); return value; } @@ -48,8 +49,9 @@ pci_write_config(device_t dev, int offset, uint32_t value, int size) { TRACE_PCI(dev, "pci_write_config(%i, 0x%lx, %i)\n", offset, value, size); - gPci->write_pci_config(dev->pci_info.bus, dev->pci_info.device, - dev->pci_info.function, offset, size, value); + gPci->write_pci_config(NETDEV(dev)->pci_info.bus, + NETDEV(dev)->pci_info.device, NETDEV(dev)->pci_info.function, + offset, size, value); } @@ -164,14 +166,10 @@ driver_vprintf(const char *format, va_list vl) int device_printf(device_t dev, const char *format, ...) { - char devDesc[32]; va_list vl; - snprintf(devDesc, sizeof(devDesc), "%i:%i:%i", (int)dev->pci_info.bus, - (int)dev->pci_info.device, (int)dev->pci_info.function); - va_start(vl, format); - driver_vprintf_etc(devDesc, format, vl); + driver_vprintf_etc(dev->dev_name, format, vl); va_end(vl); return 0; } @@ -192,6 +190,23 @@ device_set_desc_copy(device_t dev, const char *desc) } +const char * +device_get_desc(device_t dev) +{ + return dev->description; +} + + +void +device_sprintf_name(device_t dev, const char *format, ...) +{ + va_list vl; + va_start(vl, format); + vsnprintf(dev->dev_name, sizeof(dev->dev_name), format, vl); + va_end(vl); +} + + const char * device_get_name(device_t dev) { diff --git a/src/libs/compat/freebsd_network/compat/sys/bus.h b/src/libs/compat/freebsd_network/compat/sys/bus.h index 3034996be3..6057a48eff 100644 --- a/src/libs/compat/freebsd_network/compat/sys/bus.h +++ b/src/libs/compat/freebsd_network/compat/sys/bus.h @@ -93,6 +93,7 @@ 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); +const char *device_get_desc(device_t dev); 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 a0c08011c9..9c9e3d2c1a 100644 --- a/src/libs/compat/freebsd_network/compat/sys/haiku-module.h +++ b/src/libs/compat/freebsd_network/compat/sys/haiku-module.h @@ -52,32 +52,41 @@ status_t _fbsd_init_driver(driver_t *); void _fbsd_uninit_driver(driver_t *); extern const char gDriverName[]; +driver_t *__haiku_get_miibus_driver(void); /* 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(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() \ - { \ - return _fbsd_init_hardware(DRIVER_MODULE_NAME(name, busname)); \ - } \ - status_t init_driver() \ - { \ - return _fbsd_init_driver(DRIVER_MODULE_NAME(name, busname)); \ - } \ - void uninit_driver() \ - { \ - _fbsd_uninit_driver(DRIVER_MODULE_NAME(name, busname)); \ - } \ - const char **publish_devices() { return (const char **)gDevNameList; } \ - device_hooks *find_device(const char *name) { return &gDeviceHooks; } +#define HAIKU_FBSD_DRIVER_GLUE(publicname, name, busname) \ + extern const 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() \ + { \ + return _fbsd_init_hardware(DRIVER_MODULE_NAME(name, busname)); \ + } \ + status_t init_driver() \ + { \ + return _fbsd_init_driver(DRIVER_MODULE_NAME(name, busname)); \ + } \ + void uninit_driver() \ + { _fbsd_uninit_driver(DRIVER_MODULE_NAME(name, busname)); } \ + const char **publish_devices() \ + { return gDevNameList; } \ + device_hooks *find_device(const char *name) \ + { return &gDeviceHooks; } + +#define HAIKU_FBSD_MII_DRIVER(name) \ + driver_t *__haiku_get_miibus_driver(device_t dev) \ + { return DRIVER_MODULE_NAME(name, miibus); } + +#define HAIKU_NO_FBSD_MII_DRIVER() \ + driver_t *__haiku_get_miibus_driver(device_t dev) \ + { return NULL; } extern spinlock __haiku_intr_spinlock; extern int __haiku_disable_interrupts(device_t dev); diff --git a/src/libs/compat/freebsd_network/device.c b/src/libs/compat/freebsd_network/device.c index 3ab108f5a8..5c5b60f8db 100644 --- a/src/libs/compat/freebsd_network/device.c +++ b/src/libs/compat/freebsd_network/device.c @@ -26,8 +26,8 @@ #define MAX_DEVICES 8 -device_t gDevices[MAX_DEVICES]; -char *gDevNameList[MAX_DEVICES + 1]; +struct network_device *gDevices[MAX_DEVICES]; +const char *gDevNameList[MAX_DEVICES + 1]; static device_probe_t *sDeviceProbe; @@ -36,28 +36,47 @@ static device_detach_t *sDeviceDetach; static device_t +init_device(device_t dev, driver_t *driver) +{ + dev->driver = driver; + dev->softc = malloc(driver->softc_size); + if (dev->softc == NULL) + return NULL; + + return dev; +} + + +static void +uninit_device(device_t dev) +{ + if (dev->flags & DEVICE_DESC_ALLOCED) + free((char *)dev->description); + free(dev->softc); +} + + +static struct network_device * allocate_device(driver_t *driver) { char semName[64]; - device_t dev = (device_t)malloc(sizeof(struct device)); + struct network_device *dev = malloc(sizeof(struct network_device)); if (dev == NULL) return NULL; memset(dev, 0, sizeof(struct device)); - snprintf(semName, sizeof(semName), "%s rcv", gDriverName); - - dev->softc_size = driver->softc_size; - dev->softc = malloc(driver->softc_size); - if (dev->softc == NULL) { + if (init_device(DEVNET(dev), driver) == NULL) { free(dev); return NULL; } + snprintf(semName, sizeof(semName), "%s rcv", gDriverName); + dev->receive_sem = create_sem(0, semName); if (dev->receive_sem < 0) { - free(dev->softc); + uninit_device(DEVNET(dev)); free(dev); return NULL; } @@ -71,13 +90,11 @@ allocate_device(driver_t *driver) static void -free_device(device_t dev) +free_device(struct network_device *dev) { delete_sem(dev->receive_sem); ifq_uninit(&dev->receive_queue); - free(dev->softc); - if (dev->flags & DEVICE_DESC_ALLOCED) - free((char *)dev->description); + uninit_device(DEVNET(dev)); free(dev); } @@ -100,8 +117,8 @@ _resolve_method(driver_t *driver, const char *name) static status_t compat_open(const char *name, uint32 flags, void **cookie) { + struct network_device *dev; status_t status; - device_t dev; int i; driver_printf("compat_open(%s, 0x%lx)\n", name, flags); @@ -124,11 +141,11 @@ compat_open(const char *name, uint32 flags, void **cookie) return B_BUSY; /* some drivers expect the softc to be zero'ed out */ - memset(dev->softc, 0, dev->softc_size); + memset(dev->base.softc, 0, dev->base.driver->softc_size); - status = sDeviceAttach(dev); + status = sDeviceAttach(DEVNET(dev)); if (status != 0) - dev->flags = 0; + atomic_and(&dev->open, 0); driver_printf(" ... status = 0x%ld\n", status); @@ -155,11 +172,11 @@ compat_open(const char *name, uint32 flags, void **cookie) static status_t compat_close(void *cookie) { - device_t dev = cookie; + struct network_device *dev = cookie; - device_printf(dev, "compat_close()\n"); + device_printf(DEVNET(dev), "compat_close()\n"); - atomic_or(&dev->flags, DEVICE_CLOSED); + atomic_or(&DEVNET(dev)->flags, DEVICE_CLOSED); /* do we need a memory barrier in read() or is the atomic_or * (and the implicit 'lock') enough? */ @@ -173,11 +190,11 @@ compat_close(void *cookie) static status_t compat_free(void *cookie) { - device_t dev = cookie; + struct network_device *dev = cookie; - device_printf(dev, "compat_free()\n"); + device_printf(DEVNET(dev), "compat_free()\n"); - sDeviceDetach(dev); + sDeviceDetach(DEVNET(dev)); /* XXX empty out the send queue */ @@ -191,24 +208,24 @@ compat_free(void *cookie) static status_t compat_read(void *cookie, off_t position, void *buf, size_t *numBytes) { + struct network_device *dev = cookie; uint32 semFlags = B_CAN_INTERRUPT; - device_t dev = cookie; status_t status; struct mbuf *mb; size_t len; - driver_printf("compat_read(%p, %lld, %p, [%lu])\n", cookie, position, buf, + device_printf(DEVNET(dev), "compat_read(%lld, %p, [%lu])\n", position, buf, *numBytes); - if (dev->flags & DEVICE_CLOSED) + if (DEVNET(dev)->flags & DEVICE_CLOSED) return B_INTERRUPTED; - if (dev->flags & DEVICE_NON_BLOCK) + if (DEVNET(dev)->flags & DEVICE_NON_BLOCK) semFlags |= B_RELATIVE_TIMEOUT; do { status = acquire_sem_etc(dev->receive_sem, 1, semFlags, 0); - if (dev->flags & DEVICE_CLOSED) + if (DEVNET(dev)->flags & DEVICE_CLOSED) return B_INTERRUPTED; if (status == B_WOULD_BLOCK) { @@ -242,10 +259,10 @@ static status_t compat_write(void *cookie, off_t position, const void *buffer, size_t *numBytes) { - device_t dev = cookie; + struct network_device *dev = cookie; struct mbuf *mb; - driver_printf("compat_write(%p, %lld, %p, [%lu])\n", cookie, position, + device_printf(DEVNET(dev), "compat_write(%lld, %p, [%lu])\n", position, buffer, *numBytes); mb = m_getcl(0, MT_DATA, 0); @@ -264,7 +281,7 @@ compat_write(void *cookie, off_t position, const void *buffer, static status_t compat_control(void *cookie, uint32 op, void *arg, size_t len) { - device_t dev = cookie; + struct network_device *dev = cookie; struct ifnet *ifp = dev->ifp; switch (op) { @@ -282,9 +299,9 @@ compat_control(void *cookie, uint32 op, void *arg, size_t len) if (user_memcpy(&value, arg, sizeof(int32)) < B_OK) return B_BAD_ADDRESS; if (value) - dev->flags |= DEVICE_NON_BLOCK; + DEVNET(dev)->flags |= DEVICE_NON_BLOCK; else - dev->flags &= ~DEVICE_NON_BLOCK; + DEVNET(dev)->flags &= ~DEVICE_NON_BLOCK; return B_OK; } @@ -378,7 +395,7 @@ device_hooks gDeviceHooks = { status_t _fbsd_init_hardware(driver_t *driver) { - struct device fakeDevice; + struct network_device fakeDevice; device_probe_t *probe; int i; @@ -397,12 +414,12 @@ _fbsd_init_hardware(driver_t *driver) for (i = 0; gPci->get_nth_pci_info(i, &fakeDevice.pci_info) == B_OK; i++) { int result; - result = probe(&fakeDevice); + result = probe(DEVNET(&fakeDevice)); if (result >= 0) { dprintf("%s, found %s at %d\n", gDriverName, - fakeDevice.description, i); - if (fakeDevice.flags & DEVICE_DESC_ALLOCED) - free((char *)fakeDevice.description); + device_get_desc(DEVNET(&fakeDevice)), i); + if (DEVNET(&fakeDevice)->flags & DEVICE_DESC_ALLOCED) + free((char *)DEVNET(&fakeDevice)->description); put_module(B_PCI_MODULE_NAME); return B_OK; } @@ -420,7 +437,7 @@ _fbsd_init_driver(driver_t *driver) { int i, ncards = 0; status_t status; - device_t dev; + struct network_device *dev; dprintf("%s: init_driver(%p)\n", gDriverName, driver); @@ -460,14 +477,15 @@ _fbsd_init_driver(driver_t *driver) for (i = 0; dev != NULL && gPci->get_nth_pci_info(i, &dev->pci_info) == B_OK; i++) { - if (sDeviceProbe(dev) >= 0) { - snprintf(dev->dev_name, sizeof(dev->dev_name), "net/%s/%i", - gDriverName, ncards); - dprintf("%s, adding %s @%d -> /dev/%s\n", gDriverName, dev->description, - i, dev->dev_name); + device_t base = DEVNET(dev); + + if (sDeviceProbe(base) >= 0) { + device_sprintf_name(base, "net/%s/%i", gDriverName, ncards); + dprintf("%s, adding %s @%d -> /dev/%s\n", gDriverName, + device_get_desc(base), i, device_get_name(base)); gDevices[ncards] = dev; - gDevNameList[ncards] = dev->dev_name; + gDevNameList[ncards] = device_get_name(base); ncards++; if (ncards < MAX_DEVICES) diff --git a/src/libs/compat/freebsd_network/device.h b/src/libs/compat/freebsd_network/device.h index d8d47984ca..44567217d5 100644 --- a/src/libs/compat/freebsd_network/device.h +++ b/src/libs/compat/freebsd_network/device.h @@ -25,27 +25,39 @@ struct ifnet; struct device { - pci_info pci_info; char dev_name[128]; - int32 open; + driver_t *driver; + int32 flags; + int unit; + char nameunit[64]; + const char * description; + void * softc; +}; + + +struct network_device { + struct device base; + + pci_info pci_info; + + int32 open; + struct ifqueue receive_queue; sem_id receive_sem; sem_id link_state_sem; struct ifnet * ifp; - - int unit; - char nameunit[64]; - const char * description; - void * softc; - size_t softc_size; }; +#define DEVNET(dev) ((device_t)(&(dev)->base)) +#define NETDEV(base) ((struct network_device *)(base)) + + enum { DEVICE_OPEN = 1 << 0, DEVICE_CLOSED = 1 << 1, @@ -80,16 +92,20 @@ void uninit_taskqueues(void); void init_bounce_pages(void); void uninit_bounce_pages(void); -void driver_printf(const char *format, ...) __attribute__ ((format (__printf__, 1, 2))); +void driver_printf(const char *format, ...) + __attribute__ ((format (__printf__, 1, 2))); void driver_vprintf(const char *format, va_list vl); +void device_sprintf_name(device_t dev, const char *format, ...) + __attribute__ ((format (__printf__, 2, 3))); + void ifq_init(struct ifqueue *ifq, const char *name); void ifq_uninit(struct ifqueue *ifq); extern struct net_stack_module_info *gStack; extern pci_module_info *gPci; -extern char *gDevNameList[]; -extern struct device *gDevices[]; +extern const char *gDevNameList[]; +extern struct network_device *gDevices[]; #endif diff --git a/src/libs/compat/freebsd_network/if.c b/src/libs/compat/freebsd_network/if.c index 996d4b32ff..49fb38cc13 100644 --- a/src/libs/compat/freebsd_network/if.c +++ b/src/libs/compat/freebsd_network/if.c @@ -67,8 +67,8 @@ if_initname(struct ifnet *ifp, const char *name, int unit) if (gDevNameList[i] == NULL) panic("unknown interface"); - ifp->if_dev = gDevices[i]; - ifp->if_dev->ifp = ifp; + ifp->if_dev = DEVNET(gDevices[i]); + gDevices[i]->ifp = ifp; } @@ -146,7 +146,8 @@ if_link_state_change(struct ifnet *ifp, int link_state) ifp->if_link_state = link_state; - release_sem_etc(ifp->if_dev->link_state_sem, 1, B_DO_NOT_RESCHEDULE); + release_sem_etc(NETDEV(ifp->if_dev)->link_state_sem, 1, + B_DO_NOT_RESCHEDULE); } @@ -269,8 +270,8 @@ ether_input(struct ifnet *ifp, struct mbuf *m) { device_t dev = ifp->if_dev; - IF_ENQUEUE(&dev->receive_queue, m); - release_sem_etc(dev->receive_sem, 1, B_DO_NOT_RESCHEDULE); + IF_ENQUEUE(&NETDEV(dev)->receive_queue, m); + release_sem_etc(NETDEV(dev)->receive_sem, 1, B_DO_NOT_RESCHEDULE); }