freebsd_network: Adjust and rewrite attach code for USB support.

init_hardware now takes 2 devices arrays: one for PCI and one for USB
drivers, respectively.

The few drivers that have their own __haiku_handle_fbsd_drivers_list
are also adjusted at the same time.
This commit is contained in:
Augustin Cavalier 2022-02-24 21:15:10 -05:00
parent 2e9f01f60d
commit 423ee7c669
8 changed files with 208 additions and 87 deletions

View File

@ -33,14 +33,14 @@ extern driver_t *DRIVER_MODULE_NAME(dc, pci);
extern driver_t *DRIVER_MODULE_NAME(de, pci); extern driver_t *DRIVER_MODULE_NAME(de, pci);
status_t status_t
__haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[])) __haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]))
{ {
driver_t *drivers[] = { driver_t *drivers[] = {
DRIVER_MODULE_NAME(dc, pci), DRIVER_MODULE_NAME(dc, pci),
DRIVER_MODULE_NAME(de, pci), DRIVER_MODULE_NAME(de, pci),
NULL NULL
}; };
return (*handler)(drivers); return (*handler)(drivers, NULL);
} }

View File

@ -18,12 +18,12 @@ NO_HAIKU_REENABLE_INTERRUPTS();
status_t status_t
__haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[])) __haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]))
{ {
driver_t *drivers[] = { driver_t *drivers[] = {
DRIVER_MODULE_NAME(em, pci), DRIVER_MODULE_NAME(em, pci),
DRIVER_MODULE_NAME(igb, pci), DRIVER_MODULE_NAME(igb, pci),
NULL NULL
}; };
return (*handler)(drivers); return (*handler)(drivers, NULL);
} }

View File

@ -46,14 +46,14 @@ extern driver_t *DRIVER_MODULE_NAME(pcn, pci);
status_t status_t
__haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[])) __haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]))
{ {
driver_t *drivers[] = { driver_t *drivers[] = {
DRIVER_MODULE_NAME(le, pci), DRIVER_MODULE_NAME(le, pci),
DRIVER_MODULE_NAME(pcn, pci), DRIVER_MODULE_NAME(pcn, pci),
NULL NULL
}; };
return (*handler)(drivers); return (*handler)(drivers, NULL);
} }

View File

@ -14,15 +14,6 @@ SubDirCcFlags [ FDefines _KERNEL=1 ] ;
SubDirC++Flags [ FDefines _KERNEL=1 ] ; SubDirC++Flags [ FDefines _KERNEL=1 ] ;
KernelStaticLibrary libfreebsd_network.a : KernelStaticLibrary libfreebsd_network.a :
bus.cpp
bus_dma.cpp
callout.cpp
clock.c
condvar.cpp
device.c
device_hooks.c
driver.c
eventhandler.c
fbsd_ether.c fbsd_ether.c
fbsd_if_media.c fbsd_if_media.c
fbsd_kern_mbuf.c fbsd_kern_mbuf.c
@ -34,6 +25,19 @@ KernelStaticLibrary libfreebsd_network.a :
fbsd_subr_bufring.c fbsd_subr_bufring.c
fbsd_subr_sbuf.c fbsd_subr_sbuf.c
fbsd_time.c fbsd_time.c
fbsd_usb_error.c
fbsd_usb_util.c
fbsd_usb_lookup.c
bus.cpp
bus_dma.cpp
callout.cpp
clock.c
condvar.cpp
device.c
device_hooks.c
driver.c
eventhandler.c
firmware.c firmware.c
if.c if.c
libkern.cpp libkern.cpp
@ -50,6 +54,8 @@ KernelStaticLibrary libfreebsd_network.a :
sysinit.c sysinit.c
taskqueue.c taskqueue.c
unit.cpp unit.cpp
usb.cpp
usb_util.c
; ;
rule MIIHeaderGen rule MIIHeaderGen

View File

