diff options
author | Ariane van der Steldt <ariane@cvs.openbsd.org> | 2009-05-07 11:30:28 +0000 |
---|---|---|
committer | Ariane van der Steldt <ariane@cvs.openbsd.org> | 2009-05-07 11:30:28 +0000 |
commit | fafe38bd094e3a643eaeee0713da3672120f6a7c (patch) | |
tree | ee6da62c994498f28d5a4adcab1dd67174c0e5fe /sys/arch/amd64/pci | |
parent | caafa8002519442d0d9a9929c9dcce73c0576c5f (diff) |
Move amas device from arch/amd64 to dev/pci and enable it in i386 as well.
amas defaults to disabled on both amd64 and i386.
"Go for it!" kettenis@
Diffstat (limited to 'sys/arch/amd64/pci')
-rw-r--r-- | sys/arch/amd64/pci/amas.c | 284 |
1 files changed, 0 insertions, 284 deletions
diff --git a/sys/arch/amd64/pci/amas.c b/sys/arch/amd64/pci/amas.c deleted file mode 100644 index 0dc07848d04..00000000000 --- a/sys/arch/amd64/pci/amas.c +++ /dev/null @@ -1,284 +0,0 @@ -/* $OpenBSD: amas.c,v 1.2 2009/04/20 20:29:11 ariane Exp $ */ - -/* - * Copyright (c) 2009 Ariane van der Steldt <ariane@stack.nl> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Device: amas (AMD memory access/address switch). - * - * Driver for the amd athlon/opteron 64 address map. - * This device is integrated in 64-bit Athlon and Opteron cpus - * and contains mappings for memory to processor nodes. - */ - -#include <machine/amas.h> - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/device.h> - -#include <dev/pci/pcivar.h> -#include <dev/pci/pcireg.h> -#include <dev/pci/pcidevs.h> - -int amas_match(struct device*, void*, void*); -void amas_attach(struct device*, struct device*, void*); - -/* - * Amas device layout: - * - * - base/limit registers (on 0x0f, 0x10, 0x11) - * - extended base/limit registers (on 0x10) - * - * 0x0f, 0x10 support up to 8 nodes - * 0x11 supports up to 1 nodes - * - * base/limit registers use bits [31..16] to indicate address [39..24] - * extended base/limit registers use bits [7..0] to indicate address [47..40] - * base/limit addresses need to be shifted <<24 for memory address - * extended base/limit addresses need to be shifted <<40 for memory address - */ - -#define AMAS_REG_BASE(node) (0x0040 + 0x08 * (node)) -#define AMAS_REG_LIMIT(node) (0x0044 + 0x08 * (node)) -#define AMAS_REG_EXTBASE(node) (0x0140 + 0x08 * (node)) -#define AMAS_REG_EXTLIMIT(node) (0x0144 + 0x08 * (node)) - -#define AMAS_REG_BL_ADDR(reg) (((reg) >> 16) & 0xffff) -#define AMAS_REG_EBL_ADDR(ereg) ((ereg) & 0xff) - -#define AMAS_REG_BL_SHIFT (24) -#define AMAS_REG_EBL_SHIFT (40) - -#define AMAS_REG_BL_PGSHIFT (AMAS_REG_BL_SHIFT - PAGE_SHIFT) -#define AMAS_REG_EBL_PGSHIFT (AMAS_REG_EBL_SHIFT - PAGE_SHIFT) - -/* - * Convert an address in amas to a page number. - * - * The device uses an inclusive mapping, where the upper bound address - * must be all 1's after shifting. - * The device driver uses C-style array indices, hence the +1 in the _LIMIT - * macro. - */ -#define AMAS_ADDR2PAGE_BASE(base, ebase) \ - (((base) << AMAS_REG_BL_PGSHIFT) | ((ebase) << AMAS_REG_EBL_PGSHIFT)) -#define AMAS_ADDR2PAGE_LIMIT(base, ebase) \ - (((base + 1) << AMAS_REG_BL_PGSHIFT) | ((ebase) << AMAS_REG_EBL_PGSHIFT)) - -/* - * Node and interleave description. - * - base contains node selection [10..8] (on 0x0f, 0x10) - * - limit contains node selection bitmask [10..8] (on 0x0f, 0x10) - * - limit contains destination node [2..0] (on 0x0f, 0x10) - */ -#define AMAS_DST_NODE(base, limit) ((limit) & 0x07) -#define AMAS_INTL_ENABLE(base, limit) (((base) >> 8) & 0x07) -#define AMAS_INTL_SELECTOR(base, limit) (((limit) >> 8) & 0x07) - -/* - * Defines for family. - * Corresponds to the amas_feature[] constant below. - */ -#define AMAS_FAM_0Fh (0) -#define AMAS_FAM_10h (1) -#define AMAS_FAM_11h (2) - -/* - * Feature tests. - * - * 0x11 supports at max 1 node, 0x0f and 0x10 support up to 8 nodes. - * 0x11 has extended address registers. - * 0x0f, 0x10 can interleave memory. - */ -struct amas_feature_t { - int maxnodes; - int can_intl; - int has_extended_bl; -}; -static const struct amas_feature_t amas_feature[] = { - /* Family 0x0f */ - { 8, 1, 0 }, - /* Family 0x10 */ - { 8, 1, 1 }, - /* Family 0x11 */ - { 1, 0, 0 }, -}; - -/* Probe code. */ -struct cfattach amas_ca = { - sizeof(struct amas_softc), - amas_match, - amas_attach -}; - -struct cfdriver amas_cd = { - NULL, - "amas", - DV_DULL -}; - -const struct pci_matchid amas_devices[] = { - { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_0F_ADDR }, - { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_10_ADDR }, - { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_AMD64_11_ADDR }, -}; - -int -amas_match(struct device *parent, void *match, void *aux) -{ - struct pci_attach_args* pa = aux; - - if (pci_matchbyid(pa, amas_devices, nitems(amas_devices))) - return 2; /* override pchb */ - return 0; -} - -void -amas_attach(struct device *parent, struct device *self, void *aux) -{ - struct pci_attach_args *pa = aux; - struct amas_softc *amas = (struct amas_softc*)self; -#ifdef DEBUG - paddr_t start_pg, end_pg; - int nodes, i; -#endif /* DEBUG */ - - amas->pa_tag = pa->pa_tag; - amas->pa_pc = pa->pa_pc; - - switch (PCI_PRODUCT(pa->pa_id)) { - case PCI_PRODUCT_AMD_AMD64_0F_ADDR: - amas->family = AMAS_FAM_0Fh; - break; - case PCI_PRODUCT_AMD_AMD64_10_ADDR: - amas->family = AMAS_FAM_10h; - break; - case PCI_PRODUCT_AMD_AMD64_11_ADDR: - amas->family = AMAS_FAM_11h; - break; - } - -#ifdef DEBUG - nodes = amas_intl_nodes(amas); - - printf(":"); - if (nodes != 0) { - printf(" interleaved across %d nodes", nodes); - } else { - for (i = 0; i < AMAS_MAX_NODES; i++) { - amas_get_pagerange(amas, i, &start_pg, &end_pg); - - if (start_pg == 0 && end_pg == 0) - printf(" []"); - else - printf(" [%p, %p]", start_pg, end_pg); - } - } -#endif /* DEBUG */ - printf("\n"); - - return; -} - -/* - * Returns the number of nodes across which the memory is interleaved. - * Returns 0 if the memory is not interleaved. - */ -int -amas_intl_nodes(struct amas_softc *amas) -{ - pcireg_t base_reg, limit_reg; - int mask; - - if (!amas_feature[amas->family].can_intl) - return 0; - - /* - * Use node 0 on amas device to find interleave information. - * Node 0 is always present. - */ - - base_reg = pci_conf_read(amas->pa_pc, amas->pa_tag, AMAS_REG_BASE(0)); - limit_reg = pci_conf_read(amas->pa_pc, amas->pa_tag, AMAS_REG_LIMIT(0)); - mask = AMAS_INTL_ENABLE(base_reg, limit_reg); - - return mask == 0 ? 0 : mask + 1; -} - -/* - * Returns the range of memory that is contained on the given node. - * If the memory is interleaved, the result is undefined. - * - * The range is written in {start,end}_pg_idx. - * Note that these are page numbers and that these use array indices: - * pages are in this range if start <= pg_no < end. - * - * This device supports at most 8 nodes. - */ -void -amas_get_pagerange(struct amas_softc *amas, int node, - paddr_t *start_pg_idx, paddr_t *end_pg_idx) -{ - pcireg_t base, ebase, limit, elimit; - paddr_t base_addr, ebase_addr, limit_addr, elimit_addr; - - /* Sanity check: max AMAS_MAX_NODES supported. */ - KASSERT(node >= 0 && node < AMAS_MAX_NODES); - - if (node >= amas_feature[amas->family].maxnodes) { - /* Unsupported node: bail out early. */ - *start_pg_idx = 0; - *end_pg_idx = 0; - return; - } - - base = pci_conf_read(amas->pa_pc, amas->pa_tag, - AMAS_REG_BASE(node)); - limit = pci_conf_read(amas->pa_pc, amas->pa_tag, - AMAS_REG_LIMIT(node)); - base_addr = AMAS_REG_BL_ADDR(base); - limit_addr = AMAS_REG_BL_ADDR(limit); - - ebase = 0; - elimit = 0; - ebase_addr = 0; - elimit_addr = 0; -#if 0 /* Needs extended pci registers. */ - if (amas_feature[amas->family].has_extended_bl) { - ebase = pci_conf_read(amas->pa_pc, amas->pa_tag, - AMAS_REG_EXTBASE(node)); - elimit = pci_conf_read(amas->pa_pc, amas->pa_tag, - AMAS_REG_EXTLIMIT(node)); - ebase_addr = AMAS_REG_EBL_ADDR(ebase); - elimit_addr = AMAS_REG_EBL_ADDR(elimit); - } -#endif /* 0 */ - - if (base_addr == limit_addr && ebase_addr == elimit_addr) { - /* no memory present */ - *start_pg_idx = 0; - *end_pg_idx = 0; - return; - } - - /* Guaranteed by spec. */ - KASSERT(node == AMAS_DST_NODE(base, limit)); - - *start_pg_idx = AMAS_ADDR2PAGE_BASE(base_addr, ebase_addr); - *end_pg_idx = AMAS_ADDR2PAGE_LIMIT(limit_addr, elimit_addr); - return; -} |