amdnb_misc.c revision 1.2
11.2Scegger/* $NetBSD: amdnb_misc.c,v 1.2 2012/04/16 16:07:24 cegger Exp $ */ 21.1Scegger/* 31.1Scegger * Copyright (c) 2012 The NetBSD Foundation, Inc. 41.1Scegger * All rights reserved. 51.1Scegger * 61.1Scegger * This code is derived from software contributed to The NetBSD Foundation 71.1Scegger * by Christoph Egger. 81.1Scegger * 91.1Scegger * Redistribution and use in source and binary forms, with or without 101.1Scegger * modification, are permitted provided that the following conditions 111.1Scegger * are met: 121.1Scegger * 1. Redistributions of source code must retain the above copyright 131.1Scegger * notice, this list of conditions and the following disclaimer. 141.1Scegger * 2. Redistributions in binary form must reproduce the above copyright 151.1Scegger * notice, this list of conditions and the following disclaimer in the 161.1Scegger * documentation and/or other materials provided with the distribution. 171.1Scegger * 181.1Scegger * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 191.1Scegger * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 201.1Scegger * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 211.1Scegger * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 221.1Scegger * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 231.1Scegger * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 241.1Scegger * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 251.1Scegger * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 261.1Scegger * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 271.1Scegger * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 281.1Scegger * POSSIBILITY OF SUCH DAMAGE. 291.1Scegger */ 301.1Scegger 311.1Scegger#include <sys/cdefs.h> 321.2Scegger__KERNEL_RCSID(0, "$NetBSD: amdnb_misc.c,v 1.2 2012/04/16 16:07:24 cegger Exp $"); 331.1Scegger 341.1Scegger#include <sys/param.h> 351.1Scegger#include <sys/device.h> 361.1Scegger 371.1Scegger#include <dev/pci/pcireg.h> 381.1Scegger#include <dev/pci/pcivar.h> 391.1Scegger#include <dev/pci/pcidevs.h> 401.1Scegger 411.1Sceggerstatic int amdnb_misc_match(device_t, cfdata_t match, void *); 421.1Sceggerstatic void amdnb_misc_attach(device_t, device_t, void *); 431.1Sceggerstatic int amdnb_misc_detach(device_t, int); 441.2Sceggerstatic int amdnb_misc_rescan(device_t, const char *, const int *); 451.2Sceggerstatic void amdnb_misc_childdet(device_t, device_t); 461.1Scegger 471.2Sceggerstruct amdnb_misc_softc { 481.2Scegger struct pci_attach_args sc_pa; 491.2Scegger}; 501.2Scegger 511.2SceggerCFATTACH_DECL3_NEW(amdnb_misc, sizeof(struct amdnb_misc_softc), 521.2Scegger amdnb_misc_match, amdnb_misc_attach, amdnb_misc_detach, NULL, 531.2Scegger amdnb_misc_rescan, amdnb_misc_childdet, DVF_DETACH_SHUTDOWN); 541.1Scegger 551.1Scegger 561.1Sceggerstatic int 571.1Sceggeramdnb_misc_match(device_t parent, cfdata_t match, void *aux) 581.1Scegger{ 591.1Scegger struct pci_attach_args *pa = aux; 601.1Scegger 611.1Scegger if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_AMD) 621.1Scegger return 0; 631.1Scegger 641.1Scegger switch (PCI_PRODUCT(pa->pa_id)) { 651.1Scegger case PCI_PRODUCT_AMD_AMD64_MISC: 661.1Scegger case PCI_PRODUCT_AMD_AMD64_F10_MISC: 671.1Scegger case PCI_PRODUCT_AMD_AMD64_F11_MISC: 681.1Scegger case PCI_PRODUCT_AMD_F14_NB: /* Family 12h, too */ 691.1Scegger case PCI_PRODUCT_AMD_F15_MISC: 701.1Scegger break; 711.1Scegger default: 721.1Scegger return 0; 731.1Scegger } 741.1Scegger 751.1Scegger return 2; /* supercede pchb(4) */ 761.1Scegger} 771.1Scegger 781.1Sceggerstatic int 791.1Sceggeramdnb_misc_search(device_t parent, cfdata_t cf, const int *locs, void *aux) 801.1Scegger{ 811.2Scegger device_t dev; 821.2Scegger deviter_t di; 831.2Scegger bool attach; 841.2Scegger 851.2Scegger if (!config_match(parent, cf, aux)) 861.2Scegger return 0; 871.2Scegger 881.2Scegger attach = true; 891.2Scegger 901.2Scegger /* Figure out if found child 'cf' is already attached. 911.2Scegger * No need to attach it twice. 921.2Scegger */ 931.2Scegger 941.2Scegger /* XXX: I only want to iterate over the children of *this* device. 951.2Scegger * Can we introduce a 961.2Scegger * deviter_first_child(&di, parent, DEVITER_F_LEAVES_ONLY) 971.2Scegger * or even better, can we introduce a query function that returns 981.2Scegger * if a child is already attached? 991.2Scegger */ 1001.2Scegger for (dev = deviter_first(&di, DEVITER_F_LEAVES_FIRST); dev != NULL; 1011.2Scegger dev = deviter_next(&di)) 1021.2Scegger { 1031.2Scegger if (device_parent(dev) != parent) 1041.2Scegger continue; 1051.2Scegger if (device_is_a(dev, cf->cf_name)) { 1061.2Scegger attach = false; 1071.2Scegger break; 1081.2Scegger } 1091.2Scegger } 1101.2Scegger deviter_release(&di); 1111.2Scegger 1121.2Scegger if (!attach) 1131.2Scegger return 0; 1141.2Scegger 1151.2Scegger config_attach_loc(parent, cf, locs, aux, NULL); 1161.1Scegger 1171.1Scegger return 0; 1181.1Scegger} 1191.1Scegger 1201.1Sceggerstatic void 1211.1Sceggeramdnb_misc_attach(device_t parent, device_t self, void *aux) 1221.1Scegger{ 1231.2Scegger struct amdnb_misc_softc *sc = device_private(self); 1241.2Scegger struct pci_attach_args *pa = aux; 1251.2Scegger 1261.2Scegger sc->sc_pa = *pa; 1271.2Scegger 1281.1Scegger aprint_naive("\n"); 1291.1Scegger aprint_normal(": AMD NB Misc Configuration\n"); 1301.1Scegger 1311.1Scegger if (!pmf_device_register(self, NULL, NULL)) 1321.1Scegger aprint_error_dev(self, "couldn't establish power handler\n"); 1331.1Scegger 1341.2Scegger config_search_loc(amdnb_misc_search, self, "amdnb_miscbus", 1351.2Scegger NULL, &sc->sc_pa); 1361.2Scegger 1371.1Scegger return; 1381.1Scegger} 1391.1Scegger 1401.1Sceggerstatic int 1411.1Sceggeramdnb_misc_detach(device_t self, int flags) 1421.1Scegger{ 1431.1Scegger int rv; 1441.1Scegger 1451.1Scegger rv = config_detach_children(self, flags); 1461.1Scegger if (rv != 0) 1471.1Scegger return rv; 1481.1Scegger 1491.1Scegger pmf_device_deregister(self); 1501.1Scegger return rv; 1511.1Scegger} 1521.2Scegger 1531.2Sceggerstatic int 1541.2Sceggeramdnb_misc_rescan(device_t self, const char *ifattr, const int *locators) 1551.2Scegger{ 1561.2Scegger struct amdnb_misc_softc *sc = device_private(self); 1571.2Scegger 1581.2Scegger if (!ifattr_match(ifattr, "amdnb_miscbus")) 1591.2Scegger return 0; 1601.2Scegger 1611.2Scegger config_search_loc(amdnb_misc_search, self, ifattr, 1621.2Scegger locators, &sc->sc_pa); 1631.2Scegger 1641.2Scegger return 0; 1651.2Scegger} 1661.2Scegger 1671.2Sceggerstatic void 1681.2Sceggeramdnb_misc_childdet(device_t self, device_t child) 1691.2Scegger{ 1701.2Scegger return; 1711.2Scegger} 172