Snapshot: PCI busses are discovered, though no devices are enumerable

yet.
This commit is contained in:
Marcel Moolenaar 2010-04-17 02:28:28 +00:00
parent e936c9680d
commit 1b1d5788b2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/altix/; revision=206720
14 changed files with 489 additions and 41 deletions

View File

@ -116,6 +116,7 @@ ia64/ia64/vm_machdep.c standard
ia64/isa/isa.c optional isa
ia64/isa/isa_dma.c optional isa
ia64/pci/pci_cfgreg.c optional pci
ia64/sgisn/sgisn_pcib.c standard
isa/syscons_isa.c optional sc
isa/vga_isa.c optional vga
kern/imgact_elf32.c optional compat_freebsd32

View File

@ -65,7 +65,7 @@ sgisn_probe(struct uart_bas *bas)
{
struct ia64_sal_result result;
result = ia64_sal_entry(SAL_SGISN_INFO, 0, 0, 0, 0, 0, 0, 0);
result = ia64_sal_entry(SAL_SGISN_SN_INFO, 0, 0, 0, 0, 0, 0, 0);
return ((result.sal_status != 0) ? ENXIO : 0);
}

View File

@ -28,11 +28,12 @@
#include <sys/param.h>
#include <sys/bus.h>
#include <machine/md_var.h>
#include <machine/pal.h>
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/actables.h>
#include <dev/acpica/acpivar.h>
#include <machine/pal.h>
int
acpi_machdep_init(device_t dev)
@ -57,3 +58,37 @@ acpi_cpu_c1()
{
ia64_call_pal_static(PAL_HALT_LIGHT, 0, 0, 0);
}
void *
acpi_find_table(const char *sig)
{
ACPI_PHYSICAL_ADDRESS rsdp_ptr;
ACPI_TABLE_RSDP *rsdp;
ACPI_TABLE_XSDT *xsdt;
ACPI_TABLE_HEADER *table;
UINT64 addr;
u_int i, count;
if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0)
return (NULL);
rsdp = (ACPI_TABLE_RSDP *)IA64_PHYS_TO_RR7(rsdp_ptr);
xsdt = (ACPI_TABLE_XSDT *)IA64_PHYS_TO_RR7(rsdp->XsdtPhysicalAddress);
count = (UINT64 *)((char *)xsdt + xsdt->Header.Length) -
xsdt->TableOffsetEntry;
for (i = 0; i < count; i++) {
addr = xsdt->TableOffsetEntry[i];
table = (ACPI_TABLE_HEADER *)IA64_PHYS_TO_RR7(addr);
if (strncmp(table->Signature, sig, ACPI_NAME_SIZE) != 0)
continue;
if (ACPI_FAILURE(AcpiTbChecksum((void *)table, table->Length)))
continue;
return (table);
}
return (NULL);
}

View File

@ -26,7 +26,6 @@
* $FreeBSD$
*/
#include "opt_bootp.h"
#include "opt_isa.h"
#include <sys/param.h>
@ -53,10 +52,6 @@ SYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL);
/* SI_ORDER_MIDDLE is hookable */
SYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL);
#ifdef BOOTP
void bootpc_init(void);
#endif
#ifdef DEV_ISA
#include <isa/isavar.h>
device_t isa_bus_device = 0;

View File