@ -80,14 +80,14 @@ typedef struct {
__fbsd_ ## name ## _ ## busname __fbsd_ ## name ## _ ## busname
status_t _fbsd_init_hardware(driver_t *driver[]); status_t _fbsd_init_hardware(driver_t* pci_drivers[], driver_t* uhub_drivers[]);
status_t _fbsd_init_drivers(driver_t *driver[]); status_t _fbsd_init_drivers();
status_t _fbsd_uninit_drivers(driver_t *driver[]); status_t _fbsd_uninit_drivers();
extern const char *gDriverName; extern const char *gDriverName;
driver_t *__haiku_select_miibus_driver(device_t dev); driver_t *__haiku_select_miibus_driver(device_t dev);
driver_t *__haiku_probe_miibus(device_t dev, driver_t *drivers[]); driver_t *__haiku_probe_miibus(device_t dev, driver_t *drivers[]);
status_t __haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[])); status_t __haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]));
status_t init_wlan_stack(void); status_t init_wlan_stack(void);
void uninit_wlan_stack(void); void uninit_wlan_stack(void);
@ -112,11 +112,11 @@ status_t wlan_close(void*);
} \ } \
status_t init_driver() \ status_t init_driver() \
{ \ { \
return __haiku_handle_fbsd_drivers_list(_fbsd_init_drivers); \ return _fbsd_init_drivers(); \
} \ } \
void uninit_driver() \ void uninit_driver() \
{ \ { \
__haiku_handle_fbsd_drivers_list(_fbsd_uninit_drivers); \ _fbsd_uninit_drivers(); \
} \ } \
const char **publish_devices() \ const char **publish_devices() \
{ return gDeviceNameList; } \ { return gDeviceNameList; } \
@ -140,12 +140,12 @@ status_t wlan_close(void*);
#define HAIKU_FBSD_DRIVER_GLUE(publicname, name, busname) \ #define HAIKU_FBSD_DRIVER_GLUE(publicname, name, busname) \
extern driver_t* DRIVER_MODULE_NAME(name, busname); \ extern driver_t* DRIVER_MODULE_NAME(name, busname); \
status_t __haiku_handle_fbsd_drivers_list(status_t (*proc)(driver_t *[])) {\ status_t __haiku_handle_fbsd_drivers_list(status_t (*proc)(driver_t *[], driver_t *[])) {\
driver_t *drivers[] = { \ driver_t *drivers[] = { \
DRIVER_MODULE_NAME(name, busname), \ DRIVER_MODULE_NAME(name, busname), \
NULL \ NULL \
}; \ }; \
return (*proc)(drivers); \ return (*proc)(drivers, NULL); \
} \ } \
HAIKU_FBSD_DRIVERS_GLUE(publicname); HAIKU_FBSD_DRIVERS_GLUE(publicname);
@ -154,12 +154,12 @@ status_t wlan_close(void*);
#define HAIKU_FBSD_WLAN_DRIVER_GLUE(publicname, name, busname) \ #define HAIKU_FBSD_WLAN_DRIVER_GLUE(publicname, name, busname) \
extern driver_t *DRIVER_MODULE_NAME(name, busname); \ extern driver_t *DRIVER_MODULE_NAME(name, busname); \
status_t __haiku_handle_fbsd_drivers_list(status_t (*proc)(driver_t *[])) {\ status_t __haiku_handle_fbsd_drivers_list(status_t (*proc)(driver_t *[], driver_t *[])) {\
driver_t *drivers[] = { \ driver_t *drivers[] = { \
DRIVER_MODULE_NAME(name, busname), \ DRIVER_MODULE_NAME(name, busname), \
NULL \ NULL \
}; \ }; \
return (*proc)(drivers); \ return (*proc)(drivers, NULL); \
} \ } \
HAIKU_FBSD_WLAN_DRIVERS_GLUE(publicname); HAIKU_FBSD_WLAN_DRIVERS_GLUE(publicname);

View File

