freebsd_network: Clean up attach logic and separate USB logic.
USB code now goes in a separate static library. This also paves the way for supporting more busses than PCI and USB in the compat layer. Tested with realtekwifi, still works.
This commit is contained in:
@@ -34,15 +34,15 @@ extern void reenable_interrupts_de(device_t dev);
|
||||
extern driver_t *DRIVER_MODULE_NAME(dc, pci);
|
||||
extern driver_t *DRIVER_MODULE_NAME(de, pci);
|
||||
|
||||
status_t
|
||||
__haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]))
|
||||
void
|
||||
__haiku_init_hardware()
|
||||
{
|
||||
driver_t *drivers[] = {
|
||||
DRIVER_MODULE_NAME(dc, pci),
|
||||
DRIVER_MODULE_NAME(de, pci),
|
||||
NULL
|
||||
};
|
||||
return (*handler)(drivers, NULL);
|
||||
_fbsd_init_hardware_pci(drivers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ NO_HAIKU_CHECK_DISABLE_INTERRUPTS();
|
||||
NO_HAIKU_REENABLE_INTERRUPTS();
|
||||
|
||||
|
||||
status_t
|
||||
__haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]))
|
||||
void
|
||||
__haiku_init_hardware()
|
||||
{
|
||||
driver_t *drivers[] = {
|
||||
DRIVER_MODULE_NAME(em, pci),
|
||||
DRIVER_MODULE_NAME(igb, pci),
|
||||
NULL
|
||||
};
|
||||
return (*handler)(drivers, NULL);
|
||||
_fbsd_init_hardware_pci(drivers);
|
||||
}
|
||||
|
||||
@@ -45,15 +45,15 @@ extern driver_t *DRIVER_MODULE_NAME(le, pci);
|
||||
extern driver_t *DRIVER_MODULE_NAME(pcn, pci);
|
||||
|
||||
|
||||
status_t
|
||||
__haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]))
|
||||
void
|
||||
__haiku_init_hardware()
|
||||
{
|
||||
driver_t *drivers[] = {
|
||||
DRIVER_MODULE_NAME(le, pci),
|
||||
DRIVER_MODULE_NAME(pcn, pci),
|
||||
NULL
|
||||
};
|
||||
return (*handler)(drivers, NULL);
|
||||
_fbsd_init_hardware_pci(drivers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ KernelAddon ralinkwifi :
|
||||
glue.c
|
||||
:
|
||||
freebsd_wlan.a
|
||||
freebsd_usb.a
|
||||
libfreebsd_network.a
|
||||
;
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ extern driver_t* DRIVER_MODULE_NAME(run, uhub);
|
||||
extern driver_t* DRIVER_MODULE_NAME(rum, uhub);
|
||||
|
||||
|
||||
status_t
|
||||
__haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]))
|
||||
void
|
||||
__haiku_init_hardware()
|
||||
{
|
||||
driver_t *pci_drivers[] = {
|
||||
DRIVER_MODULE_NAME(ral, pci),
|
||||
@@ -63,7 +63,8 @@ __haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[])
|
||||
DRIVER_MODULE_NAME(rum, uhub),
|
||||
NULL
|
||||
};
|
||||
return (*handler)(pci_drivers, usb_drivers);
|
||||
_fbsd_init_hardware_pci(pci_drivers);
|
||||
_fbsd_init_hardware_uhub(usb_drivers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -153,6 +153,7 @@ KernelAddon realtekwifi :
|
||||
r21au_init.c
|
||||
:
|
||||
freebsd_wlan.a
|
||||
freebsd_usb.a
|
||||
libfreebsd_network.a
|
||||
;
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ NO_HAIKU_FBSD_MII_DRIVER();
|
||||
NO_HAIKU_REENABLE_INTERRUPTS();
|
||||
|
||||
|
||||
status_t
|
||||
__haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]))
|
||||
void
|
||||
__haiku_init_hardware()
|
||||
{
|
||||
driver_t *pci_drivers[] = {
|
||||
DRIVER_MODULE_NAME(rtwn_pci, pci),
|
||||
@@ -54,7 +54,8 @@ __haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[])
|
||||
DRIVER_MODULE_NAME(rtwn_usb, uhub),
|
||||
NULL
|
||||
};
|
||||
return (*handler)(pci_drivers, usb_drivers);
|
||||
_fbsd_init_hardware_pci(pci_drivers);
|
||||
_fbsd_init_hardware_uhub(usb_drivers);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,9 +20,6 @@ KernelStaticLibrary libfreebsd_network.a :
|
||||
fbsd_subr_sbuf.c
|
||||
fbsd_time.c
|
||||
fbsd_timingsafe.c
|
||||
fbsd_usb_error.c
|
||||
fbsd_usb_util.c
|
||||
fbsd_usb_lookup.c
|
||||
|
||||
bus.cpp
|
||||
bus_dma.cpp
|
||||
@@ -48,6 +45,14 @@ KernelStaticLibrary libfreebsd_network.a :
|
||||
sysinit.c
|
||||
taskqueue.c
|
||||
unit.cpp
|
||||
;
|
||||
|
||||
SEARCH_SOURCE += [ FDirName $(SUBDIR) dev usb ] ;
|
||||
|
||||
KernelStaticLibrary freebsd_usb.a :
|
||||
fbsd_usb_error.c
|
||||
fbsd_usb_util.c
|
||||
fbsd_usb_lookup.c
|
||||
usb.cpp
|
||||
usb_util.c
|
||||
;
|
||||
|
||||
@@ -12,6 +12,4 @@ struct usb_device {
|
||||
uint32 haiku_usb_device;
|
||||
};
|
||||
|
||||
void usb_cleanup_device(struct usb_device* udev);
|
||||
|
||||
#endif // _FBSD_COMPAT_USB_DEVICE_H_
|
||||
|
||||
@@ -78,14 +78,16 @@ typedef struct {
|
||||
__fbsd_ ## name ## _ ## busname
|
||||
|
||||
|
||||
status_t _fbsd_init_hardware(driver_t* pci_drivers[], driver_t* uhub_drivers[]);
|
||||
void __haiku_init_hardware(void);
|
||||
status_t _fbsd_init_hardware();
|
||||
status_t _fbsd_init_hardware_pci(driver_t* drivers[]);
|
||||
status_t _fbsd_init_hardware_uhub(driver_t* drivers[]);
|
||||
status_t _fbsd_init_drivers();
|
||||
status_t _fbsd_uninit_drivers();
|
||||
|
||||
extern const char *gDriverName;
|
||||
driver_t *__haiku_select_miibus_driver(device_t dev);
|
||||
driver_t *__haiku_probe_drivers(device_t dev, driver_t *drivers[]);
|
||||
status_t __haiku_handle_fbsd_drivers_list(status_t (*handler)(driver_t *[], driver_t *[]));
|
||||
|
||||
status_t init_wlan_stack(void);
|
||||
void uninit_wlan_stack(void);
|
||||
@@ -106,15 +108,15 @@ status_t wlan_close(void*);
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION; \
|
||||
status_t init_hardware() \
|
||||
{ \
|
||||
return __haiku_handle_fbsd_drivers_list(_fbsd_init_hardware); \
|
||||
return _fbsd_init_hardware(); \
|
||||
} \
|
||||
status_t init_driver() \
|
||||
{ \
|
||||
return _fbsd_init_drivers(); \
|
||||
return _fbsd_init_drivers(); \
|
||||
} \
|
||||
void uninit_driver() \
|
||||
{ \
|
||||
_fbsd_uninit_drivers(); \
|
||||
_fbsd_uninit_drivers(); \
|
||||
} \
|
||||
const char **publish_devices() \
|
||||
{ return gDeviceNameList; } \
|
||||
@@ -138,12 +140,13 @@ status_t wlan_close(void*);
|
||||
|
||||
#define HAIKU_FBSD_DRIVER_GLUE(publicname, name, busname) \
|
||||
extern driver_t* DRIVER_MODULE_NAME(name, busname); \
|
||||
status_t __haiku_handle_fbsd_drivers_list(status_t (*proc)(driver_t *[], driver_t *[])) {\
|
||||
void __haiku_init_hardware() \
|
||||
{ \
|
||||
driver_t *drivers[] = { \
|
||||
DRIVER_MODULE_NAME(name, busname), \
|
||||
NULL \
|
||||
}; \
|
||||
return (*proc)(drivers, NULL); \
|
||||
_fbsd_init_hardware_pci(drivers); \
|
||||
} \
|
||||
HAIKU_FBSD_DRIVERS_GLUE(publicname);
|
||||
|
||||
@@ -152,12 +155,13 @@ status_t wlan_close(void*);
|
||||
|
||||
#define HAIKU_FBSD_WLAN_DRIVER_GLUE(publicname, name, busname) \
|
||||
extern driver_t *DRIVER_MODULE_NAME(name, busname); \
|
||||
status_t __haiku_handle_fbsd_drivers_list(status_t (*proc)(driver_t *[], driver_t *[])) {\
|
||||
void __haiku_init_hardware() \
|
||||
{ \
|
||||
driver_t *drivers[] = { \
|
||||
DRIVER_MODULE_NAME(name, busname), \
|
||||
NULL \
|
||||
}; \
|
||||
return (*proc)(drivers, NULL); \
|
||||
_fbsd_init_hardware_pci(drivers); \
|
||||
} \
|
||||
HAIKU_FBSD_WLAN_DRIVERS_GLUE(publicname);
|
||||
|
||||
|
||||
@@ -506,8 +506,11 @@ bus_generic_attach(device_t dev)
|
||||
} else {
|
||||
device_printf(dev, "failed to find driver for child device\n");
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
device_printf(dev, "found device driver: %s\n",
|
||||
driver->name);
|
||||
device_set_driver(child, driver);
|
||||
}
|
||||
} else
|
||||
child->methods.device_probe(child);
|
||||
|
||||
@@ -543,31 +546,32 @@ bus_generic_detach(device_t device)
|
||||
|
||||
|
||||
driver_t *
|
||||
__haiku_probe_drivers(device_t dev, driver_t *drivers[])
|
||||
__haiku_probe_drivers(device_t device, driver_t *drivers[])
|
||||
{
|
||||
driver_t *selected = NULL;
|
||||
int i, selectedResult = 0;
|
||||
int best = 0;
|
||||
|
||||
if (drivers == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; drivers[i]; i++) {
|
||||
device_probe_t *probe = (device_probe_t *)
|
||||
resolve_device_method(drivers[i], ID_device_probe);
|
||||
if (probe == NULL)
|
||||
continue;
|
||||
for (int i = 0; drivers[i]; i++) {
|
||||
// Skip allocating the device softc and just call probe() directly.
|
||||
// (Any drivers which don't support this should be patched.)
|
||||
device->methods.device_register
|
||||
= resolve_device_method(drivers[i], ID_device_register);
|
||||
device->methods.device_probe
|
||||
= resolve_device_method(drivers[i], ID_device_probe);
|
||||
|
||||
int result = probe(dev);
|
||||
if (result >= 0) {
|
||||
if (selected == NULL || result < selectedResult) {
|
||||
selected = drivers[i];
|
||||
selectedResult = result;
|
||||
device_printf(dev, "found %s device driver: %s\n",
|
||||
dev->parent->description, selected->name);
|
||||
}
|
||||
int result = device->methods.device_probe(device);
|
||||
if (result >= 0 && (selected == NULL || result > best)) {
|
||||
selected = drivers[i];
|
||||
best = result;
|
||||
}
|
||||
}
|
||||
|
||||
device->methods.device_register = NULL;
|
||||
device->methods.device_probe = NULL;
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,13 +82,12 @@ void uninit_callout(void);
|
||||
status_t init_pci();
|
||||
void uninit_pci();
|
||||
|
||||
status_t init_usb();
|
||||
void uninit_usb();
|
||||
void uninit_usb() __attribute__((weak));
|
||||
|
||||
status_t get_next_usb_device(uint32* cookie, struct freebsd_usb_device* result);
|
||||
status_t get_usb_device_attach_arg(struct freebsd_usb_device* device, struct usb_attach_arg* uaa);
|
||||
|
||||
device_t find_root_device(int);
|
||||
void report_probed_device(int bus, void* compat_device, driver_t* driver,
|
||||
void (*prepare_attach)(void*, device_t), void (*free_compat_device)(void*));
|
||||
status_t init_root_device(device_t *_root, int bus_type);
|
||||
device_t find_root_device(int unit);
|
||||
pci_info* get_device_pci_info(device_t dev);
|
||||
|
||||
device_method_signature_t resolve_device_method(driver_t *driver, int id);
|
||||
|
||||
@@ -37,8 +37,10 @@ static struct {
|
||||
driver_t* driver;
|
||||
int bus;
|
||||
struct pci_info pci_info;
|
||||
struct freebsd_usb_device usb_dev;
|
||||
struct usb_attach_arg uaa;
|
||||
|
||||
void* compat_device;
|
||||
void (*prepare_attach)(void*, device_t);
|
||||
void (*free_compat_device)(void*);
|
||||
} sProbedDevices[MAX_DEVICES];
|
||||
|
||||
const char* gDeviceNameList[MAX_DEVICES + 1];
|
||||
@@ -46,7 +48,7 @@ struct ifnet* gDevices[MAX_DEVICES];
|
||||
int32 gDeviceCount;
|
||||
|
||||
|
||||
static status_t
|
||||
status_t
|
||||
init_root_device(device_t *_root, int bus_type)
|
||||
{
|
||||
static driver_t sRootDriverPCI = {
|
||||
@@ -115,18 +117,41 @@ uninit_probed_devices()
|
||||
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);
|
||||
} else {
|
||||
sProbedDevices[p].free_compat_device(sProbedDevices[p].compat_device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
report_probed_device(int bus, void* compat_device, driver_t* driver,
|
||||
void (*prepare_attach)(void*, device_t), void (*free_compat_device)(void*))
|
||||
{
|
||||
int p = 0;
|
||||
while (sProbedDevices[p].bus != BUS_INVALID && p < MAX_DEVICES)
|
||||
p++;
|
||||
if (p == MAX_DEVICES) {
|
||||
free_compat_device(compat_device);
|
||||
return;
|
||||
}
|
||||
|
||||
sProbedDevices[p].bus = bus;
|
||||
sProbedDevices[p].driver = driver;
|
||||
sProbedDevices[p].compat_device = compat_device;
|
||||
sProbedDevices[p].prepare_attach = prepare_attach;
|
||||
sProbedDevices[p].free_compat_device = free_compat_device;
|
||||
|
||||
if ((p + 1) < MAX_DEVICES)
|
||||
sProbedDevices[p + 1].bus = BUS_INVALID;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - Haiku Driver API
|
||||
|
||||
|
||||
static status_t
|
||||
init_hardware_pci(driver_t* drivers[])
|
||||
status_t
|
||||
_fbsd_init_hardware_pci(driver_t* drivers[])
|
||||
{
|
||||
status_t status;
|
||||
int i = 0;
|
||||
@@ -154,23 +179,7 @@ init_hardware_pci(driver_t* drivers[])
|
||||
device.parent = root;
|
||||
device.root = root;
|
||||
|
||||
for (int index = 0; drivers[index] != NULL; index++) {
|
||||
// Skip allocating the device softc and just call probe() directly.
|
||||
// (Any drivers which don't support this should be patched.)
|
||||
device.methods.device_register
|
||||
= resolve_device_method(drivers[index], ID_device_register);
|
||||
device.methods.device_probe
|
||||
= resolve_device_method(drivers[index], ID_device_probe);
|
||||
|
||||
int result = device.methods.device_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;
|
||||
}
|
||||
}
|
||||
|
||||
driver = __haiku_probe_drivers(&device, drivers);
|
||||
if (driver == NULL)
|
||||
continue;
|
||||
|
||||
@@ -199,94 +208,12 @@ init_hardware_pci(driver_t* drivers[])
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
init_hardware_uhub(driver_t* drivers[])
|
||||
{
|
||||
status_t status;
|
||||
device_t root;
|
||||
|
||||
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;
|
||||
|
||||
struct device device = {};
|
||||
device.parent = root;
|
||||
device.root = root;
|
||||
device_set_ivars(&device, &uaa);
|
||||
|
||||
for (int index = 0; drivers[index] != NULL; index++) {
|
||||
device.methods.device_register
|
||||
= resolve_device_method(drivers[index], ID_device_register);
|
||||
device.methods.device_probe
|
||||
= resolve_device_method(drivers[index], ID_device_probe);
|
||||
|
||||
int result = device.methods.device_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;
|
||||
}
|
||||
}
|
||||
|
||||
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[])
|
||||
_fbsd_init_hardware()
|
||||
{
|
||||
sProbedDevices[0].bus = BUS_INVALID;
|
||||
|
||||
if (pci_drivers != NULL)
|
||||
init_hardware_pci(pci_drivers);
|
||||
|
||||
if (uhub_drivers != NULL)
|
||||
init_hardware_uhub(uhub_drivers);
|
||||
__haiku_init_hardware();
|
||||
|
||||
return (sProbedDevices[0].bus != BUS_INVALID) ? B_OK : B_NOT_SUPPORTED;
|
||||
}
|
||||
@@ -328,20 +255,16 @@ _fbsd_init_drivers()
|
||||
if (status != B_OK)
|
||||
break;
|
||||
|
||||
if (sProbedDevices[p].bus == BUS_pci) {
|
||||
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);
|
||||
if (status != B_OK)
|
||||
break;
|
||||
|
||||
if (sProbedDevices[p].bus == BUS_uhub)
|
||||
device_set_ivars(device, &sProbedDevices[p].uaa);
|
||||
if (sProbedDevices[p].bus == BUS_pci) {
|
||||
pci_info* info = get_device_pci_info(root);
|
||||
*info = sProbedDevices[p].pci_info;
|
||||
} else {
|
||||
sProbedDevices[p].prepare_attach(sProbedDevices[p].compat_device, device);
|
||||
}
|
||||
|
||||
// some drivers expect probe() to be called before attach()
|
||||
// (i.e. they set driver softc in probe(), etc.)
|
||||
@@ -376,7 +299,8 @@ err3:
|
||||
err2:
|
||||
uninit_probed_devices();
|
||||
|
||||
uninit_usb();
|
||||
if (uninit_usb != NULL)
|
||||
uninit_usb();
|
||||
uninit_pci();
|
||||
|
||||
return status;
|
||||
@@ -399,7 +323,8 @@ _fbsd_uninit_drivers()
|
||||
|
||||
uninit_probed_devices();
|
||||
|
||||
uninit_usb();
|
||||
if (uninit_usb != NULL)
|
||||
uninit_usb();
|
||||
uninit_pci();
|
||||
|
||||
return B_OK;
|
||||
|
||||
@@ -63,7 +63,7 @@ uninit_usb()
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
static status_t
|
||||
get_next_usb_device(uint32* cookie, freebsd_usb_device* result)
|
||||
{
|
||||
// We cheat here: since USB IDs are sequential, instead of doing a
|
||||
@@ -114,7 +114,7 @@ get_next_usb_device(uint32* cookie, freebsd_usb_device* result)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
static status_t
|
||||
get_usb_device_attach_arg(struct freebsd_usb_device* device, struct usb_attach_arg* uaa)
|
||||
{
|
||||
memset(uaa, 0, sizeof(struct usb_attach_arg));
|
||||
@@ -158,7 +158,7 @@ get_usb_device_attach_arg(struct freebsd_usb_device* device, struct usb_attach_a
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
usb_cleanup_device(freebsd_usb_device* udev)
|
||||
{
|
||||
for (int i = 0; i < USB_MAX_EP_UNITS; i++) {
|
||||
@@ -168,6 +168,93 @@ usb_cleanup_device(freebsd_usb_device* udev)
|
||||
}
|
||||
|
||||
|
||||
struct compat_usb_device {
|
||||
freebsd_usb_device udev;
|
||||
struct usb_attach_arg uaa;
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
free_compat_usb_device(void* cookie)
|
||||
{
|
||||
compat_usb_device* compat_device = (compat_usb_device*)cookie;
|
||||
usb_cleanup_device(&compat_device->udev);
|
||||
free(compat_device);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
prepare_usb_attach(void* cookie, device_t device)
|
||||
{
|
||||
compat_usb_device* compat_device = (compat_usb_device*)cookie;
|
||||
|
||||
struct root_device_softc* root_softc
|
||||
= (struct root_device_softc*)device->parent->softc;
|
||||
root_softc->usb_dev = &compat_device->udev;
|
||||
device_set_ivars(device, &compat_device->uaa);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
_fbsd_init_hardware_uhub(driver_t* drivers[])
|
||||
{
|
||||
status_t status;
|
||||
device_t root;
|
||||
const int BUS_uhub = root_device_softc::BUS_uhub;
|
||||
|
||||
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;
|
||||
|
||||
struct device device = {};
|
||||
device.parent = root;
|
||||
device.root = root;
|
||||
device_set_ivars(&device, &uaa);
|
||||
|
||||
driver = __haiku_probe_drivers(&device, drivers);
|
||||
if (driver == NULL)
|
||||
continue;
|
||||
|
||||
compat_usb_device* compat_device = (compat_usb_device*)malloc(sizeof(compat_usb_device));
|
||||
compat_device->udev = udev;
|
||||
compat_device->uaa = uaa;
|
||||
compat_device->uaa.device = &compat_device->udev;
|
||||
|
||||
// We just "transferred ownership" of usb_dev to sProbedDevices.
|
||||
memset(&udev, 0, sizeof(udev));
|
||||
|
||||
report_probed_device(BUS_uhub, compat_device, driver,
|
||||
prepare_usb_attach, free_compat_usb_device);
|
||||
found = true;
|
||||
}
|
||||
|
||||
device_delete_child(NULL, root);
|
||||
usb_cleanup_device(&udev);
|
||||
|
||||
if (found)
|
||||
return B_OK;
|
||||
|
||||
uninit_usb();
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
static usb_error_t
|
||||
map_usb_error(status_t err)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user