#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: amdnb_misc.c,v 1.5 2021/08/07 16:19:07 thorpej Exp $");
#include <sys/param.h>
#include <sys/device.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
static int amdnb_misc_match(device_t, cfdata_t match, void *);
static void amdnb_misc_attach(device_t, device_t, void *);
static int amdnb_misc_detach(device_t, int);
static int amdnb_misc_rescan(device_t, const char *, const int *);
static void amdnb_misc_childdet(device_t, device_t);
struct amdnb_misc_softc {
struct pci_attach_args sc_pa;
};
CFATTACH_DECL3_NEW(amdnb_misc, sizeof(struct amdnb_misc_softc),
amdnb_misc_match, amdnb_misc_attach, amdnb_misc_detach, NULL,
amdnb_misc_rescan, amdnb_misc_childdet, DVF_DETACH_SHUTDOWN);
static int
amdnb_misc_match(device_t parent, cfdata_t match, void *aux)
{
struct pci_attach_args *pa = aux;
if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD)
return 0;
switch (PCI_PRODUCT(pa->pa_id)) {
case PCI_PRODUCT_AMD_AMD64_MISC:
case PCI_PRODUCT_AMD_AMD64_F10_MISC:
case PCI_PRODUCT_AMD_AMD64_F11_MISC:
case PCI_PRODUCT_AMD_F14_NB:
case PCI_PRODUCT_AMD_F15_MISC:
case PCI_PRODUCT_AMD_F16_NB:
case PCI_PRODUCT_AMD_F16_30_NB:
break;
default:
return 0;
}
return 2;
}
static int
amdnb_misc_search(device_t parent, cfdata_t cf, const int *locs, void *aux)
{
device_t dev;
deviter_t di;
bool attach;
if (!config_probe(parent, cf, aux))
return 0;
attach = true;
for (dev = deviter_first(&di, DEVITER_F_LEAVES_FIRST); dev != NULL;
dev = deviter_next(&di))
{
if (device_parent(dev) != parent)
continue;
if (device_is_a(dev, cf->cf_name)) {
attach = false;
break;
}
}
deviter_release(&di);
if (!attach)
return 0;
config_attach(parent, cf, aux, NULL, CFARGS_NONE);
return 0;
}
static void
amdnb_misc_attach(device_t parent, device_t self, void *aux)
{
struct amdnb_misc_softc *sc = device_private(self);
struct pci_attach_args *pa = aux;
sc->sc_pa = *pa;
aprint_naive("\n");
aprint_normal(": AMD NB Misc Configuration\n");
if (!pmf_device_register(self, NULL, NULL))
aprint_error_dev(self, "couldn't establish power handler\n");
config_search(self, &sc->sc_pa,
CFARGS(.search = amdnb_misc_search));
return;
}
static int
amdnb_misc_detach(device_t self, int flags)
{
int rv;
rv = config_detach_children(self, flags);
if (rv != 0)
return rv;
pmf_device_deregister(self);
return rv;
}
static int
amdnb_misc_rescan(device_t self, const char *ifattr, const int *locators)
{
struct amdnb_misc_softc *sc = device_private(self);
config_search(self, &sc->sc_pa,
CFARGS(.search = amdnb_misc_search));
return 0;
}
static void
amdnb_misc_childdet(device_t self, device_t child)
{
return;
}