Module Name: src Committed By: dyoung Date: Wed Apr 28 21:27:14 UTC 2010
Modified Files: src/sys/arch/x86/include: pci_machdep_common.h src/sys/arch/x86/pci: pci_intr_machdep.c pci_machdep.c Log Message: Provide an x86 implementation of pci_chipset_tag_create(9) and pci_chipset_tag_destroy(9). To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/sys/arch/x86/include/pci_machdep_common.h cvs rdiff -u -r1.16 -r1.17 src/sys/arch/x86/pci/pci_intr_machdep.c cvs rdiff -u -r1.42 -r1.43 src/sys/arch/x86/pci/pci_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/include/pci_machdep_common.h diff -u src/sys/arch/x86/include/pci_machdep_common.h:1.2 src/sys/arch/x86/include/pci_machdep_common.h:1.3 --- src/sys/arch/x86/include/pci_machdep_common.h:1.2 Sat Mar 20 00:02:59 2010 +++ src/sys/arch/x86/include/pci_machdep_common.h Wed Apr 28 21:27:14 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep_common.h,v 1.2 2010/03/20 00:02:59 dyoung Exp $ */ +/* $NetBSD: pci_machdep_common.h,v 1.3 2010/04/28 21:27:14 dyoung Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. @@ -74,31 +74,9 @@ struct pci_chipset_tag { pci_chipset_tag_t pc_super; - pcireg_t (*pc_conf_read)(pci_chipset_tag_t, pcitag_t, int); - - void (*pc_conf_write)(pci_chipset_tag_t, pcitag_t, int, pcireg_t); - -#if 0 - int (*pc_find_rom)(struct pci_attach_args *, bus_space_tag_t, - bus_space_handle_t, int, bus_space_handle_t *, bus_space_size_t *); -#endif - - int (*pc_intr_map)(struct pci_attach_args *, pci_intr_handle_t *); - - const char *(*pc_intr_string)(pci_chipset_tag_t, pci_intr_handle_t); - - const struct evcnt *(*pc_intr_evcnt)(pci_chipset_tag_t, - pci_intr_handle_t); - - void *(*pc_intr_establish)(pci_chipset_tag_t, pci_intr_handle_t, int, - int (*)(void *), void *); - - void (*pc_intr_disestablish)(pci_chipset_tag_t, void *); - - pcitag_t (*pc_make_tag)(pci_chipset_tag_t, int, int, int); - - void (*pc_decompose_tag)(pci_chipset_tag_t, pcitag_t, - int *, int *, int *); + uint64_t pc_present; + const struct pci_overrides *pc_ov; + void *pc_ctx; }; /* Index: src/sys/arch/x86/pci/pci_intr_machdep.c diff -u src/sys/arch/x86/pci/pci_intr_machdep.c:1.16 src/sys/arch/x86/pci/pci_intr_machdep.c:1.17 --- src/sys/arch/x86/pci/pci_intr_machdep.c:1.16 Sun Mar 14 20:19:06 2010 +++ src/sys/arch/x86/pci/pci_intr_machdep.c Wed Apr 28 21:27:14 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_intr_machdep.c,v 1.16 2010/03/14 20:19:06 dyoung Exp $ */ +/* $NetBSD: pci_intr_machdep.c,v 1.17 2010/04/28 21:27:14 dyoung Exp $ */ /*- * Copyright (c) 1997, 1998, 2009 The NetBSD Foundation, Inc. @@ -73,7 +73,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.16 2010/03/14 20:19:06 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.17 2010/04/28 21:27:14 dyoung Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -122,8 +122,8 @@ #endif if ((pc = pa->pa_pc) != NULL) { - if (pc->pc_intr_map != NULL) - return (*pc->pc_intr_map)(pa, ihp); + if ((pc->pc_present & PCI_OVERRIDE_INTR_MAP) != 0) + return (*pc->pc_ov->ov_intr_map)(pc->pc_ctx, pa, ihp); if (pc->pc_super != NULL) { struct pci_attach_args paclone = *pa; paclone.pa_pc = pc->pc_super; @@ -217,9 +217,10 @@ const char * pci_intr_string(pci_chipset_tag_t pc, pci_intr_handle_t ih) { + if (pc != NULL) { - if (pc->pc_intr_string != NULL) - return (*pc->pc_intr_string)(pc, ih); + if ((pc->pc_present & PCI_OVERRIDE_INTR_STRING) != 0) + return (*pc->pc_ov->ov_intr_string)(pc->pc_ctx, pc, ih); if (pc->pc_super != NULL) return pci_intr_string(pc->pc_super, ih); } @@ -233,8 +234,8 @@ { if (pc != NULL) { - if (pc->pc_intr_evcnt != NULL) - return (*pc->pc_intr_evcnt)(pc, ih); + if ((pc->pc_present & PCI_OVERRIDE_INTR_EVCNT) != 0) + return (*pc->pc_ov->ov_intr_evcnt)(pc->pc_ctx, pc, ih); if (pc->pc_super != NULL) return pci_intr_evcnt(pc->pc_super, ih); } @@ -274,9 +275,9 @@ bool mpsafe; if (pc != NULL) { - if (pc->pc_intr_establish != NULL) { - return (*pc->pc_intr_establish)(pc, ih, level, func, - arg); + if ((pc->pc_present & PCI_OVERRIDE_INTR_ESTABLISH) != 0) { + return (*pc->pc_ov->ov_intr_establish)(pc->pc_ctx, + pc, ih, level, func, arg); } if (pc->pc_super != NULL) { return pci_intr_establish(pc->pc_super, ih, level, func, @@ -313,8 +314,9 @@ { if (pc != NULL) { - if (pc->pc_intr_disestablish != NULL) { - (*pc->pc_intr_disestablish)(pc, cookie); + if ((pc->pc_present & PCI_OVERRIDE_INTR_ESTABLISH) != 0) { + (*pc->pc_ov->ov_intr_disestablish)(pc->pc_ctx, + pc, cookie); return; } if (pc->pc_super != NULL) { Index: src/sys/arch/x86/pci/pci_machdep.c diff -u src/sys/arch/x86/pci/pci_machdep.c:1.42 src/sys/arch/x86/pci/pci_machdep.c:1.43 --- src/sys/arch/x86/pci/pci_machdep.c:1.42 Tue Apr 27 23:33:14 2010 +++ src/sys/arch/x86/pci/pci_machdep.c Wed Apr 28 21:27:14 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: pci_machdep.c,v 1.42 2010/04/27 23:33:14 dyoung Exp $ */ +/* $NetBSD: pci_machdep.c,v 1.43 2010/04/28 21:27:14 dyoung Exp $ */ /*- * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. @@ -73,7 +73,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.42 2010/04/27 23:33:14 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.43 2010/04/28 21:27:14 dyoung Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -83,6 +83,7 @@ #include <sys/device.h> #include <sys/bus.h> #include <sys/cpu.h> +#include <sys/kmem.h> #include <uvm/uvm_extern.h> @@ -95,6 +96,7 @@ #include <dev/isa/isavar.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> +#include <dev/pci/pccbbreg.h> #include <dev/pci/pcidevs.h> #include "acpica.h" @@ -401,8 +403,10 @@ pcitag_t tag; if (pc != NULL) { - if (pc->pc_make_tag != NULL) - return (*pc->pc_make_tag)(pc, bus, device, function); + if ((pc->pc_present & PCI_OVERRIDE_MAKE_TAG) != 0) { + return (*pc->pc_ov->ov_make_tag)(pc->pc_ctx, + pc, bus, device, function); + } if (pc->pc_super != NULL) { return pci_make_tag(pc->pc_super, bus, device, function); @@ -436,8 +440,9 @@ { if (pc != NULL) { - if (pc->pc_decompose_tag != NULL) { - (*pc->pc_decompose_tag)(pc, tag, bp, dp, fp); + if ((pc->pc_present & PCI_OVERRIDE_DECOMPOSE_TAG) != 0) { + (*pc->pc_ov->ov_decompose_tag)(pc->pc_ctx, + pc, tag, bp, dp, fp); return; } if (pc->pc_super != NULL) { @@ -469,8 +474,7 @@ } pcireg_t -pci_conf_read( pci_chipset_tag_t pc, pcitag_t tag, - int reg) +pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg) { pcireg_t data; struct pci_conf_lock ocl; @@ -478,8 +482,10 @@ KASSERT((reg & 0x3) == 0); if (pc != NULL) { - if (pc->pc_conf_read != NULL) - return (*pc->pc_conf_read)(pc, tag, reg); + if ((pc->pc_present & PCI_OVERRIDE_CONF_READ) != 0) { + return (*pc->pc_ov->ov_conf_read)(pc->pc_ctx, + pc, tag, reg); + } if (pc->pc_super != NULL) return pci_conf_read(pc->pc_super, tag, reg); } @@ -500,16 +506,16 @@ } void -pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, - pcireg_t data) +pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, pcireg_t data) { struct pci_conf_lock ocl; KASSERT((reg & 0x3) == 0); if (pc != NULL) { - if (pc->pc_conf_write != NULL) { - (*pc->pc_conf_write)(pc, tag, reg, data); + if ((pc->pc_present & PCI_OVERRIDE_CONF_WRITE) != 0) { + (*pc->pc_ov->ov_conf_write)(pc->pc_ctx, pc, tag, reg, + data); return; } if (pc->pc_super != NULL) { @@ -750,3 +756,75 @@ (*bridge_hook->func)(pc, tag, bridge_hook->arg); } } + +static const void * +bit_to_function_pointer(const struct pci_overrides *ov, uint64_t bit) +{ + switch (bit) { + case PCI_OVERRIDE_CONF_READ: + return ov->ov_conf_read; + case PCI_OVERRIDE_CONF_WRITE: + return ov->ov_conf_write; + case PCI_OVERRIDE_INTR_MAP: + return ov->ov_intr_map; + case PCI_OVERRIDE_INTR_STRING: + return ov->ov_intr_string; + case PCI_OVERRIDE_INTR_EVCNT: + return ov->ov_intr_evcnt; + case PCI_OVERRIDE_INTR_ESTABLISH: + return ov->ov_intr_establish; + case PCI_OVERRIDE_INTR_DISESTABLISH: + return ov->ov_intr_disestablish; + case PCI_OVERRIDE_MAKE_TAG: + return ov->ov_make_tag; + case PCI_OVERRIDE_DECOMPOSE_TAG: + return ov->ov_decompose_tag; + default: + return NULL; + } +} + +void +pci_chipset_tag_destroy(pci_chipset_tag_t pc) +{ + kmem_free(pc, sizeof(struct pci_chipset_tag)); +} + +int +pci_chipset_tag_create(pci_chipset_tag_t opc, const uint64_t present, + const struct pci_overrides *ov, void *ctx, pci_chipset_tag_t *pcp) +{ + uint64_t bit, bits, nbits; + pci_chipset_tag_t pc; + const void *fp; + + if (ov == NULL || present == 0) + return EINVAL; + + pc = kmem_alloc(sizeof(struct pci_chipset_tag), KM_SLEEP); + + if (pc == NULL) + return ENOMEM; + + pc->pc_super = opc; + + for (bits = present; bits != 0; bits = nbits) { + nbits = bits & (bits - 1); + bit = nbits ^ bits; + if ((fp = bit_to_function_pointer(ov, bit)) == NULL) { + printf("%s: missing bit %" PRIx64 "\n", __func__, bit); + goto einval; + } + } + + pc->pc_ov = ov; + pc->pc_present = present; + pc->pc_ctx = ctx; + + *pcp = pc; + + return 0; +einval: + kmem_free(pc, sizeof(struct pci_chipset_tag)); + return EINVAL; +}