diff --git a/src/add-ons/kernel/drivers/network/3com/dev/mii/ukphy.c b/src/add-ons/kernel/drivers/network/3com/dev/mii/ukphy.c index 4f5a485b51..10347825bf 100644 --- a/src/add-ons/kernel/drivers/network/3com/dev/mii/ukphy.c +++ b/src/add-ons/kernel/drivers/network/3com/dev/mii/ukphy.c @@ -67,7 +67,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy.c,v 1.17 2005/01/06 01:42:56 imp Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy.c,v 1.20 2007/01/20 00:52:29 marius Exp $"); /* * driver for generic unknown PHYs @@ -114,34 +114,27 @@ DRIVER_MODULE(ukphy, miibus, ukphy_driver, ukphy_devclass, 0, 0); static int ukphy_service(struct mii_softc *, struct mii_data *, int); static int -ukphy_probe(dev) - device_t dev; +ukphy_probe(device_t dev) { /* * We know something is here, so always match at a low priority. */ device_set_desc(dev, "Generic IEEE 802.3u media interface"); - return (-100); + return (BUS_PROBE_GENERIC); } static int -ukphy_attach(dev) - device_t dev; +ukphy_attach(device_t dev) { struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; -static int ppp; -if (ppp++ > 0) - panic("oops"); sc = device_get_softc(dev); ma = device_get_ivars(dev); sc->mii_dev = device_get_parent(dev); mii = device_get_softc(sc->mii_dev); -device_printf(dev, "insert into %p\n", mii); -device_printf(sc->mii_dev, "this is the parent\n"); LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); if (bootverbose) @@ -156,8 +149,6 @@ device_printf(sc->mii_dev, "this is the parent\n"); mii->mii_instance++; - sc->mii_flags |= MIIF_NOISOLATE; - mii_phy_reset(sc); sc->mii_capabilities = @@ -171,14 +162,11 @@ device_printf(sc->mii_dev, "this is the parent\n"); MIIBUS_MEDIAINIT(sc->mii_dev); mii_phy_setmedia(sc); - return(0); + return (0); } static int -ukphy_service(sc, mii, cmd) - struct mii_softc *sc; - struct mii_data *mii; - int cmd; +ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg; diff --git a/src/add-ons/kernel/drivers/network/3com/pci/glue.c b/src/add-ons/kernel/drivers/network/3com/pci/glue.c index feca20a945..4e55fe61c4 100644 --- a/src/add-ons/kernel/drivers/network/3com/pci/glue.c +++ b/src/add-ons/kernel/drivers/network/3com/pci/glue.c @@ -23,10 +23,11 @@ __haiku_select_miibus_driver(device_t dev) driver_t *drivers[] = { DRIVER_MODULE_NAME(bmtphy, miibus), DRIVER_MODULE_NAME(xlphy, miibus), - DRIVER_MODULE_NAME(ukphy, miibus) + DRIVER_MODULE_NAME(ukphy, miibus), + NULL }; - return __haiku_probe_miibus(dev, drivers, 3); + return __haiku_probe_miibus(dev, drivers); } diff --git a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/mii/ukphy.c b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/mii/ukphy.c index 4f5a485b51..10347825bf 100644 --- a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/mii/ukphy.c +++ b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/mii/ukphy.c @@ -67,7 +67,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy.c,v 1.17 2005/01/06 01:42:56 imp Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy.c,v 1.20 2007/01/20 00:52:29 marius Exp $"); /* * driver for generic unknown PHYs @@ -114,34 +114,27 @@ DRIVER_MODULE(ukphy, miibus, ukphy_driver, ukphy_devclass, 0, 0); static int ukphy_service(struct mii_softc *, struct mii_data *, int); static int -ukphy_probe(dev) - device_t dev; +ukphy_probe(device_t dev) { /* * We know something is here, so always match at a low priority. */ device_set_desc(dev, "Generic IEEE 802.3u media interface"); - return (-100); + return (BUS_PROBE_GENERIC); } static int -ukphy_attach(dev) - device_t dev; +ukphy_attach(device_t dev) { struct mii_softc *sc; struct mii_attach_args *ma; struct mii_data *mii; -static int ppp; -if (ppp++ > 0) - panic("oops"); sc = device_get_softc(dev); ma = device_get_ivars(dev); sc->mii_dev = device_get_parent(dev); mii = device_get_softc(sc->mii_dev); -device_printf(dev, "insert into %p\n", mii); -device_printf(sc->mii_dev, "this is the parent\n"); LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list); if (bootverbose) @@ -156,8 +149,6 @@ device_printf(sc->mii_dev, "this is the parent\n"); mii->mii_instance++; - sc->mii_flags |= MIIF_NOISOLATE; - mii_phy_reset(sc); sc->mii_capabilities = @@ -171,14 +162,11 @@ device_printf(sc->mii_dev, "this is the parent\n"); MIIBUS_MEDIAINIT(sc->mii_dev); mii_phy_setmedia(sc); - return(0); + return (0); } static int -ukphy_service(sc, mii, cmd) - struct mii_softc *sc; - struct mii_data *mii; - int cmd; +ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg; diff --git a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c index 1cb746c291..815aa6104c 100644 --- a/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c +++ b/src/add-ons/kernel/drivers/network/marvell_yukon/dev/msk/glue.c @@ -19,10 +19,11 @@ __haiku_select_miibus_driver(device_t dev) { driver_t *drivers[] = { DRIVER_MODULE_NAME(e1000phy, miibus), - DRIVER_MODULE_NAME(ukphy, miibus) + DRIVER_MODULE_NAME(ukphy, miibus), + NULL }; - return __haiku_probe_miibus(dev, drivers, 2); + return __haiku_probe_miibus(dev, drivers); } NO_HAIKU_CHECK_DISABLE_INTERRUPTS(); diff --git a/src/add-ons/kernel/drivers/network/rtl8139/pci/glue.c b/src/add-ons/kernel/drivers/network/rtl8139/pci/glue.c index a54f8efc80..d1bd10cb55 100644 --- a/src/add-ons/kernel/drivers/network/rtl8139/pci/glue.c +++ b/src/add-ons/kernel/drivers/network/rtl8139/pci/glue.c @@ -6,21 +6,33 @@ HAIKU_FBSD_DRIVER_GLUE(rtl8139, rl, pci); HAIKU_FBSD_MII_DRIVER(rlphy); HAIKU_DRIVER_REQUIREMENTS(0); + int -HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) { +HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) +{ struct rl_softc *sc = device_get_softc(dev); + uint16_t status; - HAIKU_PROTECT_INTR_REGISTER(CSR_WRITE_2(sc, RL_IMR, 0)); + status = CSR_READ_2(sc, RL_ISR); + if (status == 0xffff) + return 0; + if (status != 0 && (status & RL_INTRS) == 0) { + CSR_WRITE_2(sc, RL_ISR, status); + return 0; + } + if ((status & RL_INTRS) == 0) + return 0; - /* we don't read the status register, so we just assume it was for us. */ + CSR_WRITE_2(sc, RL_IMR, 0); return 1; } + void HAIKU_REENABLE_INTERRUPTS(device_t dev) { struct rl_softc *sc = device_get_softc(dev); RL_LOCK(sc); - HAIKU_PROTECT_INTR_REGISTER(CSR_WRITE_2(sc, RL_IMR, RL_INTRS)); + CSR_WRITE_2(sc, RL_IMR, RL_INTRS); RL_UNLOCK(sc); } diff --git a/src/add-ons/kernel/drivers/network/via_rhine/dev/mii/ukphy.c b/src/add-ons/kernel/drivers/network/via_rhine/dev/mii/ukphy.c index 4ce5a9c771..10347825bf 100644 --- a/src/add-ons/kernel/drivers/network/via_rhine/dev/mii/ukphy.c +++ b/src/add-ons/kernel/drivers/network/via_rhine/dev/mii/ukphy.c @@ -67,7 +67,7 @@ */ #include -__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy.c,v 1.17 2005/01/06 01:42:56 imp Exp $"); +__FBSDID("$FreeBSD: src/sys/dev/mii/ukphy.c,v 1.20 2007/01/20 00:52:29 marius Exp $"); /* * driver for generic unknown PHYs @@ -114,20 +114,18 @@ DRIVER_MODULE(ukphy, miibus, ukphy_driver, ukphy_devclass, 0, 0); static int ukphy_service(struct mii_softc *, struct mii_data *, int); static int -ukphy_probe(dev) - device_t dev; +ukphy_probe(device_t dev) { /* * We know something is here, so always match at a low priority. */ device_set_desc(dev, "Generic IEEE 802.3u media interface"); - return (-100); + return (BUS_PROBE_GENERIC); } static int -ukphy_attach(dev) - device_t dev; +ukphy_attach(device_t dev) { struct mii_softc *sc; struct mii_attach_args *ma; @@ -151,8 +149,6 @@ ukphy_attach(dev) mii->mii_instance++; - sc->mii_flags |= MIIF_NOISOLATE; - mii_phy_reset(sc); sc->mii_capabilities = @@ -166,14 +162,11 @@ ukphy_attach(dev) MIIBUS_MEDIAINIT(sc->mii_dev); mii_phy_setmedia(sc); - return(0); + return (0); } static int -ukphy_service(sc, mii, cmd) - struct mii_softc *sc; - struct mii_data *mii; - int cmd; +ukphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) { struct ifmedia_entry *ife = mii->mii_media.ifm_cur; int reg; diff --git a/src/add-ons/kernel/drivers/network/via_rhine/pci/glue.c b/src/add-ons/kernel/drivers/network/via_rhine/pci/glue.c index bf55581afa..0dcad1be34 100644 --- a/src/add-ons/kernel/drivers/network/via_rhine/pci/glue.c +++ b/src/add-ons/kernel/drivers/network/via_rhine/pci/glue.c @@ -20,9 +20,10 @@ __haiku_select_miibus_driver(device_t dev) { driver_t *drivers[] = { DRIVER_MODULE_NAME(ciphy, miibus), - DRIVER_MODULE_NAME(ukphy, miibus) + DRIVER_MODULE_NAME(ukphy, miibus), + NULL }; - return __haiku_probe_miibus(dev, drivers, 2); + return __haiku_probe_miibus(dev, drivers); } diff --git a/src/libs/compat/freebsd_network/Jamfile b/src/libs/compat/freebsd_network/Jamfile index 3d2464752b..e23ecf67dc 100644 --- a/src/libs/compat/freebsd_network/Jamfile +++ b/src/libs/compat/freebsd_network/Jamfile @@ -13,6 +13,7 @@ KernelStaticLibrary libfreebsd_network.a : callout.c compat.c device.c + driver.c fbsd_busdma_x86.c fbsd_ether.c fbsd_if_media.c @@ -23,5 +24,6 @@ KernelStaticLibrary libfreebsd_network.a : mbuf.c mii.c mutex.c + pci.c taskqueue.c ; diff --git a/src/libs/compat/freebsd_network/bus.c b/src/libs/compat/freebsd_network/bus.c index 3b2fc2a245..75e4a7f4fa 100644 --- a/src/libs/compat/freebsd_network/bus.c +++ b/src/libs/compat/freebsd_network/bus.c @@ -11,6 +11,7 @@ #include +#include #include #include #include @@ -24,6 +25,14 @@ # define TRACE_BUS_SPACE_RW(x) #endif +//#define DEBUG_PCI +#ifdef DEBUG_PCI +# define TRACE_PCI(dev, format, args...) device_printf(dev, format , ##args) +#else +# define TRACE_PCI(dev, format, args...) do { } while (0) +#endif + + #define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1)) // TODO: x86 specific! @@ -306,7 +315,7 @@ bus_setup_intr(device_t dev, struct resource *res, int flags, status = install_io_interrupt_handler(intr->irq, intr_fast_wrapper, intr, 0); } else { - snprintf(semName, sizeof(semName), "%s intr", dev->dev_name); + snprintf(semName, sizeof(semName), "%s intr", dev->device_name); intr->sem = create_sem(0, semName); if (intr->sem < B_OK) { @@ -314,7 +323,7 @@ bus_setup_intr(device_t dev, struct resource *res, int flags, return B_NO_MEMORY; } - snprintf(semName, sizeof(semName), "%s intr handler", dev->dev_name); + snprintf(semName, sizeof(semName), "%s intr handler", dev->device_name); intr->thread = spawn_kernel_thread(intr_handler, semName, B_REAL_TIME_DISPLAY_PRIORITY, intr); @@ -450,3 +459,184 @@ BUS_SPACE_READ(4, uint32_t, in32) BUS_SPACE_WRITE(1, uint8_t, out8) BUS_SPACE_WRITE(2, uint16_t, out16) BUS_SPACE_WRITE(4, uint32_t, out32) + + +// #pragma mark - PCI functions + + +uint32_t +pci_read_config(device_t dev, int offset, int size) +{ + pci_info *info = &((struct root_device_softc *)dev->root->softc)->pci_info; + + uint32_t value = gPci->read_pci_config(info->bus, info->device, + info->function, offset, size); + TRACE_PCI(dev, "pci_read_config(%i, %i) = 0x%x\n", offset, size, value); + return value; +} + + +void +pci_write_config(device_t dev, int offset, uint32_t value, int size) +{ + pci_info *info = &((struct root_device_softc *)dev->root->softc)->pci_info; + + TRACE_PCI(dev, "pci_write_config(%i, 0x%x, %i)\n", offset, value, size); + + gPci->write_pci_config(info->bus, info->device, info->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); +} + + +uint16_t +pci_get_subvendor(device_t dev) +{ + return pci_read_config(dev, PCI_subsystem_vendor_id, 2); +} + + +uint16_t +pci_get_subdevice(device_t dev) +{ + return pci_read_config(dev, PCI_subsystem_id, 2); +} + + +uint8_t +pci_get_revid(device_t dev) +{ + return pci_read_config(dev, PCI_revision, 1); +} + + +static void +pci_set_command_bit(device_t dev, uint16_t bit) +{ + uint16_t command = pci_read_config(dev, PCI_command, 2); + pci_write_config(dev, PCI_command, command | bit, 2); +} + + +int +pci_enable_busmaster(device_t dev) +{ + pci_set_command_bit(dev, PCI_command_master); + return 0; +} + + +int +pci_enable_io(device_t dev, int space) +{ + /* adapted from FreeBSD's pci_enable_io_method */ + 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 +pci_find_extcap(device_t child, int capability, int *_capabilityRegister) +{ + uint8 capabilityPointer; + uint8 headerType; + uint16 status; + + status = pci_read_config(child, PCIR_STATUS, 2); + if ((status & PCIM_STATUS_CAPPRESENT) == 0) + return ENXIO; + + headerType = pci_read_config(child, PCI_header_type, 1); + switch (headerType & PCIM_HDRTYPE) { + case 0: + case 1: + capabilityPointer = PCIR_CAP_PTR; + break; + case 2: + capabilityPointer = PCIR_CAP_PTR_2; + break; + default: + return ENXIO; + } + capabilityPointer = pci_read_config(child, capabilityPointer, 1); + + while (capabilityPointer != 0) { + if (pci_read_config(child, capabilityPointer + PCICAP_ID, 1) + == capability) { + if (_capabilityRegister != NULL) + *_capabilityRegister = capabilityPointer; + return 0; + } + capabilityPointer = pci_read_config(child, + capabilityPointer + PCICAP_NEXTPTR, 1); + } + + return ENOENT; +} + + +int +pci_msi_count(device_t dev) +{ + return 0; +} + + +int +pci_alloc_msi(device_t dev, int *count) +{ + return ENODEV; +} + + +int +pci_release_msi(device_t dev) +{ + return ENODEV; +} + + +int +pci_msix_count(device_t dev) +{ + return 0; +} + + +int +pci_alloc_msix(device_t dev, int *count) +{ + return ENODEV; +} + diff --git a/src/libs/compat/freebsd_network/compat.c b/src/libs/compat/freebsd_network/compat.c index 662d11428b..487aa1f668 100644 --- a/src/libs/compat/freebsd_network/compat.c +++ b/src/libs/compat/freebsd_network/compat.c @@ -14,201 +14,85 @@ #include #include -#include -#include +#include #include #include -//#define DEBUG_PCI -#ifdef DEBUG_PCI -# define TRACE_PCI(dev, format, args...) device_printf(dev, format , ##args) -#else -# define TRACE_PCI(dev, format, args...) do { } while (0) -#endif - spinlock __haiku_intr_spinlock; struct net_stack_module_info *gStack; pci_module_info *gPci; - -// #pragma mark - PCI +static struct list sRootDevices; +static int sNextUnit; -uint32_t -pci_read_config(device_t dev, int offset, int size) +// #pragma mark - private functions + + +static device_t +init_device(device_t device, driver_t *driver) { - 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%x\n", offset, size, value); - return value; + list_init_etc(&device->children, offsetof(struct device, link)); + device->unit = sNextUnit++; + + if (driver != NULL && device_set_driver(device, driver) < 0) + return NULL; + + return device; } -void -pci_write_config(device_t dev, int offset, uint32_t value, int size) +static device_t +new_device(driver_t *driver) { - TRACE_PCI(dev, "pci_write_config(%i, 0x%x, %i)\n", offset, value, size); + device_t dev = malloc(sizeof(struct device)); + if (dev == NULL) + return NULL; - gPci->write_pci_config(NETDEV(dev)->pci_info.bus, - NETDEV(dev)->pci_info.device, NETDEV(dev)->pci_info.function, - offset, size, value); -} + memset(dev, 0, sizeof(struct device)); - -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); -} - - -uint16_t -pci_get_subvendor(device_t dev) -{ - return pci_read_config(dev, PCI_subsystem_vendor_id, 2); -} - - -uint16_t -pci_get_subdevice(device_t dev) -{ - return pci_read_config(dev, PCI_subsystem_id, 2); -} - - -uint8_t -pci_get_revid(device_t dev) -{ - return pci_read_config(dev, PCI_revision, 1); -} - - -static void -pci_set_command_bit(device_t dev, uint16_t bit) -{ - uint16_t command = pci_read_config(dev, PCI_command, 2); - pci_write_config(dev, PCI_command, command | bit, 2); -} - - -int -pci_enable_busmaster(device_t dev) -{ - pci_set_command_bit(dev, PCI_command_master); - return 0; -} - - -int -pci_enable_io(device_t dev, int space) -{ - /* adapted from FreeBSD's pci_enable_io_method */ - 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; + if (init_device(dev, driver) == NULL) { + free(dev); + return NULL; } - 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; + return dev; } -int -pci_find_extcap(device_t child, int capability, int *_capabilityRegister) +static image_id +find_own_image() { - uint8 capabilityPointer; - uint8 headerType; - uint16 status; - - status = pci_read_config(child, PCIR_STATUS, 2); - if ((status & PCIM_STATUS_CAPPRESENT) == 0) - return ENXIO; - - headerType = pci_read_config(child, PCI_header_type, 1); - switch (headerType & PCIM_HDRTYPE) { - case 0: - case 1: - capabilityPointer = PCIR_CAP_PTR; - break; - case 2: - capabilityPointer = PCIR_CAP_PTR_2; - break; - default: - return ENXIO; - } - capabilityPointer = pci_read_config(child, capabilityPointer, 1); - - while (capabilityPointer != 0) { - if (pci_read_config(child, capabilityPointer + PCICAP_ID, 1) - == capability) { - if (_capabilityRegister != NULL) - *_capabilityRegister = capabilityPointer; - return 0; + int32 cookie = 0; + image_info info; + while (get_next_image_info(B_SYSTEM_TEAM, &cookie, &info) == B_OK) { + if (((uint32)info.text <= (uint32)find_own_image + && (uint32)info.text + (uint32)info.text_size + > (uint32)find_own_image)) { + // found our own image + return info.id; } - capabilityPointer = pci_read_config(child, - capabilityPointer + PCICAP_NEXTPTR, 1); } - return ENOENT; + return B_ENTRY_NOT_FOUND; } -int -pci_msi_count(device_t dev) +static device_method_signature_t +resolve_method(driver_t *driver, const char *name) { - return 0; -} + device_method_signature_t method = NULL; + int i; + for (i = 0; method == NULL && driver->methods[i].name != NULL; i++) { + if (strcmp(driver->methods[i].name, name) == 0) + method = driver->methods[i].method; + } -int -pci_alloc_msi(device_t dev, int *count) -{ - return ENODEV; -} - - -int -pci_release_msi(device_t dev) -{ - return ENODEV; -} - - -int -pci_msix_count(device_t dev) -{ - return 0; -} - - -int -pci_alloc_msix(device_t dev, int *count) -{ - return ENODEV; + return method; } @@ -251,7 +135,7 @@ device_printf(device_t dev, const char *format, ...) va_list vl; va_start(vl, format); - driver_vprintf_etc(dev->dev_name, format, vl); + driver_vprintf_etc(dev->device_name, format, vl); va_end(vl); return 0; } @@ -300,22 +184,13 @@ device_get_ivars(device_t dev) } -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) { - if (dev) - return dev->dev_name; - return NULL; + if (dev == NULL) + return NULL; + + return dev->device_name; } @@ -340,18 +215,6 @@ device_get_softc(device_t dev) } -device_t -init_device(device_t dev, driver_t *driver) -{ - list_init_etc(&dev->children, offsetof(struct device, link)); - - if (driver != NULL && device_set_driver(dev, driver) < 0) - return NULL; - - return dev; -} - - int device_set_driver(device_t dev, driver_t *driver) { @@ -397,60 +260,14 @@ device_set_driver(device_t dev, driver_t *driver) int -device_is_alive(device_t dev) +device_is_alive(device_t device) { - return dev->driver != NULL; -} - - -void -uninit_device(device_t dev) -{ - if (dev->flags & DEVICE_DESC_ALLOCED) - free((char *)dev->description); - if (dev->softc) - free(dev->softc); -} - - -static device_t -new_device(driver_t *driver) -{ - device_t dev = malloc(sizeof(struct device)); - if (dev == NULL) - return NULL; - - memset(dev, 0, sizeof(struct device)); - - if (init_device(dev, driver) == NULL) { - free(dev); - return NULL; - } - - return dev; -} - - -static image_id -find_own_image() -{ - int32 cookie = 0; - image_info info; - while (get_next_image_info(B_SYSTEM_TEAM, &cookie, &info) == B_OK) { - if (((uint32)info.text <= (uint32)find_own_image - && (uint32)info.text + (uint32)info.text_size - > (uint32)find_own_image)) { - // found our own image - return info.id; - } - } - - return B_ENTRY_NOT_FOUND; + return (device->flags & DEVICE_ATTACHED) != 0; } device_t -device_add_child(device_t dev, const char *name, int order) +device_add_child(device_t parent, const char *name, int unit) { device_t child = NULL; @@ -462,13 +279,11 @@ device_add_child(device_t dev, const char *name, int order) driver_t **driver; char symbol[128]; - snprintf(symbol, sizeof(symbol), "__fbsd_%s%s", name, dev->driver->name); + snprintf(symbol, sizeof(symbol), "__fbsd_%s%s", name, + parent->driver->name); if (get_image_symbol(find_own_image(), symbol, B_SYMBOL_TYPE_DATA, (void **)&driver) == B_OK) child = new_device(*driver); - - // inherit the device name of our parent - name = dev->dev_name; } } else child = new_device(NULL); @@ -477,37 +292,76 @@ device_add_child(device_t dev, const char *name, int order) return NULL; if (name != NULL) - strlcpy(child->dev_name, name, sizeof(child->dev_name)); - child->parent = dev; - list_add_item(&dev->children, child); + strlcpy(child->device_name, name, sizeof(child->device_name)); + + child->parent = parent; + + if (parent != NULL) { + list_add_item(&parent->children, child); + child->root = parent->root; + } else { + if (sRootDevices.link.next == NULL) + list_init_etc(&sRootDevices, offsetof(struct device, link)); + list_add_item(&sRootDevices, child); + } return child; } -driver_t * -__haiku_probe_miibus(device_t dev, driver_t *drivers[], int count) +/*! Delete the child and all of its children. Detach as necessary. +*/ +int +device_delete_child(device_t parent, device_t child) { - driver_t *selected = NULL; - int i, selcost = 0; + if (child == NULL) + return 0; - for (i = 0; i < count; i++) { - device_probe_t *probe = (device_probe_t *) - _resolve_method(drivers[i], "device_probe"); - if (probe) { - int result = probe(dev); - // the ukphy driver (fallback for unknown PHYs) return -100 here - if (result >= -100) { - if (selected == NULL || result > selcost) { - selected = drivers[i]; - selcost = result; - device_printf(dev, "Found MII: %s\n", selected->name); - } - } - } + if (parent != NULL) + list_remove_item(&parent->children, child); + + parent = child; + + while ((child = list_remove_head_item(&parent->children)) != NULL) { + device_delete_child(NULL, child); } - return selected; + if ((atomic_and(&parent->flags, ~DEVICE_ATTACHED) & DEVICE_ATTACHED) != 0 + && parent->methods.detach != NULL) { + int status = parent->methods.detach(parent); + if (status != 0) + return status; + } + + if (parent->flags & DEVICE_DESC_ALLOCED) + free((char *)parent->description); + + free(parent->softc); + free(parent); + return 0; +} + + +int +device_is_attached(device_t device) +{ + return (device->flags & DEVICE_ATTACHED) != 0; +} + + +int +device_attach(device_t device) +{ + int result; + + if (device->driver == NULL) + return B_ERROR; + + result = device->methods.attach(device); + if (result == 0) + atomic_or(&device->flags, DEVICE_ATTACHED); + + return result; } @@ -522,15 +376,15 @@ bus_generic_attach(device_t dev) if (driver == NULL) { struct mii_attach_args *ma = device_get_ivars(child); - device_printf(dev, "No PHY module found (%x/%x)!\n", ma->mii_id1, - ma->mii_id2); + device_printf(dev, "No PHY module found (%x/%x)!\n", + MII_OUI(ma->mii_id1, ma->mii_id2), MII_MODEL(ma->mii_id2)); } else device_set_driver(child, driver); - } else if (child->driver == &miibus_driver) + } else if (child->driver != &miibus_driver) child->methods.probe(child); if (child->driver != NULL) { - int result = child->methods.attach(child); + int result = device_attach(child); if (result != 0) return result; } @@ -540,25 +394,51 @@ bus_generic_attach(device_t dev) } -int -device_delete_child(device_t dev, device_t child) -{ - UNIMPLEMENTED(); - return -1; -} - - -int -device_is_attached(device_t dev) -{ - UNIMPLEMENTED(); - return -1; -} - - // #pragma mark - Misc, Malloc +device_t +find_root_device(int unit) +{ + device_t device = NULL; + + while ((device = list_get_next_item(&sRootDevices, device)) != NULL) { + if (device->unit <= unit) + return device; + } + + return NULL; +} + + +driver_t * +__haiku_probe_miibus(device_t dev, driver_t *drivers[]) +{ + driver_t *selected = NULL; + int i, selectedResult = 0; + + if (drivers == NULL) + return NULL; + + for (i = 0; drivers[i]; i++) { + device_probe_t *probe = (device_probe_t *) + resolve_method(drivers[i], "device_probe"); + if (probe) { + int result = probe(dev); + if (result >= 0) { + if (selected == NULL || result < selectedResult) { + selected = drivers[i]; + selectedResult = result; + device_printf(dev, "Found MII: %s\n", selected->name); + } + } + } + } + + return selected; +} + + int printf(const char *format, ...) { @@ -665,10 +545,3 @@ pmap_kextract(vm_offset_t virtualAddress) return (vm_paddr_t)entry.address; } - -status_t -init_compat_layer() -{ - __haiku_intr_spinlock = 0; - return B_OK; -} 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 df9ae53a97..0b773e0fed 100644 --- a/src/libs/compat/freebsd_network/compat/net/if_var.h +++ b/src/libs/compat/freebsd_network/compat/net/if_var.h @@ -186,8 +186,14 @@ struct ifnet { struct mtx if_addr_mtx; /* mutex to protect address lists */ /* Haiku additions */ - struct sockaddr_dl if_lladdr; - struct device *if_dev; + struct sockaddr_dl if_lladdr; + char device_name[128]; + struct device *root_device; + struct ifqueue receive_queue; + sem_id receive_sem; + sem_id link_state_sem; + int32 open_count; + int32 flags; }; typedef void if_init_f_t(void *); diff --git a/src/libs/compat/freebsd_network/compat/sys/bus.h b/src/libs/compat/freebsd_network/compat/sys/bus.h index 4b4a258044..e6d1f1ffcd 100644 --- a/src/libs/compat/freebsd_network/compat/sys/bus.h +++ b/src/libs/compat/freebsd_network/compat/sys/bus.h @@ -88,6 +88,13 @@ enum intr_type { #define FILTER_HANDLED B_HANDLED_INTERRUPT #define FILTER_SCHEDULE_THREAD B_INVOKE_SCHEDULER +/* Note that we reversed the original order, so whenever actual (negative) + numbers are used in a driver, we have to change it. */ +#define BUS_PROBE_SPECIFIC 0 +#define BUS_PROBE_LOW_PRIORITY 10 +#define BUS_PROBE_DEFAULT 20 +#define BUS_PROBE_GENERIC 100 + int bus_generic_detach(device_t dev); int bus_generic_suspend(device_t dev); int bus_generic_resume(device_t dev); @@ -136,6 +143,7 @@ void *device_get_ivars(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); int device_is_attached(device_t dev); +int device_attach(device_t dev); int bus_generic_print_child(device_t dev, device_t child); void bus_generic_driver_added(device_t dev, driver_t *driver); int bus_generic_attach(device_t dev); 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 50108d3874..60b0bde683 100644 --- a/src/libs/compat/freebsd_network/compat/sys/haiku-module.h +++ b/src/libs/compat/freebsd_network/compat/sys/haiku-module.h @@ -41,19 +41,16 @@ typedef struct { size_t softc_size; } driver_t; -#define BUS_PROBE_LOW_PRIORITY 10 -#define BUS_PROBE_DEFAULT 20 - #define DRIVER_MODULE_NAME(name, busname) \ - __fbsd_##name##busname + __fbsd_ ## name ## _ ## busname -status_t _fbsd_init_hardware(driver_t *); -status_t _fbsd_init_driver(driver_t *); -void _fbsd_uninit_driver(driver_t *); +status_t _fbsd_init_hardware(driver_t *driver); +status_t _fbsd_init_driver(driver_t *driver); +void _fbsd_uninit_driver(driver_t *driver); -extern const char gDriverName[]; +extern const char *gDriverName; driver_t *__haiku_select_miibus_driver(device_t dev); -driver_t *__haiku_probe_miibus(device_t dev, driver_t *drivers[], int count); +driver_t *__haiku_probe_miibus(device_t dev, driver_t *drivers[]); /* we define the driver methods with HAIKU_FBSD_DRIVER_GLUE to * force the rest of the stuff to be linked back with the driver. @@ -61,10 +58,10 @@ driver_t *__haiku_probe_miibus(device_t dev, driver_t *drivers[], int count); * the final binary, gcc 4.x rightfuly doesn't. */ #define HAIKU_FBSD_DRIVER_GLUE(publicname, name, busname) \ - extern const char *gDevNameList[]; \ + extern const char *gDeviceNameList[]; \ extern device_hooks gDeviceHooks; \ extern driver_t *DRIVER_MODULE_NAME(name, busname); \ - const char gDriverName[] = #publicname; \ + const char *gDriverName = #publicname; \ int32 api_version = B_CUR_DRIVER_API_VERSION; \ status_t init_hardware() \ { \ @@ -77,14 +74,14 @@ driver_t *__haiku_probe_miibus(device_t dev, driver_t *drivers[], int count); void uninit_driver() \ { _fbsd_uninit_driver(DRIVER_MODULE_NAME(name, busname)); } \ const char **publish_devices() \ - { return gDevNameList; } \ + { return gDeviceNameList; } \ device_hooks *find_device(const char *name) \ { return &gDeviceHooks; } -#define HAIKU_FBSD_RETURN_MII_DRIVER(drivers, count) \ +#define HAIKU_FBSD_RETURN_MII_DRIVER(drivers) \ driver_t *__haiku_select_miibus_driver(device_t dev) \ { \ - return __haiku_probe_miibus(dev, drivers, count); \ + return __haiku_probe_miibus(dev, drivers); \ } #define HAIKU_FBSD_MII_DRIVER(name) \ @@ -92,13 +89,14 @@ driver_t *__haiku_probe_miibus(device_t dev, driver_t *drivers[], int count); driver_t *__haiku_select_miibus_driver(device_t dev) \ { \ driver_t *drivers[] = { \ - DRIVER_MODULE_NAME(name, miibus) \ + DRIVER_MODULE_NAME(name, miibus), \ + NULL \ }; \ - return __haiku_probe_miibus(dev, drivers, 1); \ + return __haiku_probe_miibus(dev, drivers); \ } #define NO_HAIKU_FBSD_MII_DRIVER() \ - HAIKU_FBSD_RETURN_MII_DRIVER(NULL, 0) + HAIKU_FBSD_RETURN_MII_DRIVER(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 6569f64b28..4548d768ed 100644 --- a/src/libs/compat/freebsd_network/device.c +++ b/src/libs/compat/freebsd_network/device.c @@ -1,5 +1,6 @@ /* * Copyright 2007, Hugo Santos. All Rights Reserved. + * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. * Copyright 2004, Marcus Overhagen. All Rights Reserved. * * Distributed under the terms of the MIT License. @@ -20,142 +21,54 @@ #include -#define MAX_DEVICES 8 - - -struct network_device *gDevices[MAX_DEVICES]; -const char *gDevNameList[MAX_DEVICES + 1]; - - -static struct network_device * -allocate_device(driver_t *driver) -{ - char semName[64]; - - struct network_device *dev = malloc(sizeof(struct network_device)); - if (dev == NULL) - return NULL; - - memset(dev, 0, sizeof(struct device)); - - 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) { - uninit_device(DEVNET(dev)); - free(dev); - return NULL; - } - - dev->link_state_sem = -1; - - ifq_init(&dev->receive_queue, semName); - - return dev; -} - - -static void -free_device(struct network_device *dev) -{ - delete_sem(dev->receive_sem); - ifq_uninit(&dev->receive_queue); - uninit_device(DEVNET(dev)); - free(dev); -} - - -device_method_signature_t -_resolve_method(driver_t *driver, const char *name) -{ - device_method_signature_t method = NULL; - int i; - - for (i = 0; method == NULL && driver->methods[i].name != NULL; i++) { - if (strcmp(driver->methods[i].name, name) == 0) - method = driver->methods[i].method; - } - - return method; -} - - static status_t compat_open(const char *name, uint32 flags, void **cookie) { - struct network_device *device; - status_t status; + struct ifnet *ifp; + struct ifreq ifr; int i; - driver_printf("compat_open(%s, 0x%lx)\n", name, flags); - - status = get_module(NET_STACK_MODULE_NAME, (module_info **)&gStack); - if (status < B_OK) - return status; - - for (i = 0; gDevNameList[i] != NULL; i++) { - if (strcmp(gDevNameList[i], name) == 0) + for (i = 0; gDeviceNameList[i] != NULL; i++) { + if (strcmp(gDeviceNameList[i], name) == 0) break; } - if (gDevNameList[i] == NULL) + if (gDeviceNameList[i] == NULL) return B_ERROR; - device = gDevices[i]; + ifp = gDevices[i]; + if_printf(ifp, "compat_open(0x%lx)\n", flags); - if (!atomic_test_and_set(&device->open, 1, 0)) + if (!atomic_test_and_set(&ifp->open_count, 1, 0)) return B_BUSY; - /* some drivers expect the softc to be zero'ed out */ - memset(device->base.softc, 0, device->base.driver->softc_size); + ifp->if_flags &= ~IFF_UP; + ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); - status = DEVNET(device)->methods.attach(DEVNET(device)); - if (status != 0) - atomic_and(&device->open, 0); + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_media = IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0); + ifp->if_ioctl(ifp, SIOCSIFMEDIA, (caddr_t)&ifr); - driver_printf(" ... status = 0x%ld\n", status); + ifp->if_flags |= IFF_UP; + ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); - if (status == 0) { - struct ifnet *ifp = device->ifp; - struct ifreq ifr; + ifp->if_init(ifp->if_softc); - ifp->if_flags &= ~IFF_UP; - ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_media = IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0); - ifp->if_ioctl(ifp, SIOCSIFMEDIA, (caddr_t)&ifr); - - ifp->if_flags |= IFF_UP; - ifp->if_ioctl(ifp, SIOCSIFFLAGS, NULL); - - ifp->if_init(ifp->if_softc); - } - - *cookie = device; - return status; + *cookie = ifp; + return B_OK; } static status_t compat_close(void *cookie) { - struct network_device *dev = cookie; + struct ifnet *ifp = cookie; - device_printf(DEVNET(dev), "compat_close()\n"); + if_printf(ifp, "compat_close()\n"); - 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? */ - - release_sem_etc(dev->receive_sem, 1, B_RELEASE_ALL); + atomic_or(&ifp->flags, DEVICE_CLOSED); + release_sem_etc(ifp->receive_sem, 1, B_RELEASE_ALL); return B_OK; } @@ -163,17 +76,13 @@ compat_close(void *cookie) static status_t compat_free(void *cookie) { - struct network_device *dev = cookie; + struct ifnet *ifp = cookie; - device_printf(DEVNET(dev), "compat_free()\n"); + if_printf(ifp, "compat_free()\n"); - DEVNET(dev)->methods.detach(DEVNET(dev)); - - /* XXX empty out the send queue */ - - atomic_and(&dev->open, 0); - put_module(NET_STACK_MODULE_NAME); + /* TODO: empty out the send queue */ + atomic_and(&ifp->open_count, 0); return B_OK; } @@ -181,24 +90,24 @@ compat_free(void *cookie) static status_t compat_read(void *cookie, off_t position, void *buffer, size_t *numBytes) { - struct network_device *dev = cookie; + struct ifnet *ifp = cookie; uint32 semFlags = B_CAN_INTERRUPT; status_t status; struct mbuf *mb; size_t length; - //device_printf(DEVNET(dev), "compat_read(%lld, %p, [%lu])\n", position, + //if_printf(ifp, "compat_read(%lld, %p, [%lu])\n", position, // buffer, *numBytes); - if (DEVNET(dev)->flags & DEVICE_CLOSED) + if (ifp->flags & DEVICE_CLOSED) return B_INTERRUPTED; - if (DEVNET(dev)->flags & DEVICE_NON_BLOCK) + if (ifp->flags & DEVICE_NON_BLOCK) semFlags |= B_RELATIVE_TIMEOUT; do { - status = acquire_sem_etc(dev->receive_sem, 1, semFlags, 0); - if (DEVNET(dev)->flags & DEVICE_CLOSED) + status = acquire_sem_etc(ifp->receive_sem, 1, semFlags, 0); + if (ifp->flags & DEVICE_CLOSED) return B_INTERRUPTED; if (status == B_WOULD_BLOCK) { @@ -207,7 +116,7 @@ compat_read(void *cookie, off_t position, void *buffer, size_t *numBytes) } else if (status < B_OK) return status; - IF_DEQUEUE(&dev->receive_queue, mb); + IF_DEQUEUE(&ifp->receive_queue, mb); } while (mb == NULL); length = min_c(max_c((size_t)mb->m_len, 0), *numBytes); @@ -232,10 +141,10 @@ static status_t compat_write(void *cookie, off_t position, const void *buffer, size_t *numBytes) { - struct network_device *dev = cookie; + struct ifnet *ifp = cookie; struct mbuf *mb; - //device_printf(DEVNET(dev), "compat_write(%lld, %p, [%lu])\n", position, + //if_printf(ifp, "compat_write(%lld, %p, [%lu])\n", position, // buffer, *numBytes); mb = m_getcl(0, MT_DATA, M_PKTHDR); @@ -247,17 +156,16 @@ compat_write(void *cookie, off_t position, const void *buffer, mb->m_len = min_c(*numBytes, (size_t)MCLBYTES); memcpy(mtod(mb, void *), buffer, mb->m_len); - return dev->ifp->if_output(dev->ifp, mb, NULL, NULL); + return ifp->if_output(ifp, mb, NULL, NULL); } static status_t compat_control(void *cookie, uint32 op, void *arg, size_t length) { - struct network_device *dev = cookie; - struct ifnet *ifp = dev->ifp; + struct ifnet *ifp = cookie; - //device_printf(DEVNET(dev), "compat_control(op %lu, %p, [%lu])\n", op, + //if_printf(ifp, "compat_control(op %lu, %p, [%lu])\n", op, // arg, length); switch (op) { @@ -275,9 +183,9 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length) if (user_memcpy(&value, arg, sizeof(int32)) < B_OK) return B_BAD_ADDRESS; if (value) - DEVNET(dev)->flags |= DEVICE_NON_BLOCK; + ifp->flags |= DEVICE_NON_BLOCK; else - DEVNET(dev)->flags &= ~DEVICE_NON_BLOCK; + ifp->flags &= ~DEVICE_NON_BLOCK; return B_OK; } @@ -297,11 +205,12 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length) case ETHER_GETFRAMESIZE: { - uint32 frame_size; + uint32 frameSize; if (length < 4) return B_BAD_VALUE; - frame_size = dev->ifp->if_mtu + ETHER_HDR_LEN; - return user_memcpy(arg, &frame_size, 4); + + frameSize = ifp->if_mtu + ETHER_HDR_LEN; + return user_memcpy(arg, &frameSize, 4); } case ETHER_ADDMULTI: @@ -309,7 +218,7 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length) { struct sockaddr_dl address; - if (!(ifp->if_flags & IFF_MULTICAST) == 0) + if ((ifp->if_flags & IFF_MULTICAST) == 0) return EOPNOTSUPP; memset(&address, 0, sizeof(address)); @@ -351,8 +260,8 @@ compat_control(void *cookie, uint32 op, void *arg, size_t length) } case ETHER_SET_LINK_STATE_SEM: - if (user_memcpy(&dev->link_state_sem, arg, sizeof(sem_id)) < B_OK) { - dev->link_state_sem = -1; + if (user_memcpy(&ifp->link_state_sem, arg, sizeof(sem_id)) < B_OK) { + ifp->link_state_sem = -1; return B_BAD_ADDRESS; } return B_OK; @@ -371,160 +280,3 @@ device_hooks gDeviceHooks = { compat_write, }; - -status_t -_fbsd_init_hardware(driver_t *driver) -{ - struct network_device fakeDevice; - device_probe_t *probe; - 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; - - probe = (device_probe_t *)_resolve_method(driver, "device_probe"); - if (probe == NULL) { - dprintf("%s: driver has no device_probe method.\n", gDriverName); - return B_ERROR; - } - - memset(&fakeDevice, 0, sizeof(struct device)); - - // Some drivers, like the rtl8139 one require softc to be initialized - // before probe() is called. - // TODO(bga): Check if the fact that whatever initialization that is - // made here is essential as fakeDevice is local to this function and - // ceases to exist after we return. - DEVNET(&fakeDevice)->softc = malloc(driver->softc_size); - if (DEVNET(&fakeDevice)->softc == NULL) - return B_NO_MEMORY; - - for (i = 0; gPci->get_nth_pci_info(i, &fakeDevice.pci_info) == B_OK; i++) { - int result; - result = probe(DEVNET(&fakeDevice)); - if (result >= 0) { - dprintf("%s, found %s at %d\n", gDriverName, - device_get_desc(DEVNET(&fakeDevice)), i); - if (DEVNET(&fakeDevice)->flags & DEVICE_DESC_ALLOCED) - free((char *)DEVNET(&fakeDevice)->description); - put_module(B_PCI_MODULE_NAME); - - // Clean up softc. - free(DEVNET(&fakeDevice)->softc); - return B_OK; - } - } - - dprintf("%s: no hardware found.\n", gDriverName); - put_module(B_PCI_MODULE_NAME); - - // Clean up softc. - free(DEVNET(&fakeDevice)->softc); - - return B_ERROR; -} - - -status_t -_fbsd_init_driver(driver_t *driver) -{ - int i, ncards = 0; - status_t status; - struct network_device *dev; - - dprintf("%s: init_driver(%p)\n", gDriverName, driver); - - status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci); - if (status < B_OK) { - driver_printf("Failed to load PCI module.\n"); - return status; - } - - dev = allocate_device(driver); - if (dev == NULL) - goto err_1; - - status = init_compat_layer(); - if (status < B_OK) - goto err_2; - - status = init_mutexes(); - if (status < B_OK) - goto err_3; - - if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) { - status = init_taskqueues(); - if (status < B_OK) - goto err_4; - } - - status = init_mbufs(); - if (status < B_OK) - goto err_5; - - init_bounce_pages(); - - for (i = 0; dev != NULL - && gPci->get_nth_pci_info(i, &dev->pci_info) == B_OK; i++) { - device_t base = DEVNET(dev); - - if (base->methods.probe(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] = device_get_name(base); - - ncards++; - if (ncards < MAX_DEVICES) - dev = allocate_device(driver); - else - dev = NULL; - } - } - - if (dev != NULL) - free_device(dev); - - dprintf("%s, ... %d cards.\n", gDriverName, ncards); - - gDevNameList[ncards + 1] = NULL; - - return B_OK; - -err_5: - if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) - uninit_taskqueues(); -err_4: - uninit_mutexes(); -err_3: -err_2: - free(dev); -err_1: - put_module(B_PCI_MODULE_NAME); - return status; -} - - -void -_fbsd_uninit_driver(driver_t *driver) -{ - int i; - - dprintf("%s: uninit_driver(%p)\n", gDriverName, driver); - - for (i = 0; gDevNameList[i] != NULL; i++) { - free_device(gDevices[i]); - } - - uninit_bounce_pages(); - uninit_mbufs(); - if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) - uninit_taskqueues(); - uninit_mutexes(); - - 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 5805122630..fe1d6ab379 100644 --- a/src/libs/compat/freebsd_network/device.h +++ b/src/libs/compat/freebsd_network/device.h @@ -1,14 +1,13 @@ /* + * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. * Copyright 2007, Hugo Santos. All Rights Reserved. + * Copyright 2004, Marcus Overhagen. 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_ +#ifndef DEVICE_H +#define DEVICE_H + #include #include @@ -24,22 +23,26 @@ #include #include + +#define MAX_DEVICES 8 + struct ifnet; struct device { - struct device * parent; - char dev_name[128]; + struct device *parent; + struct device *root; driver_t *driver; struct list children; int32 flags; + char device_name[128]; int unit; char nameunit[64]; - const char * description; - void * softc; - void * ivars; + const char *description; + void *softc; + void *ivars; struct { int (*probe)(device_t dev); @@ -59,35 +62,27 @@ struct device { struct list_link link; }; - -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; +struct root_device_softc { + struct pci_info pci_info; }; - -#define DEVNET(dev) ((device_t)(&(dev)->base)) -#define NETDEV(base) ((struct network_device *)(base)) - - enum { DEVICE_OPEN = 1 << 0, DEVICE_CLOSED = 1 << 1, DEVICE_NON_BLOCK = 1 << 2, DEVICE_DESC_ALLOCED = 1 << 3, + DEVICE_ATTACHED = 1 << 4 }; +extern struct net_stack_module_info *gStack; +extern pci_module_info *gPci; + +extern const char *gDeviceNameList[]; +extern struct ifnet *gDevices[]; +extern int32 gDeviceCount; + + static inline void __unimplemented(const char *method) { @@ -105,11 +100,11 @@ void uninit_mbufs(void); status_t init_mutexes(void); void uninit_mutexes(void); -status_t init_compat_layer(void); - status_t init_taskqueues(void); void uninit_taskqueues(void); +device_t find_root_device(int unit); + /* busdma_machdep.c */ void init_bounce_pages(void); void uninit_bounce_pages(void); @@ -121,17 +116,7 @@ void driver_vprintf(const char *format, va_list vl); void device_sprintf_name(device_t dev, const char *format, ...) __attribute__ ((format (__printf__, 2, 3))); -device_t init_device(device_t dev, driver_t *driver); -void uninit_device(device_t dev); -device_method_signature_t _resolve_method(driver_t *driver, const char *name); - 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 const char *gDevNameList[]; -extern struct network_device *gDevices[]; - -#endif +#endif /* DEVICE_H */ diff --git a/src/libs/compat/freebsd_network/driver.c b/src/libs/compat/freebsd_network/driver.c new file mode 100644 index 0000000000..533d452c7d --- /dev/null +++ b/src/libs/compat/freebsd_network/driver.c @@ -0,0 +1,224 @@ +/* + * Copyright 2007, Hugo Santos. All Rights Reserved. + * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. + * Copyright 2004, Marcus Overhagen. All Rights Reserved. + * + * Distributed under the terms of the MIT License. + */ + +/*! Driver functions that adapt the FreeBSD driver to Haiku's driver API. + The actual driver functions are exported by the HAIKU_FBSD_DRIVER_GLUE + macro, and just call the functions here. +*/ + + +#include "device.h" + +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#define TRACE_DRIVER +#ifdef TRACE_DRIVER +# define TRACE(x) dprintf x +#else +# define TRACE(x) +#endif + + +const char *gDeviceNameList[MAX_DEVICES + 1]; +struct ifnet *gDevices[MAX_DEVICES]; +int32 gDeviceCount; + + +static status_t +init_root_device(driver_t *driver, device_t *_root, device_t *_child) +{ + device_t child; + + device_t root = device_add_child(NULL, NULL, 0); + if (root == NULL) + return B_NO_MEMORY; + + root->softc = malloc(sizeof(struct root_device_softc)); + if (root->softc == NULL) { + device_delete_child(NULL, root); + return B_NO_MEMORY; + } + + child = device_add_child(root, driver->name, 0); + if (child == NULL) { + device_delete_child(NULL, root); + return B_ERROR; + } + + if (_root != NULL) + *_root = root; + if (_child != NULL) + *_child = child; + + return B_OK; +} + + +static pci_info * +get_pci_info(struct device *device) +{ + return &((struct root_device_softc *)device->softc)->pci_info; +} + + +// #pragma mark - Haiku Driver API + + +status_t +_fbsd_init_hardware(driver_t *driver) +{ + status_t status = B_ENTRY_NOT_FOUND; + device_t child, root; + pci_info *info; + int i; + + if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPci) < B_OK) + return B_ERROR; + + if (init_root_device(driver, &root, &child) != B_OK) { + dprintf("%s: creating device failed.\n", gDriverName); + put_module(B_PCI_MODULE_NAME); + return B_ERROR; + } + + TRACE(("%s: init_hardware(%p)\n", gDriverName, driver)); + + if (child->methods.probe == NULL) { + dprintf("%s: driver has no device_probe method.\n", gDriverName); + device_delete_child(NULL, root); + put_module(B_PCI_MODULE_NAME); + return B_ERROR; + } + + info = get_pci_info(root); + + for (i = 0; gPci->get_nth_pci_info(i, info) == B_OK; i++) { + int result; + result = child->methods.probe(child); + if (result >= 0) { + TRACE(("%s, found %s at %d\n", gDriverName, + device_get_desc(child), i)); + status = B_OK; + break; + } + } + + if (status < B_OK) + TRACE(("%s: no hardware found.\n", gDriverName)); + + device_delete_child(NULL, root); + put_module(B_PCI_MODULE_NAME); + + return status; +} + + +status_t +_fbsd_init_driver(driver_t *driver) +{ + int i, found = 0; + status_t status; + + dprintf("%s: init_driver(%p)\n", gDriverName, driver); + + status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci); + if (status < B_OK) + return status; + + status = init_mutexes(); + if (status < B_OK) + goto err1; + + status = init_mbufs(); + if (status < B_OK) + goto err2; + + init_bounce_pages(); + + if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) { + status = init_taskqueues(); + if (status < B_OK) + goto err3; + } + + i = 0; + + while (gDeviceCount < MAX_DEVICES) { + device_t root, device; + bool found = false; + pci_info *info; + + status = init_root_device(driver, &root, &device); + if (status < B_OK) + break; + + info = get_pci_info(root); + + for (; gPci->get_nth_pci_info(i, info) == B_OK; i++) { + if (device->methods.probe(device) < 0) + continue; + + if (device_attach(device) == 0) { + found = true; + break; + } + } + + if (!found) { + device_delete_child(NULL, root); + break; + } + } + + if (gDeviceCount > 0) { + TRACE(("%s, ... %d cards.\n", gDriverName, found)); + return B_OK; + } else if (status == B_OK) + status = B_ERROR; + + if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) + uninit_taskqueues(); +err3: + uninit_mbufs(); +err2: + uninit_mutexes(); +err1: + put_module(B_PCI_MODULE_NAME); + return status; +} + + +void +_fbsd_uninit_driver(driver_t *driver) +{ + int i; + + TRACE(("%s: uninit_driver(%p)\n", gDriverName, driver)); + + for (i = 0; gDeviceNameList[i] != NULL; i++) { + device_delete_child(NULL, gDevices[i]->root_device); + } + + uninit_bounce_pages(); + uninit_mbufs(); + if (HAIKU_DRIVER_REQUIRES(FBSD_TASKQUEUES)) + uninit_taskqueues(); + uninit_mutexes(); + + put_module(B_PCI_MODULE_NAME); +} diff --git a/src/libs/compat/freebsd_network/fbsd_mii.c b/src/libs/compat/freebsd_network/fbsd_mii.c index b894e4e09c..75cbc77615 100644 --- a/src/libs/compat/freebsd_network/fbsd_mii.c +++ b/src/libs/compat/freebsd_network/fbsd_mii.c @@ -173,8 +173,11 @@ miibus_attach(device_t dev) struct mii_data *mii; mii = device_get_softc(dev); - - mii->mii_ifp = NETDEV(device_get_parent(dev))->ifp; + /* + * Note that each NIC's softc must start with an ifnet pointer. + * XXX: EVIL HACK! + */ + mii->mii_ifp = *(struct ifnet**)device_get_softc(device_get_parent(dev)); v = device_get_ivars(dev); ifmedia_upd = v[0]; ifmedia_sts = v[1]; @@ -247,7 +250,11 @@ miibus_statchg(device_t dev) mii = device_get_softc(dev); - ifp = NETDEV(parent)->ifp; + /* + * Note that each NIC's softc must start with an ifnet pointer. + * XXX: EVIL HACK! + */ + ifp = *(struct ifnet **)device_get_softc(parent); ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active); return; } @@ -272,7 +279,11 @@ miibus_linkchg(device_t dev) } else link_state = LINK_STATE_UNKNOWN; - if_link_state_change(NETDEV(parent)->ifp, link_state); + /* + * Note that each NIC's softc must start with an ifnet pointer. + * XXX: EVIL HACK! + */ + if_link_state_change(*(struct ifnet**)device_get_softc(parent), link_state); } static void diff --git a/src/libs/compat/freebsd_network/if.c b/src/libs/compat/freebsd_network/if.c index 851fea3aca..3e10055475 100644 --- a/src/libs/compat/freebsd_network/if.c +++ b/src/libs/compat/freebsd_network/if.c @@ -1,13 +1,12 @@ /* * Copyright 2007, Hugo Santos. All Rights Reserved. + * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. + * Copyright 2004, Marcus Overhagen. 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 @@ -24,25 +23,43 @@ #include + struct ifnet * if_alloc(u_char type) { + char semName[64]; + struct ifnet *ifp = _kernel_malloc(sizeof(struct ifnet), M_ZERO); if (ifp == NULL) return NULL; + snprintf(semName, sizeof(semName), "%s receive", gDriverName); + + ifp->receive_sem = create_sem(0, semName); + if (ifp->receive_sem < B_OK) + goto err1; + if (type == IFT_ETHER) { ifp->if_l2com = _kernel_malloc(sizeof(struct arpcom), M_ZERO); - if (ifp->if_l2com == NULL) { - _kernel_free(ifp); - return NULL; - } + if (ifp->if_l2com == NULL) + goto err2; + IFP2AC(ifp)->ac_ifp = ifp; } + ifp->link_state_sem = -1; + ifp->flags = 0; + ifq_init(&ifp->receive_queue, semName); + ifp->if_type = type; IF_ADDR_LOCK_INIT(ifp); return ifp; + +err2: + delete_sem(ifp->receive_sem); +err1: + _kernel_free(ifp); + return NULL; } @@ -53,6 +70,9 @@ if_free(struct ifnet *ifp) if (ifp->if_type == IFT_ETHER) _kernel_free(ifp->if_l2com); + delete_sem(ifp->receive_sem); + ifq_uninit(&ifp->receive_queue); + _kernel_free(ifp); } @@ -60,28 +80,29 @@ if_free(struct ifnet *ifp) void if_initname(struct ifnet *ifp, const char *name, int unit) { - int i; - dprintf("if_initname(%p, %s, %d)\n", ifp, name, unit); if (name == NULL) panic("interface goes unamed"); + if (gDeviceCount >= MAX_DEVICES) + panic("unit too large"); + ifp->if_dname = name; ifp->if_dunit = unit; + ifp->if_index = gDeviceCount++; strlcpy(ifp->if_xname, name, sizeof(ifp->if_xname)); - for (i = 0; gDevNameList[i] != NULL; i++) { - if (strcmp(gDevNameList[i], name) == 0) - break; - } + snprintf(ifp->device_name, sizeof(ifp->device_name), "net/%s/%i", + gDriverName, ifp->if_index); - if (gDevNameList[i] == NULL) - panic("unknown interface"); + driver_printf("%s: /dev/%s\n", gDriverName, ifp->device_name); - ifp->if_dev = DEVNET(gDevices[i]); - gDevices[i]->ifp = ifp; + gDeviceNameList[ifp->if_index] = ifp->device_name; + gDevices[ifp->if_index] = ifp; + + ifp->root_device = find_root_device(unit); } @@ -146,21 +167,19 @@ if_printf(struct ifnet *ifp, const char *format, ...) vsnprintf(buf, sizeof(buf), format, vl); va_end(vl); - dprintf("[%s] %s", ifp->if_xname, buf); + dprintf("[%s] %s", ifp->device_name, buf); return 0; } void -if_link_state_change(struct ifnet *ifp, int link_state) +if_link_state_change(struct ifnet *ifp, int linkState) { - if (ifp->if_link_state == link_state) + if (ifp->if_link_state == linkState) return; - ifp->if_link_state = link_state; - - release_sem_etc(NETDEV(ifp->if_dev)->link_state_sem, 1, - B_DO_NOT_RESCHEDULE); + ifp->if_link_state = linkState; + release_sem_etc(ifp->link_state_sem, 1, B_DO_NOT_RESCHEDULE); } @@ -281,10 +300,8 @@ ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, static void ether_input(struct ifnet *ifp, struct mbuf *m) { - device_t dev = ifp->if_dev; - - IF_ENQUEUE(&NETDEV(dev)->receive_queue, m); - release_sem_etc(NETDEV(dev)->receive_sem, 1, B_DO_NOT_RESCHEDULE); + IF_ENQUEUE(&ifp->receive_queue, m); + release_sem_etc(ifp->receive_sem, 1, B_DO_NOT_RESCHEDULE); } diff --git a/src/libs/compat/freebsd_network/pci.c b/src/libs/compat/freebsd_network/pci.c new file mode 100644 index 0000000000..33084acb8a --- /dev/null +++ b/src/libs/compat/freebsd_network/pci.c @@ -0,0 +1,206 @@ +/* + * Copyright 2007, Hugo Santos, hugosantos@gmail.com. All Rights Reserved. + * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. + * Copyright 2004, Marcus Overhagen. All Rights Reserved. + * + * Distributed under the terms of the MIT License. + */ + +#include "device.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +//#define DEBUG_PCI +#ifdef DEBUG_PCI +# define TRACE_PCI(dev, format, args...) device_printf(dev, format , ##args) +#else +# define TRACE_PCI(dev, format, args...) do { } while (0) +#endif + + +uint32_t +pci_read_config(device_t dev, int offset, int size) +{ + pci_info *info = &((struct root_device_softc *)dev->root->softc)->pci_info; + + uint32_t value = gPci->read_pci_config(info->bus, info->device, + info->function, offset, size); + TRACE_PCI(dev, "pci_read_config(%i, %i) = 0x%x\n", offset, size, value); + return value; +} + + +void +pci_write_config(device_t dev, int offset, uint32_t value, int size) +{ + pci_info *info = &((struct root_device_softc *)dev->root->softc)->pci_info; + + TRACE_PCI(dev, "pci_write_config(%i, 0x%x, %i)\n", offset, value, size); + + gPci->write_pci_config(info->bus, info->device, info->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); +} + + +uint16_t +pci_get_subvendor(device_t dev) +{ + return pci_read_config(dev, PCI_subsystem_vendor_id, 2); +} + + +uint16_t +pci_get_subdevice(device_t dev) +{ + return pci_read_config(dev, PCI_subsystem_id, 2); +} + + +uint8_t +pci_get_revid(device_t dev) +{ + return pci_read_config(dev, PCI_revision, 1); +} + + +static void +pci_set_command_bit(device_t dev, uint16_t bit) +{ + uint16_t command = pci_read_config(dev, PCI_command, 2); + pci_write_config(dev, PCI_command, command | bit, 2); +} + + +int +pci_enable_busmaster(device_t dev) +{ + pci_set_command_bit(dev, PCI_command_master); + return 0; +} + + +int +pci_enable_io(device_t dev, int space) +{ + /* adapted from FreeBSD's pci_enable_io_method */ + 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 +pci_find_extcap(device_t child, int capability, int *_capabilityRegister) +{ + uint8 capabilityPointer; + uint8 headerType; + uint16 status; + + status = pci_read_config(child, PCIR_STATUS, 2); + if ((status & PCIM_STATUS_CAPPRESENT) == 0) + return ENXIO; + + headerType = pci_read_config(child, PCI_header_type, 1); + switch (headerType & PCIM_HDRTYPE) { + case 0: + case 1: + capabilityPointer = PCIR_CAP_PTR; + break; + case 2: + capabilityPointer = PCIR_CAP_PTR_2; + break; + default: + return ENXIO; + } + capabilityPointer = pci_read_config(child, capabilityPointer, 1); + + while (capabilityPointer != 0) { + if (pci_read_config(child, capabilityPointer + PCICAP_ID, 1) + == capability) { + if (_capabilityRegister != NULL) + *_capabilityRegister = capabilityPointer; + return 0; + } + capabilityPointer = pci_read_config(child, + capabilityPointer + PCICAP_NEXTPTR, 1); + } + + return ENOENT; +} + + +int +pci_msi_count(device_t dev) +{ + return 0; +} + + +int +pci_alloc_msi(device_t dev, int *count) +{ + return ENODEV; +} + + +int +pci_release_msi(device_t dev) +{ + return ENODEV; +} + + +int +pci_msix_count(device_t dev) +{ + return 0; +} + + +int +pci_alloc_msix(device_t dev, int *count) +{ + return ENODEV; +} +