@ -29,13 +29,21 @@ extern "C" {
#endif #endif
struct root_device_softc { struct root_device_softc {
enum {
BUS_INVALID = 0,
BUS_pci,
BUS_uhub,
} bus;
struct pci_info pci_info; struct pci_info pci_info;
bool is_msi; bool is_msi;
bool is_msix; bool is_msix;
struct freebsd_usb_device* usb_dev;
}; };
enum { enum {
DEVICE_OPEN = 1 << 0, DEVICE_OPEN = 1 << 0,
DEVICE_CLOSED = 1 << 1, DEVICE_CLOSED = 1 << 1,
DEVICE_NON_BLOCK = 1 << 2, DEVICE_NON_BLOCK = 1 << 2,
DEVICE_DESC_ALLOCED = 1 << 3, DEVICE_DESC_ALLOCED = 1 << 3,

View File

@ -1,17 +1,10 @@
/* /*
* Copyright 2007, Hugo Santos. All Rights Reserved. * Copyright 2007-2010, Axel Dörfler. All rights reserved.
* Copyright 2007, Axel Dörfler, axeld@pinc-software.de. All Rights Reserved. * Copyright 2009-2022, Haiku, Inc. All rights reserved.
* Copyright 2004, Marcus Overhagen. All Rights Reserved.
* Distributed under the terms of the MIT License. * 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 "device.h"
#include "sysinit.h" #include "sysinit.h"
@ -20,7 +13,6 @@
#include <Drivers.h> #include <Drivers.h>
#include <ether_driver.h> #include <ether_driver.h>
#include <PCI_x86.h>
#include <compat/sys/haiku-module.h> #include <compat/sys/haiku-module.h>
@ -28,6 +20,10 @@
#include <compat/sys/mbuf.h> #include <compat/sys/mbuf.h>
#include <compat/net/ethernet.h> #include <compat/net/ethernet.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usb_device.h>
//#define TRACE_DRIVER //#define TRACE_DRIVER
#ifdef TRACE_DRIVER #ifdef TRACE_DRIVER
@ -39,7 +35,10 @@
static struct { static struct {
driver_t* driver; driver_t* driver;
pci_info info; int bus;
struct pci_info pci_info;
struct freebsd_usb_device usb_dev;
struct usb_attach_arg uaa;
} sProbedDevices[MAX_DEVICES]; } sProbedDevices[MAX_DEVICES];
const char* gDeviceNameList[MAX_DEVICES + 1]; const char* gDeviceNameList[MAX_DEVICES + 1];
@ -48,12 +47,17 @@ int32 gDeviceCount;
static status_t static status_t
init_root_device(device_t *_root) init_root_device(device_t *_root, int bus_type)
{ {
static driver_t sRootDriver = { static driver_t sRootDriverPCI = {
"pci", "pci",
NULL, NULL,
sizeof(struct root_device_softc) sizeof(struct root_device_softc),
};
static driver_t sRootDriverUSB = {
"uhub",
NULL,
sizeof(struct root_device_softc),
}; };
device_t root = device_add_child(NULL, NULL, 0); device_t root = device_add_child(NULL, NULL, 0);
@ -67,7 +71,15 @@ init_root_device(device_t *_root)
} }
bzero(root->softc, sizeof(struct root_device_softc)); bzero(root->softc, sizeof(struct root_device_softc));
root->driver = &sRootDriver;
if (bus_type == BUS_pci)
root->driver = &sRootDriverPCI;
else if (bus_type == BUS_uhub)
root->driver = &sRootDriverUSB;
else
panic("unknown bus type");
((struct root_device_softc*)root->softc)->bus = bus_type;
root->root = root; root->root = root;
if (_root != NULL) if (_root != NULL)
@ -81,9 +93,8 @@ static status_t
add_child_device(driver_t* driver, device_t root, device_t* _child) add_child_device(driver_t* driver, device_t root, device_t* _child)
{ {
device_t child = device_add_child_driver(root, driver->name, driver, 0); device_t child = device_add_child_driver(root, driver->name, driver, 0);
if (child == NULL) { if (child == NULL)
return B_ERROR; return B_ERROR;
}
if (_child != NULL) if (_child != NULL)
*_child = child; *_child = child;
@ -92,43 +103,50 @@ add_child_device(driver_t* driver, device_t root, device_t* _child)
} }
static pci_info * static void
get_pci_info(struct device *device) uninit_probed_devices()
{ {
return &((struct root_device_softc *)device->softc)->pci_info; for (int p = 0; sProbedDevices[p].bus != BUS_INVALID; p++) {
if (sProbedDevices[p].bus == BUS_pci) {
gPci->unreserve_device(sProbedDevices[p].pci_info.bus,
sProbedDevices[p].pci_info.device, sProbedDevices[p].pci_info.function,
gDriverName, NULL);
} else if (sProbedDevices->bus == BUS_uhub) {
usb_cleanup_device(&sProbedDevices[p].usb_dev);
}
}
} }
// #pragma mark - Haiku Driver API // #pragma mark - Haiku Driver API
status_t static status_t
_fbsd_init_hardware(driver_t *drivers[]) init_hardware_pci(driver_t* drivers[])
{ {
status_t status; status_t status;
int i = 0, p = 0, index = 0; int i = 0;
pci_info* info; pci_info* info;
device_t root; device_t root;
status = get_module(B_PCI_MODULE_NAME, (module_info **)&gPci); int p = 0;
while (sProbedDevices[p].bus != BUS_INVALID)
p++;
status = init_pci(); status = init_pci();
if (status != B_OK) if (status != B_OK)
return status; return status;
status = init_root_device(&root); status = init_root_device(&root, BUS_pci);
if (status != B_OK) if (status != B_OK)
return status; return status;
for (p = 0; p <= MAX_DEVICES; p++) bool found = false;
sProbedDevices[i].driver = NULL; for (info = get_device_pci_info(root); gPci->get_nth_pci_info(i, info) == B_OK; i++) {
p = 0;
for (info = get_pci_info(root); gPci->get_nth_pci_info(i, info) == B_OK;
i++) {
int best = 0; int best = 0;
driver_t* driver = NULL; driver_t* driver = NULL;
for (index = 0; drivers[index] && gDeviceCount < MAX_DEVICES; index++) { for (int index = 0; drivers[index] != NULL; index++) {
int result; int result;
device_t device = NULL; device_t device = NULL;
status = add_child_device(drivers[index], root, &device); status = add_child_device(drivers[index], root, &device);
@ -155,14 +173,17 @@ _fbsd_init_hardware(driver_t *drivers[])
gDriverName, info->bus, info->device, info->function); gDriverName, info->bus, info->device, info->function);
continue; continue;
} }
sProbedDevices[p].bus = BUS_pci;
sProbedDevices[p].driver = driver; sProbedDevices[p].driver = driver;
sProbedDevices[p].info = *info; sProbedDevices[p].pci_info = *info;
found = true;
p++; p++;
} }
sProbedDevices[p].bus = BUS_INVALID;
device_delete_child(NULL, root); device_delete_child(NULL, root);
if (p > 0) if (found)
return B_OK; return B_OK;
uninit_pci(); uninit_pci();
@ -170,13 +191,102 @@ _fbsd_init_hardware(driver_t *drivers[])
} }
status_t static status_t
_fbsd_init_drivers(driver_t *drivers[]) init_hardware_uhub(driver_t* drivers[])
{ {
status_t status; status_t status;
int p = 0; device_t root;
status = init_mutexes(); int p = 0;
while (sProbedDevices[p].bus != BUS_INVALID)
p++;
status = init_usb();
if (status != B_OK)
return status;
status = init_root_device(&root, BUS_uhub);
if (status != B_OK)
return status;
bool found = false;
uint32 cookie = 0;
struct freebsd_usb_device udev = {};
while ((status = get_next_usb_device(&cookie, &udev)) == B_OK) {
int best = 0;
driver_t* driver = NULL;
struct usb_attach_arg uaa;
status = get_usb_device_attach_arg(&udev, &uaa);
if (status != B_OK)
continue;
for (int index = 0; drivers[index] != NULL; index++) {
int result;
device_t device = NULL;
status = add_child_device(drivers[index], root, &device);
if (status < B_OK)
break;
device_set_ivars(device, &uaa);
result = device->methods.probe(device);
if (result >= 0 && (driver == NULL || result > best)) {
TRACE(("%s, found %s at %d (%d)\n", gDriverName,
device_get_desc(device), i, result));
driver = drivers[index];
best = result;
}
device_delete_child(root, device);
}
if (driver == NULL)
continue;
sProbedDevices[p].bus = BUS_uhub;
sProbedDevices[p].driver = driver;
sProbedDevices[p].usb_dev = udev;
sProbedDevices[p].uaa = uaa;
sProbedDevices[p].uaa.device = &sProbedDevices[p].usb_dev;
// We just "transferred ownership" of usb_dev to sProbedDevices.
memset(&udev, 0, sizeof(udev));
found = true;
p++;
}
sProbedDevices[p].bus = BUS_INVALID;
device_delete_child(NULL, root);
usb_cleanup_device(&udev);
if (found)
return B_OK;
uninit_usb();
return B_NOT_SUPPORTED;
}
status_t
_fbsd_init_hardware(driver_t* pci_drivers[], driver_t* uhub_drivers[])
{
sProbedDevices[0].bus = BUS_INVALID;
if (pci_drivers != NULL)
init_hardware_pci(pci_drivers);
if (uhub_drivers != NULL)
init_hardware_uhub(uhub_drivers);
return (sProbedDevices[0].bus != BUS_INVALID) ? B_OK : B_NOT_SUPPORTED;
}
status_t
_fbsd_init_drivers()
{
status_t status = init_mutexes();
if (status < B_OK) if (status < B_OK)
goto err2; goto err2;
@ -200,20 +310,27 @@ _fbsd_init_drivers(driver_t *drivers[])
if (status < B_OK) if (status < B_OK)
goto err6; goto err6;
for (p = 0; sProbedDevices[p].driver != NULL; p++) { for (int p = 0; sProbedDevices[p].bus != BUS_INVALID; p++) {
pci_info* info;
device_t root, device = NULL; device_t root, device = NULL;
status = init_root_device(&root); status = init_root_device(&root, sProbedDevices[p].bus);
if (status != B_OK) if (status != B_OK)
break; break;
info = get_pci_info(root); if (sProbedDevices[p].bus == BUS_pci) {
*info = sProbedDevices[p].info; pci_info* info = get_device_pci_info(root);
*info = sProbedDevices[p].pci_info;
} else if (sProbedDevices[p].bus == BUS_uhub) {
struct root_device_softc* root_softc = (struct root_device_softc*)root->softc;
root_softc->usb_dev = &sProbedDevices[p].usb_dev;
}
status = add_child_device(sProbedDevices[p].driver, root, &device); status = add_child_device(sProbedDevices[p].driver, root, &device);
if (status != B_OK) if (status != B_OK)
break; break;
if (sProbedDevices[p].bus == BUS_uhub)
device_set_ivars(device, &sProbedDevices[p].uaa);
// some drivers expect probe() to be called before attach() // some drivers expect probe() to be called before attach()
// (i.e. they set driver softc in probe(), etc.) // (i.e. they set driver softc in probe(), etc.)
if (device->methods.probe(device) >= 0 if (device->methods.probe(device) >= 0
@ -243,12 +360,9 @@ err4:
err3: err3:
uninit_mutexes(); uninit_mutexes();
err2: err2:
for (p = 0; sProbedDevices[p].driver != NULL; p++) { uninit_probed_devices();
gPci->unreserve_device(sProbedDevices[p].info.bus,
sProbedDevices[p].info.device, sProbedDevices[p].info.function,
gDriverName, NULL);
}
uninit_usb();
uninit_pci(); uninit_pci();
return status; return status;
@ -256,16 +370,10 @@ err2:
status_t status_t
_fbsd_uninit_drivers(driver_t *drivers[]) _fbsd_uninit_drivers()
{ {
int i, p; for (int i = 0; i < gDeviceCount; i++)
for (i = 0; drivers[i]; i++)
TRACE(("%s: uninit_driver(%p)\n", gDriverName, drivers[i]));
for (i = 0; i < gDeviceCount; i++) {
device_delete_child(NULL, gDevices[i]->root_device); device_delete_child(NULL, gDevices[i]->root_device);
}
uninit_wlan_stack(); uninit_wlan_stack();
uninit_sysinit(); uninit_sysinit();
@ -275,12 +383,9 @@ _fbsd_uninit_drivers(driver_t *drivers[])
uninit_mbufs(); uninit_mbufs();
uninit_mutexes(); uninit_mutexes();
for (p = 0; sProbedDevices[p].driver != NULL; p++) { uninit_probed_devices();
gPci->unreserve_device(sProbedDevices[p].info.bus,
sProbedDevices[p].info.device, sProbedDevices[p].info.function,
gDriverName, NULL);
}
uninit_usb();
uninit_pci(); uninit_pci();
return B_OK; return B_OK;

View File

@ -59,6 +59,8 @@ pci_info*
get_device_pci_info(device_t device) get_device_pci_info(device_t device)
{ {
struct root_device_softc* root_softc = (struct root_device_softc*)device->root->softc; struct root_device_softc* root_softc = (struct root_device_softc*)device->root->softc;
if (root_softc->bus != root_device_softc::BUS_pci)
return NULL;
return &root_softc->pci_info; return &root_softc->pci_info;
} }