/** * Probe UNDI root bus * * @v rootdev UNDI bus root device * * Scans the UNDI bus for devices and registers all devices it can * find. */ static int undibus_probe ( struct root_device *rootdev ) { struct undi_device *undi = &preloaded_undi; int rc; /* Check for a valie preloaded UNDI device */ if ( ! undi->entry.segment ) { DBG ( "No preloaded UNDI device found!\n" ); return -ENODEV; } /* Add to device hierarchy */ strncpy ( undi->dev.name, "UNDI", ( sizeof ( undi->dev.name ) - 1 ) ); if ( undi->pci_busdevfn != UNDI_NO_PCI_BUSDEVFN ) { undi->dev.desc.bus_type = BUS_TYPE_PCI; undi->dev.desc.location = undi->pci_busdevfn; undi->dev.desc.vendor = undi->pci_vendor; undi->dev.desc.device = undi->pci_device; } else if ( undi->isapnp_csn != UNDI_NO_ISAPNP_CSN ) { undi->dev.desc.bus_type = BUS_TYPE_ISAPNP; } undi->dev.parent = &rootdev->dev; list_add ( &undi->dev.siblings, &rootdev->dev.children); INIT_LIST_HEAD ( &undi->dev.children ); /* Create network device */ if ( ( rc = undinet_probe ( undi ) ) != 0 ) goto err; return 0; err: list_del ( &undi->dev.siblings ); return rc; }
/** * Probe PCI device * * @v pci PCI device * @v id PCI ID * @ret rc Return status code */ static int undipci_probe ( struct pci_device *pci ) { struct undi_device *undi; struct undi_rom *undirom; int rc; /* Allocate UNDI device structure */ undi = zalloc ( sizeof ( *undi ) ); if ( ! undi ) return -ENOMEM; pci_set_drvdata ( pci, undi ); /* Find/create our pixie */ if ( preloaded_undi.pci_busdevfn == pci->busdevfn ) { /* Claim preloaded UNDI device */ DBGC ( undi, "UNDI %p using preloaded UNDI device\n", undi ); memcpy ( undi, &preloaded_undi, sizeof ( *undi ) ); memset ( &preloaded_undi, 0, sizeof ( preloaded_undi ) ); } else { /* Find UNDI ROM for PCI device */ if ( ! ( undirom = undipci_find_rom ( pci ) ) ) { rc = -ENODEV; goto err_find_rom; } /* Call UNDI ROM loader to create pixie */ if ( ( rc = undi_load_pci ( undi, undirom, pci->busdevfn ) ) != 0 ) { goto err_load_pci; } } /* Add to device hierarchy */ snprintf ( undi->dev.name, sizeof ( undi->dev.name ), "UNDI-%s", pci->dev.name ); memcpy ( &undi->dev.desc, &pci->dev.desc, sizeof ( undi->dev.desc ) ); undi->dev.parent = &pci->dev; INIT_LIST_HEAD ( &undi->dev.children ); list_add ( &undi->dev.siblings, &pci->dev.children ); /* Create network device */ if ( ( rc = undinet_probe ( undi ) ) != 0 ) goto err_undinet_probe; return 0; err_undinet_probe: undi_unload ( undi ); list_del ( &undi->dev.siblings ); err_find_rom: err_load_pci: free ( undi ); pci_set_drvdata ( pci, NULL ); return rc; }
/** * Probe UNDI root bus * * @v rootdev UNDI bus root device * * Scans the UNDI bus for devices and registers all devices it can * find. */ static int undibus_probe ( struct root_device *rootdev ) { struct undi_device *undi = &preloaded_undi; struct device *dev = &undibus_dev; int rc; /* Check for a valie preloaded UNDI device */ if ( ! undi->entry.segment ) { DBG ( "No preloaded UNDI device found!\n" ); return -ENODEV; } /* Add to device hierarchy */ dev->driver_name = "undionly"; if ( undi->pci_busdevfn != UNDI_NO_PCI_BUSDEVFN ) { dev->desc.bus_type = BUS_TYPE_PCI; dev->desc.location = undi->pci_busdevfn; dev->desc.vendor = undi->pci_vendor; dev->desc.device = undi->pci_device; snprintf ( dev->name, sizeof ( dev->name ), "0000:%02x:%02x.%x", PCI_BUS ( undi->pci_busdevfn ), PCI_SLOT ( undi->pci_busdevfn ), PCI_FUNC ( undi->pci_busdevfn ) ); } else if ( undi->isapnp_csn != UNDI_NO_ISAPNP_CSN ) { dev->desc.bus_type = BUS_TYPE_ISAPNP; snprintf ( dev->name, sizeof ( dev->name ), "ISAPNP" ); } dev->parent = &rootdev->dev; list_add ( &dev->siblings, &rootdev->dev.children); INIT_LIST_HEAD ( &dev->children ); /* Create network device */ if ( ( rc = undinet_probe ( undi, dev ) ) != 0 ) goto err; return 0; err: list_del ( &dev->siblings ); return rc; }