@ -210,7 +210,9 @@ ia64_setup_intr(const char *name, int irq, driver_filter_t filter,
sa = sapic_lookup(irq, &xiv);
if (sa == NULL) {
/* XXX unlock */
return (EINVAL);
printf("XXX %s: no I/O SAPIC -- can't setup IRQ %u\n",
__func__, irq);
return (0);
}
if (xiv == 0) {

View File

@ -174,6 +174,70 @@ struct kva_md_info kmi;
#define Mhz 1000000L
#define Ghz (1000L*Mhz)
#define SN_SAL_SET_OS_FEATURE_SET 0x02000066
#define OSF_ACPI_ENABLE 2
#define OSF_PCISEGMENT_ENABLE 3
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/actables.h>
#include <dev/acpica/acpivar.h>
static void
srat_dump_entry(ACPI_SUBTABLE_HEADER *entry, void *arg)
{
ACPI_SRAT_CPU_AFFINITY *cpu;
ACPI_SRAT_MEM_AFFINITY *mem;
uint32_t domain;
uint16_t sapicid;
switch (entry->Type) {
case ACPI_SRAT_TYPE_CPU_AFFINITY:
cpu = (ACPI_SRAT_CPU_AFFINITY *)entry;
domain = cpu->ProximityDomainLo |
cpu->ProximityDomainHi[0] << 8 |
cpu->ProximityDomainHi[1] << 16 |
cpu->ProximityDomainHi[2] << 24;
sapicid = (cpu->ApicId << 8) | cpu->LocalSapicEid;
printf("SRAT: Sapic ID %u domain %d: %s\n", sapicid, domain,
(cpu->Flags & ACPI_SRAT_CPU_ENABLED) ? "enabled" :
"disabled");
break;
case ACPI_SRAT_TYPE_MEMORY_AFFINITY:
mem = (ACPI_SRAT_MEM_AFFINITY *)entry;
printf("SRAT: memory domain %d addr %lx len %lx: %s\n",
mem->ProximityDomain, mem->BaseAddress, mem->Length,
(mem->Flags & ACPI_SRAT_MEM_ENABLED) ? "enabled" :
"disabled");
break;
default:
printf("SRAT: unknown type (%u)\n", entry->Type);
break;
}
}
static void
check_sn_sal(void)
{
struct ia64_sal_result r;
ACPI_TABLE_HEADER *tbl;
void *ptr;
r = ia64_sal_entry(SAL_SGISN_SN_INFO, 0, 0, 0, 0, 0, 0, 0);
printf("XXX: %s: stat=%ld, res0=%#lx, res1=%#lx, res2=%#lx\n",
__func__, r.sal_status, r.sal_result[0], r.sal_result[1],
r.sal_result[2]);
if (r.sal_status != 0)
return;
tbl = ptr = acpi_find_table(ACPI_SIG_SRAT);
printf("XXX: %s: SRAT table at %p\n", __func__, ptr);
acpi_walk_subtables((char *)ptr + sizeof(ACPI_TABLE_SRAT),
(char *)ptr + tbl->Length, srat_dump_entry, ptr);
tbl = acpi_find_table(ACPI_SIG_SLIT);
printf("XXX: %s: SLIT table at %p\n", __func__, tbl);
}
static void
identifycpu(void)
{
@ -508,6 +572,22 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t size)
pcpu->pc_acpi_id = 0xffffffff;
}
void
cpu_pcpu_setup(struct pcpu *pc, u_int acpi_id, u_int sapic_id)
{
struct ia64_sal_result r;
pc->pc_acpi_id = acpi_id;
pc->pc_md.lid = IA64_LID_SET_SAPIC_ID(sapic_id);
r = ia64_sal_entry(SAL_SGISN_SAPIC_INFO, sapic_id, 0, 0, 0, 0, 0, 0);
if (r.sal_status == 0) {
pc->pc_md.sgisn_nasid = r.sal_result[0];
pc->pc_md.sgisn_subnode = r.sal_result[1];
pc->pc_md.sgisn_slice = r.sal_result[2];
}
}
void
spinlock_enter(void)
{
@ -745,16 +825,11 @@ ia64_init(void)
ia64_set_k4((u_int64_t)pcpup);
pcpu_init(pcpup, 0, sizeof(pcpu0));
dpcpu_init((void *)kernend, 0);
cpu_pcpu_setup(pcpup, ~0U, ia64_get_lid());
kernend += DPCPU_SIZE;
PCPU_SET(curthread, &thread0);
/*
* Initialize the console before we print anything out.
*/
cninit();
/* OUTPUT NOW ALLOWED */
#if 0
if (ia64_pal_base != 0) {
ia64_pal_base &= ~IA64_ID_PAGE_MASK;
/*
@ -765,6 +840,7 @@ ia64_init(void)
printf("PAL code mapped by the kernel's TR\n");
} else
printf("PAL code not found\n");
#endif
/*
* Wire things up so we can call the firmware.
@ -775,9 +851,18 @@ ia64_init(void)
ia64_sal_init();
calculate_frequencies();
/*
* Initialize the console before we print anything out.
*/
cninit();
/* OUTPUT NOW ALLOWED */
if (metadata_missing)
printf("WARNING: loader(8) metadata is missing!\n");
check_sn_sal();
/* Get FPSWA interface */
fpswa_iface = (bootinfo.bi_fpswa == 0) ? NULL :
(struct fpswa_iface *)IA64_PHYS_TO_RR7(bootinfo.bi_fpswa);

View File

@ -66,11 +66,9 @@ MALLOC_DEFINE(M_SMP, "SMP", "SMP related allocations");
void ia64_ap_startup(void);
#define LID_SAPIC(x) ((u_int)((x) >> 16))
#define LID_SAPIC_ID(x) ((u_int)((x) >> 24) & 0xff)
#define LID_SAPIC_EID(x) ((u_int)((x) >> 16) & 0xff)
#define LID_SAPIC_SET(id,eid) (((id & 0xff) << 8 | (eid & 0xff)) << 16);
#define LID_SAPIC_MASK 0xffff0000UL
#define SAPIC_ID_GET_ID(x) ((u_int)((x) >> 8) & 0xff)
#define SAPIC_ID_GET_EID(x) ((u_int)(x) & 0xff)
#define SAPIC_ID_SET(id, eid) ((u_int)(((id) & 0xff) << 8) | ((eid) & 0xff))
/* Variables used by os_boot_rendez and ia64_ap_startup */
struct pcpu *ap_pcpu;
@ -251,18 +249,18 @@ cpu_mp_probe(void)
}
void
cpu_mp_add(u_int acpiid, u_int apicid, u_int apiceid)
cpu_mp_add(u_int acpi_id, u_int id, u_int eid)
{
struct pcpu *pc;
u_int64_t lid;
void *dpcpu;
u_int cpuid;
u_int cpuid, sapic_id;
lid = LID_SAPIC_SET(apicid, apiceid);
cpuid = ((ia64_get_lid() & LID_SAPIC_MASK) == lid) ? 0 : smp_cpus++;
sapic_id = SAPIC_ID_SET(id, eid);
cpuid = (IA64_LID_GET_SAPIC_ID(ia64_get_lid()) == sapic_id)
? 0 : smp_cpus++;
KASSERT((all_cpus & (1UL << cpuid)) == 0,
("%s: cpu%d already in CPU map", __func__, acpiid));
("%s: cpu%d already in CPU map", __func__, acpi_id));
if (cpuid != 0) {
pc = (struct pcpu *)malloc(sizeof(*pc), M_SMP, M_WAITOK);
@ -272,23 +270,25 @@ cpu_mp_add(u_int acpiid, u_int apicid, u_int apiceid)
} else
pc = pcpup;
pc->pc_acpi_id = acpiid;
pc->pc_md.lid = lid;
all_cpus |= (1UL << cpuid);
cpu_pcpu_setup(pc, acpi_id, sapic_id);
all_cpus |= (1UL << pc->pc_cpuid);
}
void
cpu_mp_announce()
{
struct pcpu *pc;
uint32_t sapic_id;
int i;
for (i = 0; i <= mp_maxid; i++) {
pc = pcpu_find(i);
if (pc != NULL) {
sapic_id = IA64_LID_GET_SAPIC_ID(pc->pc_md.lid);
printf("cpu%d: ACPI Id=%x, SAPIC Id=%x, SAPIC Eid=%x",
i, pc->pc_acpi_id, LID_SAPIC_ID(pc->pc_md.lid),
LID_SAPIC_EID(pc->pc_md.lid));
i, pc->pc_acpi_id, SAPIC_ID_GET_ID(sapic_id),
SAPIC_ID_GET_EID(sapic_id));
if (i == 0)
printf(" (BSP)\n");
else
@ -420,21 +420,19 @@ ipi_all_but_self(int ipi)
}
/*
* Send an IPI to the specified processor. The lid parameter holds the
* cr.lid (CR64) contents of the target processor. Only the id and eid
* fields are used here.
* Send an IPI to the specified processor.
*/
void
ipi_send(struct pcpu *cpu, int xiv)
{
u_int lid;
u_int sapic_id;
KASSERT(xiv != 0, ("ipi_send"));
lid = LID_SAPIC(cpu->pc_md.lid);
sapic_id = IA64_LID_GET_SAPIC_ID(cpu->pc_md.lid);
ia64_mf();
ia64_st8(&(ia64_pib->ib_ipi[lid][0]), xiv);
ia64_st8(&(ia64_pib->ib_ipi[sapic_id][0]), xiv);
ia64_mf_a();
CTR3(KTR_SMP, "ipi_send(%p, %d): cpuid=%d", cpu, xiv, PCPU_GET(cpuid));
}

View File

@ -30,6 +30,12 @@
#ifndef _MACHINE_IA64_CPU_H_
#define _MACHINE_IA64_CPU_H_
/*
* Local Interrupt ID.
*/
#define IA64_LID_GET_SAPIC_ID(x) ((u_int)((x) >> 16) & 0xffff)
#define IA64_LID_SET_SAPIC_ID(x) ((u_int)((x) & 0xffff) << 16)
/*
* Definition of DCR bits.
*/

View File

@ -61,6 +61,7 @@ ia64_bsp_adjust(uint64_t bsp, int nslots)
#ifdef _KERNEL
struct _special;
struct pcpu;
struct thread;
struct trapframe;
@ -76,9 +77,11 @@ extern uint64_t ia64_lapic_addr;
extern long Maxmem;
void *acpi_find_table(const char *sig);
void busdma_swi(void);
int copyout_regstack(struct thread *, uint64_t *, uint64_t *);
void cpu_mp_add(u_int, u_int, u_int);
void cpu_pcpu_setup(struct pcpu *, u_int, u_int);
int do_ast(struct trapframe *);
void ia32_trap(int, struct trapframe *);
int ia64_count_cpus(void);

View File

@ -52,6 +52,9 @@ struct pcpu_md {
uint64_t lid; /* local CPU ID */
uint64_t clock; /* Clock counter. */
uint64_t clockadj; /* Clock adjust. */
uint32_t sgisn_nasid;
uint32_t sgisn_subnode;
uint32_t sgisn_slice;
uint32_t awake:1; /* CPU is awake? */
struct pcpu_stats stats; /* Interrupt stats. */
#ifdef _KERNEL

View File

@ -114,10 +114,13 @@ struct sal_ap_wakeup_descriptor {
#define SAL_FREQ_BASE 0x01000012
#define SAL_UPDATE_PAL 0x01000020
#define SAL_SGISN_INFO 0x0200001e
#define SAL_SGISN_SAPIC_INFO 0x0200001d
#define SAL_SGISN_SN_INFO 0x0200001e
#define SAL_SGISN_PUTC 0x02000021
#define SAL_SGISN_GETC 0x02000022
#define SAL_SGISN_POLL 0x02000026
#define SAL_SGISN_IOHUB_INFO 0x02000055
#define SAL_SGISN_IOBUS_INFO 0x02000056
/* SAL_SET_VECTORS event handler types */
#define SAL_OS_MCA 0

105
sys/ia64/include/sgisn.h Normal file
View File

@ -0,0 +1,105 @@
/*-
* Copyright (c) 2010 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _MACHINE_SGISN_H_
#define _MACHINE_SGISN_H_
#define SGISN_GEOID_MODULE(id) (((id) >> 0) & 0xffffffffu)
#define SGISN_GEOID_TYPE(id) (((id) >> 32) & 0xff)
#define SGISN_GEOID_SLAB(id) (((id) >> 40) & 0xff)
#define SGISN_GEOID_ADDIT(id) (((id) >> 48) & 0xffff);
#define SGISN_GEOID_CPU_SLICE(id) ((SGISN_GEOID_ADDIT(id) >> 0) & 0xff)
#define SGISN_GEOID_DEV_BUS(id) ((SGISN_GEOID_ADDIT(id) >> 0) & 0xff)
#define SGISN_GEOID_DEV_SLOT(id) ((SGISN_GEOID_ADDIT(id) >> 8) & 0xff)
#define SGISN_GEOID_MEM_BUS(id) ((SGISN_GEOID_ADDIT(id) >> 0) & 0xff)
#define SGISN_GEOID_MEM_SLOT(id) ((SGISN_GEOID_ADDIT(id) >> 8) & 0xff)
#define SGISN_GEO_TYPE_INVALID 0
#define SGISN_GEO_TYPE_MODULE 1
#define SGISN_GEO_TYPE_NODE 2
#define SGISN_GEO_TYPE_RTR 3
#define SGISN_GEO_TYPE_IOC 4
#define SGISN_GEO_TYPE_DEV 5 /* PCI device */
#define SGISN_GEO_TYPE_CPU 6
#define SGISN_GEO_TYPE_MEM 7
#define SGISN_HUB_NITTES 8
#define SGISN_HUB_NWIDGETS 16
struct sgisn_widget {
uint32_t wgt_hwmfg;
uint32_t wgt_hwrev;
uint32_t wgt_hwpn;
uint8_t wgt_port;
char _pad[3];
uint64_t wgt_private;
uint64_t wgt_provider;
uint64_t wgt_vertex;
};
struct sgisn_hub {
uint64_t hub_geoid;
uint16_t hub_nasid;
uint16_t hub_peer_nasid;
char _pad[4];
uint64_t hub_pointer;
uint64_t hub_dma_itte[SGISN_HUB_NITTES];
struct sgisn_widget hub_widget[SGISN_HUB_NWIDGETS];
void *hdi_nodepda;
void *hdi_node_vertex;
uint32_t hub_pci_maxseg;
uint32_t hub_pci_maxbus;
};
struct sgisn_irq {
uint64_t irq_unused;
uint16_t irq_nasid;
char _pad1[2];
u_int irq_slice;
u_int irq_cpuid;
u_int irq_no;
u_int irq_pin;
uint64_t irq_xtaddr;
u_int irq_br_type;
char _pad2[4];
uint64_t irq_bridge;
uint64_t irq_io_info;
u_int irq_last;
u_int irq_cookie;
u_int irq_flags;
u_int irq_refcnt;
};
struct sgisn_dev {
uint64_t dev_bar[6];
uint64_t dev_rom;
uint64_t dev_handle;
};
#endif /* !_MACHINE_SGISN_H_ */

View File

@ -70,7 +70,7 @@ pci_cfgregread(int bus, int slot, int func, int reg, int len)
register_t is;
u_long addr;
addr = pci_sal_address(0, bus, slot, func, reg);
addr = pci_sal_address(bus >> 8, bus & 0xff, slot, func, reg);
if (addr == ~0ul)
return (~0);
@ -91,7 +91,7 @@ pci_cfgregwrite(int bus, int slot, int func, int reg, uint32_t data, int len)
register_t is;
u_long addr;
addr = pci_sal_address(0, bus, slot, func, reg);
addr = pci_sal_address(bus >> 8, bus & 0xff, slot, func, reg);
if (addr == ~0ul)
return;

212
sys/ia64/sgisn/sgisn_pcib.c Normal file
View File

@ -0,0 +1,212 @@
/*-
* Copyright (c) 2010 Marcel Moolenaar
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/pcpu.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
#include <machine/pci_cfgreg.h>
#include <machine/sal.h>
#include <machine/sgisn.h>
static struct sgisn_hub sgisn_pcib_hub;
struct sgisn_pcib_softc {
device_t sc_dev;
u_int sc_busnr;
};
static int sgisn_pcib_attach(device_t);
static void sgisn_pcib_identify(driver_t *, device_t);
static int sgisn_pcib_probe(device_t);
static int sgisn_pcib_read_ivar(device_t, device_t, int, uintptr_t *);
static int sgisn_pcib_write_ivar(device_t, device_t, int, uintptr_t);
static int sgisn_pcib_maxslots(device_t);
static uint32_t sgisn_pcib_cfgread(device_t, u_int, u_int, u_int, u_int, int);
static void sgisn_pcib_cfgwrite(device_t, u_int, u_int, u_int, u_int, uint32_t,
int);
/*
* Bus interface definitions.
*/
static device_method_t sgisn_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, sgisn_pcib_identify),
DEVMETHOD(device_probe, sgisn_pcib_probe),
DEVMETHOD(device_attach, sgisn_pcib_attach),
/* Bus interface */
DEVMETHOD(bus_read_ivar, sgisn_pcib_read_ivar),
DEVMETHOD(bus_write_ivar, sgisn_pcib_write_ivar),
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, sgisn_pcib_maxslots),
DEVMETHOD(pcib_read_config, sgisn_pcib_cfgread),
DEVMETHOD(pcib_write_config, sgisn_pcib_cfgwrite),
DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt),
{ 0, 0 }
};
static driver_t sgisn_pcib_driver = {
"pcib",
sgisn_pcib_methods,
sizeof(struct sgisn_pcib_softc),
};
devclass_t pcib_devclass;
DRIVER_MODULE(pcib, nexus, sgisn_pcib_driver, pcib_devclass, 0, 0);
static int
sgisn_pcib_maxslots(device_t dev)
{
return (31);
}
static uint32_t
sgisn_pcib_cfgread(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, int bytes)
{
u_int domain = device_get_unit(dev);
uint32_t val;
device_printf(dev, "%u:%u:%u: reg=%u", bus, slot, func, reg);
val = pci_cfgregread(domain << 8 | bus, slot, func, reg, bytes);
printf(" -> %u (%u bytes)\n", val, bytes);
return (val);
}
static void
sgisn_pcib_cfgwrite(device_t dev, u_int bus, u_int slot, u_int func,
u_int reg, uint32_t val, int bytes)
{
u_int domain = device_get_unit(dev);
device_printf(dev, "%u:%u:%u: reg=%u <- %u (%u bytes)\n", bus, slot,
func, reg, val, bytes);
pci_cfgregwrite(domain << 8 | bus, slot, func, reg, val, bytes);
}
static void
sgisn_pcib_identify(driver_t *drv, device_t bus)
{
struct ia64_sal_result r;
void *addr;
u_int seg;
sgisn_pcib_hub.hub_pci_maxseg = 0xffffffff;
sgisn_pcib_hub.hub_pci_maxbus = 0xff;
r = ia64_sal_entry(SAL_SGISN_IOHUB_INFO, PCPU_GET(md.sgisn_nasid),
ia64_tpa((uintptr_t)&sgisn_pcib_hub), 0, 0, 0, 0, 0);
if (r.sal_status != 0)
return;
printf("XXX: %s: maxseg=%u, maxbus=%u\n", __func__,
sgisn_pcib_hub.hub_pci_maxseg, sgisn_pcib_hub.hub_pci_maxbus);
for (seg = 0; seg <= sgisn_pcib_hub.hub_pci_maxseg; seg++) {
r = ia64_sal_entry(SAL_SGISN_IOBUS_INFO, seg, 0,
ia64_tpa((uintptr_t)&addr), 0, 0, 0, 0);
printf("XXX: %s: seg=%u: stat=%#lx, addr=%p\n", __func__, seg,
r.sal_status, addr);
if (r.sal_status == 0)
BUS_ADD_CHILD(bus, 100 + seg, drv->name, seg);
}
}
static int
sgisn_pcib_probe(device_t dev)
{
device_set_desc(dev, "SGI PCI-X host controller");
return (BUS_PROBE_DEFAULT);
}
static int
sgisn_pcib_attach(device_t dev)
{
struct sgisn_pcib_softc *sc;
sc = device_get_softc(dev);
sc->sc_dev = dev;
device_add_child(dev, "pci", -1);
return (bus_generic_attach(dev));
}
static int
sgisn_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *res)
{
struct sgisn_pcib_softc *sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_BUS:
*res = sc->sc_busnr;
return (0);
case PCIB_IVAR_DOMAIN:
*res = device_get_unit(dev);
return (0);
}
return (ENOENT);
}
static int
sgisn_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
{
struct sgisn_pcib_softc *sc = device_get_softc(dev);
switch (which) {
case PCIB_IVAR_BUS:
sc->sc_busnr = value;
return (0);
}
return (ENOENT);
}