* Completely rewrite the alpha busspace to hide the implementation from

the drivers.
* Remove legacy inx/outx support from chipset and replace with macros
  which call busspace.
* Rework pci config accesses to route through the pcib device instead of
  calling a MD function directly.

With these changes it is possible to cleanly support machines which have
more than one independantly numbered PCI busses. As a bonus, the new
busspace implementation should be measurably faster than the old one.
This commit is contained in:
Doug Rabson 2000-08-28 21:48:13 +00:00
parent 5809aaba67
commit 21c3015a24
72 changed files with 3686 additions and 4792 deletions

View file

@ -513,7 +513,7 @@ bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
} while (buflen > 0);
if (buflen != 0) {
printf("bus_dmamap_load: Too many segs! buf_len = 0x%lx\n",
printf("bus_dmamap_load: Too many segs! buf_len = 0x%x\n",
buflen);
error = EFBIG;
}

289
sys/alpha/alpha/busspace.c Normal file
View file

@ -0,0 +1,289 @@
/*-
* Copyright (c) 2000 Doug Rabson
* 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$
*/
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/kobj.h>
#include <machine/bus.h>
#include "busspace_if.h"
void
busspace_generic_read_multi_1(struct alpha_busspace *space, size_t offset,
u_int8_t *addr, size_t count)
{
while (count--) {
*addr++ = space->ab_ops->abo_read_1(space, offset);
}
}
void
busspace_generic_read_multi_2(struct alpha_busspace *space, size_t offset,
u_int16_t *addr, size_t count)
{
while (count--) {
*addr++ = space->ab_ops->abo_read_2(space, offset);
}
}
void
busspace_generic_read_multi_4(struct alpha_busspace *space, size_t offset,
u_int32_t *addr, size_t count)
{
while (count--) {
*addr++ = space->ab_ops->abo_read_4(space, offset);
}
}
void
busspace_generic_read_region_1(struct alpha_busspace *space, size_t offset,
u_int8_t *addr, size_t count)
{
while (count--) {
*addr++ = space->ab_ops->abo_read_1(space, offset);
offset += 1;
}
}
void
busspace_generic_read_region_2(struct alpha_busspace *space, size_t offset,
u_int16_t *addr, size_t count)
{
while (count--) {
*addr++ = space->ab_ops->abo_read_2(space, offset);
offset += 2;
}
}
void
busspace_generic_read_region_4(struct alpha_busspace *space, size_t offset,
u_int32_t *addr, size_t count)
{
while (count--) {
*addr++ = space->ab_ops->abo_read_4(space, offset);
offset += 4;
}
}
void
busspace_generic_write_multi_1(struct alpha_busspace *space, size_t offset,
const u_int8_t *addr, size_t count)
{
while (count--) {
space->ab_ops->abo_write_1(space, offset, *addr++);
}
}
void
busspace_generic_write_multi_2(struct alpha_busspace *space, size_t offset,
const u_int16_t *addr, size_t count)
{
while (count--) {
space->ab_ops->abo_write_2(space, offset, *addr++);
}
}
void
busspace_generic_write_multi_4(struct alpha_busspace *space, size_t offset,
const u_int32_t *addr, size_t count)
{
while (count--) {
space->ab_ops->abo_write_4(space, offset, *addr++);
}
}
void
busspace_generic_write_region_1(struct alpha_busspace *space, size_t offset,
const u_int8_t *addr, size_t count)
{
while (count--) {
space->ab_ops->abo_write_1(space, offset, *addr++);
offset += 1;
}
}
void
busspace_generic_write_region_2(struct alpha_busspace *space, size_t offset,
const u_int16_t *addr, size_t count)
{
while (count--) {
space->ab_ops->abo_write_2(space, offset, *addr++);
offset += 2;
}
}
void
busspace_generic_write_region_4(struct alpha_busspace *space, size_t offset,
const u_int32_t *addr, size_t count)
{
while (count--) {
space->ab_ops->abo_write_4(space, offset, *addr++);
offset += 4;
}
}
void
busspace_generic_set_multi_1(struct alpha_busspace *space, size_t offset,
u_int8_t value, size_t count)
{
while (count--) {
space->ab_ops->abo_write_1(space, offset, value);
}
}
void
busspace_generic_set_multi_2(struct alpha_busspace *space, size_t offset,
u_int16_t value, size_t count)
{
while (count--) {
space->ab_ops->abo_write_2(space, offset, value);
}
}
void
busspace_generic_set_multi_4(struct alpha_busspace *space, size_t offset,
u_int32_t value, size_t count)
{
while (count--) {
space->ab_ops->abo_write_4(space, offset, value);
}
}
void
busspace_generic_set_region_1(struct alpha_busspace *space, size_t offset,
u_int8_t value, size_t count)
{
while (count--) {
space->ab_ops->abo_write_1(space, offset, value);
offset += 1;
}
}
void
busspace_generic_set_region_2(struct alpha_busspace *space, size_t offset,
u_int16_t value, size_t count)
{
while (count--) {
space->ab_ops->abo_write_2(space, offset, value);
offset += 2;
}
}
void
busspace_generic_set_region_4(struct alpha_busspace *space, size_t offset,
u_int32_t value, size_t count)
{
while (count--) {
space->ab_ops->abo_write_4(space, offset, value);
offset += 4;
}
}
void
busspace_generic_copy_region_1(struct alpha_busspace *space,
size_t offset1, size_t offset2, size_t count)
{
u_int8_t value;
if (offset1 > offset2) {
while (count--) {
value = space->ab_ops->abo_read_1(space, offset1);
space->ab_ops->abo_write_1(space, offset2, value);
offset1 += 1;
offset2 += 1;
}
} else {
offset1 += count - 1;
offset2 += count - 1;
while (count--) {
value = space->ab_ops->abo_read_1(space, offset1);
space->ab_ops->abo_write_1(space, offset2, value);
offset1 -= 1;
offset2 -= 1;
}
}
}
void
busspace_generic_copy_region_2(struct alpha_busspace *space,
size_t offset1, size_t offset2, size_t count)
{
u_int16_t value;
if (offset1 > offset2) {
while (count--) {
value = space->ab_ops->abo_read_1(space, offset1);
space->ab_ops->abo_write_1(space, offset2, value);
offset1 += 2;
offset2 += 2;
}
} else {
offset1 += 2*(count - 1);
offset2 += 2*(count - 1);
while (count--) {
value = space->ab_ops->abo_read_2(space, offset1);
space->ab_ops->abo_write_2(space, offset2, value);
offset1 -= 2;
offset2 -= 2;
}
}
}
void
busspace_generic_copy_region_4(struct alpha_busspace *space,
size_t offset1, size_t offset2, size_t count)
{
u_int32_t value;
if (offset1 > offset2) {
while (count--) {
value = space->ab_ops->abo_read_4(space, offset1);
space->ab_ops->abo_write_4(space, offset2, value);
offset1 += 4;
offset2 += 4;
}
} else {
offset1 += 4*(count - 1);
offset2 += 4*(count - 1);
while (count--) {
value = space->ab_ops->abo_read_4(space, offset1);
space->ab_ops->abo_write_4(space, offset2, value);
offset1 -= 4;
offset2 -= 4;
}
}
}
void
busspace_generic_barrier(struct alpha_busspace *space, size_t offset, size_t len, int flags)
{
if (flags & BUS_SPACE_BARRIER_READ)
alpha_mb();
else
alpha_wmb();
}

View file

@ -54,6 +54,7 @@
#include <sys/timetc.h>
#include <machine/cpuconf.h>
#include <machine/bus.h>
#include <machine/clock.h>
#include <machine/clockvar.h>
#include <isa/isareg.h>

View file

@ -83,6 +83,7 @@
#include <machine/rpb.h>
#include <machine/cpuconf.h>
#include <machine/clock.h>
#include <machine/bus.h>
#include <alpha/pci/apecsvar.h>
#include <alpha/pci/ciavar.h>

View file

@ -247,8 +247,9 @@ default:
* Read the SIO IRQ routing register to determine where the
* interrupt will actually be routed. Thank you, NetBSD.
*/
pirqreg = chipset.cfgreadl(0, 0, 7, 0, SIO_PCIREG_PIRQ_RTCTRL);
pirqreg = apecs_pcib_read_config(0, 0, 7, 0,
SIO_PCIREG_PIRQ_RTCTRL, 4);
pirqline = (pirqreg >> (pirq * 8)) & 0xff;
if ((pirqline & 0x80) != 0)
panic("bad pirqline %d",pirqline);

View file

@ -36,6 +36,7 @@
#include <machine/rpb.h>
#include <machine/cpuconf.h>
#include <machine/clock.h>
#include <machine/bus.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <alpha/pci/t2var.h>
@ -57,8 +58,6 @@ extern int siocnattach __P((int, int));
extern int siogdbattach __P((int, int));
extern int sccnattach __P((void));
extern vm_offset_t t2_csr_base;
void
dec_2100_a500_init(cputype)
{

View file

@ -41,6 +41,7 @@
#include <machine/rpb.h>
#include <machine/cpuconf.h>
#include <machine/clock.h>
#include <machine/bus.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <alpha/pci/lcavar.h>
@ -265,7 +266,8 @@ dec_axppci_33_intr_map(void *arg)
return;
}
pirqreg = chipset.cfgreadl(0, 0, 7, 0, SIO_PCIREG_PIRQ_RTCTRL);
pirqreg = lca_pcib_read_config(0, 0, 7, 0,
SIO_PCIREG_PIRQ_RTCTRL, 4);
#if 0
printf("dec_axppci_33_intr_map: device %d pin %c: pirq %d, reg = %x\n",
device, '@' + cfg->intpin, pirq, pirqreg);

View file

@ -42,7 +42,6 @@
#include <machine/clock.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include <alpha/pci/tsunamireg.h>
#include <alpha/pci/tsunamivar.h>
#include "sio.h"

File diff suppressed because it is too large Load diff

View file

@ -93,11 +93,25 @@ stw_nb(vm_offset_t va, u_int64_t r)
__asm__ __volatile__ ("stw %1,%0" : "=m"(*(u_int16_t*)va) : "r"(r));
}
static __inline void
stl_nb(vm_offset_t va, u_int64_t r)
{
__asm__ __volatile__ ("stl %1,%0" : "=m"(*(u_int32_t*)va) : "r"(r));
}
#ifdef _KERNEL
/*
* A kernel object for accessing memory-like spaces (port and
* memory spaces) using BWX instructions.
*/
struct bwx_space {
struct alpha_busspace_ops *ops;
u_int64_t base; /* base address of space */
};
void bwx_init_space(struct bwx_space *bwx, u_int64_t base);
#endif /* _KERNEL */
#endif /* !_MACHINE_BWX_H_ */

View file

@ -29,74 +29,12 @@
#ifndef _MACHINE_CHIPSET_H_
#define _MACHINE_CHIPSET_H_
typedef u_int8_t alpha_chipset_inb_t(u_int32_t port);
typedef u_int16_t alpha_chipset_inw_t(u_int32_t port);
typedef u_int32_t alpha_chipset_inl_t(u_int32_t port);
typedef void alpha_chipset_outb_t(u_int32_t port, u_int8_t data);
typedef void alpha_chipset_outw_t(u_int32_t port, u_int16_t data);
typedef void alpha_chipset_outl_t(u_int32_t port, u_int32_t data);
typedef u_int8_t alpha_chipset_readb_t(u_int32_t pa);
typedef u_int16_t alpha_chipset_readw_t(u_int32_t pa);
typedef u_int32_t alpha_chipset_readl_t(u_int32_t pa);
typedef void alpha_chipset_writeb_t(u_int32_t pa, u_int8_t data);
typedef void alpha_chipset_writew_t(u_int32_t pa, u_int16_t data);
typedef void alpha_chipset_writel_t(u_int32_t pa, u_int32_t data);
typedef int alpha_chipset_maxdevs_t(u_int bus);
typedef u_int8_t alpha_chipset_cfgreadb_t(u_int, u_int, u_int, u_int, u_int);
typedef u_int16_t alpha_chipset_cfgreadw_t(u_int, u_int, u_int, u_int, u_int);
typedef u_int32_t alpha_chipset_cfgreadl_t(u_int, u_int, u_int, u_int, u_int);
typedef void alpha_chipset_cfgwriteb_t(u_int, u_int, u_int, u_int, u_int,
u_int8_t);
typedef void alpha_chipset_cfgwritew_t(u_int, u_int, u_int, u_int, u_int,
u_int16_t);
typedef void alpha_chipset_cfgwritel_t(u_int, u_int, u_int, u_int, u_int,
u_int32_t);
typedef vm_offset_t alpha_chipset_addrcvt_t(vm_offset_t);
typedef u_int64_t alpha_chipset_read_hae_t(void);
typedef void alpha_chipset_write_hae_t(u_int64_t);
struct sgmap;
typedef struct alpha_chipset {
/*
* I/O port access
*/
alpha_chipset_inb_t* inb;
alpha_chipset_inw_t* inw;
alpha_chipset_inl_t* inl;
alpha_chipset_outb_t* outb;
alpha_chipset_outw_t* outw;
alpha_chipset_outl_t* outl;
/*
* Memory access
*/
alpha_chipset_readb_t* readb;
alpha_chipset_readw_t* readw;
alpha_chipset_readl_t* readl;
alpha_chipset_writeb_t* writeb;
alpha_chipset_writew_t* writew;
alpha_chipset_writel_t* writel;
/*
* PCI configuration access
*/
alpha_chipset_maxdevs_t* maxdevs;
alpha_chipset_cfgreadb_t* cfgreadb;
alpha_chipset_cfgreadw_t* cfgreadw;
alpha_chipset_cfgreadl_t* cfgreadl;
alpha_chipset_cfgwriteb_t* cfgwriteb;
alpha_chipset_cfgwritew_t* cfgwritew;
alpha_chipset_cfgwritel_t* cfgwritel;
/*
* PCI address space translation functions
*/
alpha_chipset_addrcvt_t* cvt_to_dense;
alpha_chipset_addrcvt_t* cvt_to_bwx;
/*
* Access the HAE register
*/

View file

@ -44,76 +44,6 @@ breakpoint(void)
#endif
#define inb(port) chipset.inb(port)
#define inw(port) chipset.inw(port)
#define inl(port) chipset.inl(port)
#define outb(port, data) chipset.outb(port, data)
#define outw(port, data) chipset.outw(port, data)
#define outl(port, data) chipset.outl(port, data)
#define readb(pa) chipset.readb(pa)
#define readw(pa) chipset.readw(pa)
#define readl(pa) chipset.readl(pa)
#define writeb(pa,v) chipset.writeb(pa,v)
#define writew(pa,v) chipset.writew(pa,v)
#define writel(pa,v) chipset.writel(pa,v)
/*
* Bulk i/o (for IDE driver).
*/
static __inline void insb(u_int32_t port, void *buffer, size_t count)
{
u_int8_t *p = (u_int8_t *) buffer;
while (count--)
*p++ = inb(port);
}
static __inline void insw(u_int32_t port, void *buffer, size_t count)
{
u_int16_t *p = (u_int16_t *) buffer;
while (count--)
*p++ = inw(port);
}
static __inline void insl(u_int32_t port, void *buffer, size_t count)
{
u_int32_t *p = (u_int32_t *) buffer;
while (count--)
*p++ = inl(port);
}
static __inline void outsb(u_int32_t port, const void *buffer, size_t count)
{
const u_int8_t *p = (const u_int8_t *) buffer;
while (count--)
outb(port, *p++);
}
static __inline void outsw(u_int32_t port, const void *buffer, size_t count)
{
const u_int16_t *p = (const u_int16_t *) buffer;
while (count--)
outw(port, *p++);
}
static __inline void outsl(u_int32_t port, const void *buffer, size_t count)
{
const u_int32_t *p = (const u_int32_t *) buffer;
while (count--)
outl(port, *p++);
}
/*
* String version of IO memory access ops:
*/
extern void memcpy_fromio(void *, u_int32_t, size_t);
extern void memcpy_toio(u_int32_t, void *, size_t);
extern void memcpy_io(u_int32_t, u_int32_t, size_t);
extern void memset_io(u_int32_t, int, size_t);
extern void memsetw(void *, int, size_t);
extern void memsetw_io(u_int32_t, int, size_t);
#endif /* _KERNEL */
#endif /* !_MACHINE_CPUFUNC_H_ */

View file

@ -70,4 +70,26 @@
#define SPARSE_WRITE_LONG(base, o, d) \
SPARSE_WRITE(base + SPARSE_LONG_OFFSET(o), d)
#ifdef _KERNEL
/*
* A kernel object for accessing memory-like spaces (port and
* memory spaces) using SWIZ instructions.
*/
typedef u_int32_t (*swiz_sethae_fn)(void *arg, u_int32_t hae);
struct swiz_space {
struct alpha_busspace_ops *ops;
u_int64_t base; /* base address of space */
swiz_sethae_fn sethae; /* function to set HAE */
void *arg; /* arg to sethae() */
};
void swiz_init_space(struct swiz_space *swiz, u_int64_t base);
void swiz_init_space_hae(struct swiz_space *swiz, u_int64_t base,
swiz_sethae_fn sethae, void *arg);
#endif /* _KERNEL */
#endif /* !_MACHINE_SWIZ_H_ */

View file

@ -220,7 +220,7 @@ static int
mcbus_setup_intr(device_t dev, device_t child, struct resource *r, int f,
driver_intr_t *intr, void *a, void **ac)
{
if (strncmp(device_get_name(child), "mcpcia", 6) == 0) {
if (strncmp(device_get_name(child), "pcib", 6) == 0) {
if (mcbus0_softc->sub_intr == NULL)
mcbus0_softc->sub_intr = intr;
return (0);
@ -232,7 +232,7 @@ mcbus_setup_intr(device_t dev, device_t child, struct resource *r, int f,
static int
mcbus_teardown_intr(device_t dev, device_t child, struct resource *i, void *c)
{
if (strncmp(device_get_name(child), "mcpcia", 6) == 0) {
if (strncmp(device_get_name(child), "pcib", 6) == 0) {
mcbus0_softc->sub_intr = NULL;
return (0);
} else {
@ -257,7 +257,7 @@ mcbus_add_child(struct mcbus_softc *mcbus, struct mcbus_device *mdev)
switch (mdev->ma_type) {
case MCBUS_TYPE_PCI:
dn = "mcpcia";
dn = "pcib";
ds = "MCPCIA PCI Bus Bridge";
un = mcpciaproto++;
break;

View file

@ -52,6 +52,9 @@
#include <alpha/pci/pcibus.h>
#include <pci/pcivar.h>
#include "alphapci_if.h"
#include "pcib_if.h"
static devclass_t mcpcia_devclass;
/* We're only allowing for one MCBUS right now */
@ -67,42 +70,18 @@ struct mcpcia_softc {
vm_offset_t smem_base; /* sparse memory */
vm_offset_t io_base; /* sparse i/o */
int mcpcia_inst; /* our mcpcia instance # */
struct swiz_space io_space; /* accessor for ports */
struct swiz_space mem_space; /* accessor for memory */
struct rman io_rman; /* resource manager for ports */
struct rman mem_rman; /* resource manager for memory */
};
static struct mcpcia_softc *mcpcia_eisa = NULL;
extern void dec_kn300_cons_init(void);
static int mcpcia_probe(device_t dev);
static int mcpcia_attach(device_t dev);
static int mcpcia_setup_intr(device_t, device_t, struct resource *, int,
driver_intr_t *, void *, void **);
static int
mcpcia_teardown_intr(device_t, device_t, struct resource *, void *);
static driver_intr_t mcpcia_intr;
static void mcpcia_enable_intr(struct mcpcia_softc *, int);
static void mcpcia_disable_intr(struct mcpcia_softc *, int);
static device_method_t mcpcia_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mcpcia_probe),
DEVMETHOD(device_attach, mcpcia_attach),
/* Bus interface */
DEVMETHOD(bus_setup_intr, mcpcia_setup_intr),
DEVMETHOD(bus_teardown_intr, mcpcia_teardown_intr),
DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
DEVMETHOD(bus_release_resource, pci_release_resource),
DEVMETHOD(bus_activate_resource, pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
{ 0, 0 }
};
static driver_t mcpcia_driver = {
"mcpcia", mcpcia_methods, sizeof (struct mcpcia_softc)
};
/*
* SGMAP window for ISA: 8M at 8M
*/
@ -129,354 +108,12 @@ do { \
} while (0)
static void mcpcia_dma_init(struct mcpcia_softc *);
static void mcpcia_sgmap_map(void *, vm_offset_t, vm_offset_t);
static void mcpcia_sgmap_map(void *, bus_addr_t, vm_offset_t);
#define MCPCIA_SOFTC(dev) (struct mcpcia_softc *) device_get_softc(dev)
static struct mcpcia_softc *mcpcia_root;
static alpha_chipset_inb_t mcpcia_inb;
static alpha_chipset_inw_t mcpcia_inw;
static alpha_chipset_inl_t mcpcia_inl;
static alpha_chipset_outb_t mcpcia_outb;
static alpha_chipset_outw_t mcpcia_outw;
static alpha_chipset_outl_t mcpcia_outl;
static alpha_chipset_readb_t mcpcia_readb;
static alpha_chipset_readw_t mcpcia_readw;
static alpha_chipset_readl_t mcpcia_readl;
static alpha_chipset_writeb_t mcpcia_writeb;
static alpha_chipset_writew_t mcpcia_writew;
static alpha_chipset_writel_t mcpcia_writel;
static alpha_chipset_maxdevs_t mcpcia_maxdevs;
static alpha_chipset_cfgreadb_t mcpcia_cfgreadb;
static alpha_chipset_cfgreadw_t mcpcia_cfgreadw;
static alpha_chipset_cfgreadl_t mcpcia_cfgreadl;
static alpha_chipset_cfgwriteb_t mcpcia_cfgwriteb;
static alpha_chipset_cfgwritew_t mcpcia_cfgwritew;
static alpha_chipset_cfgwritel_t mcpcia_cfgwritel;
static alpha_chipset_t mcpcia_chipset = {
mcpcia_inb,
mcpcia_inw,
mcpcia_inl,
mcpcia_outb,
mcpcia_outw,
mcpcia_outl,
mcpcia_readb,
mcpcia_readw,
mcpcia_readl,
mcpcia_writeb,
mcpcia_writew,
mcpcia_writel,
mcpcia_maxdevs,
mcpcia_cfgreadb,
mcpcia_cfgreadw,
mcpcia_cfgreadl,
mcpcia_cfgwriteb,
mcpcia_cfgwritew,
mcpcia_cfgwritel,
};
#define MCPCIA_NMBR(port) ((port >> 30) & 0x3)
#define MCPCIA_INST(port) mcpcias[MCPCIA_NMBR(port)]
#define MCPCIA_ADDR(port) (port & 0x3fffffff)
static u_int8_t
mcpcia_inb(u_int32_t port)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(port));
if (port < (1 << 16)) {
if (mcpcia_eisa == NULL) {
return (0xff);
}
return SPARSE_READ_BYTE(mcpcia_eisa->io_base, port);
}
return SPARSE_READ_BYTE(sc->io_base, MCPCIA_ADDR(port));
}
static u_int16_t
mcpcia_inw(u_int32_t port)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(port));
if (port < (1 << 16)) {
if (mcpcia_eisa == NULL) {
return (0xffff);
}
return SPARSE_READ_WORD(mcpcia_eisa->io_base, port);
}
return SPARSE_READ_WORD(sc->io_base, MCPCIA_ADDR(port));
}
static u_int32_t
mcpcia_inl(u_int32_t port)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(port));
return SPARSE_READ_LONG(sc->io_base, MCPCIA_ADDR(port));
}
static void
mcpcia_outb(u_int32_t port, u_int8_t data)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(port));
if (port < (1 << 16)) {
if (mcpcia_eisa)
SPARSE_WRITE_BYTE(mcpcia_eisa->io_base, port, data);
} else {
SPARSE_WRITE_BYTE(sc->io_base, MCPCIA_ADDR(port), data);
}
alpha_mb();
}
static void
mcpcia_outw(u_int32_t port, u_int16_t data)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(port));
if (port < (1 << 16)) {
if (mcpcia_eisa)
SPARSE_WRITE_WORD(mcpcia_eisa->io_base, port, data);
} else {
SPARSE_WRITE_WORD(sc->io_base, MCPCIA_ADDR(port), data);
}
alpha_mb();
}
static void
mcpcia_outl(u_int32_t port, u_int32_t data)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(port));
SPARSE_WRITE_LONG(sc->io_base, MCPCIA_ADDR(port), data);
alpha_mb();
}
static u_int8_t
mcpcia_readb(u_int32_t pa)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(pa));
if (pa < (8 << 20)) {
if (mcpcia_eisa == NULL) {
return (0xff);
}
return SPARSE_READ_BYTE(mcpcia_eisa->smem_base, pa);
}
return SPARSE_READ_BYTE(sc->smem_base, MCPCIA_ADDR(pa));
}
static u_int16_t
mcpcia_readw(u_int32_t pa)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(pa));
if (pa < (8 << 20)) {
if (mcpcia_eisa == NULL) {
return (0xffff);
}
return SPARSE_READ_WORD(mcpcia_eisa->smem_base, pa);
}
return SPARSE_READ_WORD(sc->smem_base, MCPCIA_ADDR(pa));
}
static u_int32_t
mcpcia_readl(u_int32_t pa)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(pa));
return SPARSE_READ_LONG(sc->smem_base, MCPCIA_ADDR(pa));
}
static void
mcpcia_writeb(u_int32_t pa, u_int8_t data)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(pa));
if (pa < (8 << 20)) {
if (mcpcia_eisa)
SPARSE_WRITE_BYTE(mcpcia_eisa->smem_base, pa, data);
} else {
SPARSE_WRITE_BYTE(sc->smem_base, MCPCIA_ADDR(pa), data);
}
alpha_mb();
}
static void
mcpcia_writew(u_int32_t pa, u_int16_t data)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(pa));
if (pa < (8 << 20)) {
if (mcpcia_eisa)
SPARSE_WRITE_WORD(mcpcia_eisa->smem_base, pa, data);
} else {
SPARSE_WRITE_WORD(sc->smem_base, MCPCIA_ADDR(pa), data);
}
alpha_mb();
}
static void
mcpcia_writel(u_int32_t pa, u_int32_t data)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(MCPCIA_INST(pa));
SPARSE_WRITE_LONG(sc->smem_base, MCPCIA_ADDR(pa), data);
alpha_mb();
}
static int
mcpcia_maxdevs(u_int b)
{
return (MCPCIA_MAXDEV);
}
static u_int32_t mcpcia_cfgread(u_int, u_int, u_int, u_int, u_int, int);
static void mcpcia_cfgwrite(u_int, u_int, u_int, u_int, u_int, int, u_int32_t);
#if 0
#define RCFGP printf
#else
#define RCFGP if (0) printf
#endif
static u_int32_t
mcpcia_cfgread(u_int bh, u_int bus, u_int slot, u_int func, u_int off, int sz)
{
device_t dev;
struct mcpcia_softc *sc;
u_int32_t *dp, data, rvp;
u_int64_t paddr;
RCFGP("CFGREAD %u.%u.%u.%u.%u.%d", bh, bus, slot, func, off, sz);
rvp = data = ~0;
if (bh == (u_int8_t)-1)
bh = bus >> 4;
dev = mcpcias[bh];
if (dev == (device_t) 0) {
RCFGP(" (no dev)\n");
return (data);
}
sc = MCPCIA_SOFTC(dev);
bus &= 0xf;
/*
* There's nothing in slot 0 on a primary bus.
*/
if (bus == 0 && (slot < 1 || slot >= MCPCIA_MAXDEV)) {
RCFGP(" (no slot)\n");
return (data);
}
paddr = bus << 21;
paddr |= slot << 16;
paddr |= func << 13;
paddr |= ((sz - 1) << 3);
paddr |= ((unsigned long) ((off >> 2) << 7));
paddr |= MCPCIA_PCI_CONF;
paddr |= sc->sysbase;
dp = (u_int32_t *)KV(paddr);
RCFGP(" hose %d MID%d paddr 0x%lx", bh, mcbus_get_mid(dev), paddr);
if (badaddr(dp, sizeof (*dp)) == 0) {
data = *dp;
}
if (data != ~0) {
if (sz == 1) {
rvp = SPARSE_BYTE_EXTRACT(off, data);
} else if (sz == 2) {
rvp = SPARSE_WORD_EXTRACT(off, data);
} else {
rvp = data;
}
} else {
rvp = data;
}
RCFGP(" data %x->0x%x\n", data, rvp);
return (rvp);
}
#if 0
#define WCFGP printf
#else
#define WCFGP if (0) printf
#endif
static void
mcpcia_cfgwrite(u_int bh, u_int bus, u_int slot, u_int func, u_int off,
int sz, u_int32_t data)
{
device_t dev;
struct mcpcia_softc *sc;
u_int32_t *dp;
u_int64_t paddr;
WCFGP("CFGWRITE %u.%u.%u.%u.%u.%d", bh, bus, slot, func, off, sz);
if (bh == (u_int8_t)-1)
bh = bus >> 4;
dev = mcpcias[bh];
if (dev == (device_t) 0) {
WCFGP(" (no dev)\n");
return;
}
sc = MCPCIA_SOFTC(dev);
bus &= 0xf;
/*
* There's nothing in slot 0 on a primary bus.
*/
if (bus == 0 && (slot < 1 || slot >= MCPCIA_MAXDEV)) {
WCFGP(" (no slot)\n");
return;
}
paddr = bus << 21;
paddr |= slot << 16;
paddr |= func << 13;
paddr |= ((sz - 1) << 3);
paddr |= ((unsigned long) ((off >> 2) << 7));
paddr |= MCPCIA_PCI_CONF;
paddr |= sc->sysbase;
dp = (u_int32_t *)KV(paddr);
WCFGP(" hose %d MID%d paddr 0x%lx\n", bh, mcbus_get_mid(dev), paddr);
if (badaddr(dp, sizeof (*dp)) == 0) {
u_int32_t new_data;
if (sz == 1) {
new_data = SPARSE_BYTE_INSERT(off, data);
} else if (sz == 2) {
new_data = SPARSE_WORD_INSERT(off, data);
} else {
new_data = data;
}
*dp = new_data;
}
}
static u_int8_t
mcpcia_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
return (u_int8_t) mcpcia_cfgread(h, b, s, f, r, 1);
}
static u_int16_t
mcpcia_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
return (u_int16_t) mcpcia_cfgread(h, b, s, f, r, 2);
}
static u_int32_t
mcpcia_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
return mcpcia_cfgread(h, b, s, f, r, 4);
}
static void
mcpcia_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
mcpcia_cfgwrite(h, b, s, f, r, 1, (u_int32_t) data);
}
static void
mcpcia_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
mcpcia_cfgwrite(h, b, s, f, r, 2, (u_int32_t) data);
}
static void
mcpcia_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
mcpcia_cfgwrite(h, b, s, f, r, 4, (u_int32_t) data);
}
static int
mcpcia_probe(device_t dev)
{
@ -503,7 +140,7 @@ mcpcia_probe(device_t dev)
if (unit == 0) {
pci_init_resources();
}
child = device_add_child(dev, "pcib", unit);
child = device_add_child(dev, "pci", -1);
device_set_ivars(child, &sc->mcpcia_inst);
return (0);
}
@ -518,7 +155,6 @@ mcpcia_attach(device_t dev)
int mid, gid, rval;
void *intr;
chipset = mcpcia_chipset;
mid = mcbus_get_mid(dev);
gid = mcbus_get_gid(dev);
@ -530,6 +166,25 @@ mcpcia_attach(device_t dev)
sc->smem_base = regs + MCPCIA_PCI_SPARSE;
sc->io_base = regs + MCPCIA_PCI_IOSPACE;
swiz_init_space(&sc->io_space, sc->io_base);
swiz_init_space(&sc->mem_space, sc->smem_base);
sc->io_rman.rm_start = 0;
sc->io_rman.rm_end = ~0u;
sc->io_rman.rm_type = RMAN_ARRAY;
sc->io_rman.rm_descr = "I/O ports";
if (rman_init(&sc->io_rman)
|| rman_manage_region(&sc->io_rman, 0x0, (1L << 32)))
panic("mcpcia_attach: io_rman");
sc->mem_rman.rm_start = 0;
sc->mem_rman.rm_end = ~0u;
sc->mem_rman.rm_type = RMAN_ARRAY;
sc->mem_rman.rm_descr = "I/O memory";
if (rman_init(&sc->mem_rman)
|| rman_manage_region(&sc->mem_rman, 0x0, (1L << 32)))
panic("mcpcia_attach: mem_rman");
/*
* Disable interrupts and clear errors prior to probing
*/
@ -538,7 +193,6 @@ mcpcia_attach(device_t dev)
REGVAL(MCPCIA_CAP_ERR(sc)) = 0xFFFFFFFF;
alpha_mb();
/*
* Say who we are
*/
@ -569,7 +223,12 @@ mcpcia_attach(device_t dev)
BUS_SETUP_INTR(p, dev, NULL, INTR_TYPE_MISC, mcpcia_intr, 0, &intr);
if (rval == 0) {
if (sc == mcpcia_eisa) {
busspace_isa_io = (struct alpha_busspace *)
&sc->io_space;
busspace_isa_mem = (struct alpha_busspace *)
&sc->mem_space;
printf("Attaching Real Console\n");
mcpcia_enable_intr(sc, 16);
dec_kn300_cons_init();
/*
* Enable EISA interrupts.
@ -681,8 +340,159 @@ mcpcia_teardown_intr(device_t dev, device_t child, struct resource *i, void *c)
return (rman_deactivate_resource(i));
}
static int
mcpcia_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static void *
mcpcia_cvt_dense(device_t dev, vm_offset_t addr)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
addr &= 0xffffffffUL;
return (void *) KV(addr | sc->dmem_base);
}
static struct alpha_busspace *
mcpcia_get_bustag(device_t dev, int type)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
switch (type) {
case SYS_RES_IOPORT:
return (struct alpha_busspace *) &sc->io_space;
case SYS_RES_MEMORY:
return (struct alpha_busspace *) &sc->mem_space;
}
return 0;
}
static struct rman *
mcpcia_get_rman(device_t dev, int type)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
switch (type) {
case SYS_RES_IOPORT:
return &sc->io_rman;
case SYS_RES_MEMORY:
return &sc->mem_rman;
}
return 0;
}
static int
mcpcia_maxslots(device_t dev)
{
return (MCPCIA_MAXDEV);
}
static u_int32_t
mcpcia_read_config(device_t dev, int bus, int slot, int func,
int off, int sz)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
u_int32_t *dp, data, rvp;
u_int64_t paddr;
rvp = data = ~0;
/*
* There's nothing in slot 0 on a primary bus.
*/
if (bus == 0 && (slot < 1 || slot >= MCPCIA_MAXDEV))
return (data);
paddr = bus << 21;
paddr |= slot << 16;
paddr |= func << 13;
paddr |= ((sz - 1) << 3);
paddr |= ((unsigned long) ((off >> 2) << 7));
paddr |= MCPCIA_PCI_CONF;
paddr |= sc->sysbase;
dp = (u_int32_t *)KV(paddr);
#if 0
printf("CFGREAD MID %d %d.%d.%d sz %d off %d -> paddr 0x%x",
mcbus_get_mid(dev), bus , slot, func, sz, off, paddr);
#endif
if (badaddr(dp, sizeof (*dp)) == 0) {
data = *dp;
}
if (data != ~0) {
if (sz == 1) {
rvp = SPARSE_BYTE_EXTRACT(off, data);
} else if (sz == 2) {
rvp = SPARSE_WORD_EXTRACT(off, data);
} else {
rvp = data;
}
} else {
rvp = data;
}
#if 0
printf(" data 0x%x -> 0x%x\n", data, rvp);
#endif
return (rvp);
}
static void
mcpcia_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa)
mcpcia_write_config(device_t dev, int bus, int slot, int func,
int off, u_int32_t data, int sz)
{
struct mcpcia_softc *sc = MCPCIA_SOFTC(dev);
u_int32_t *dp;
u_int64_t paddr;
/*
* There's nothing in slot 0 on a primary bus.
*/
if (bus != 0 && (slot < 1 || slot >= MCPCIA_MAXDEV))
return;
paddr = bus << 21;
paddr |= slot << 16;
paddr |= func << 13;
paddr |= ((sz - 1) << 3);
paddr |= ((unsigned long) ((off >> 2) << 7));
paddr |= MCPCIA_PCI_CONF;
paddr |= sc->sysbase;
dp = (u_int32_t *)KV(paddr);
if (badaddr(dp, sizeof (*dp)) == 0) {
u_int32_t new_data;
if (sz == 1) {
new_data = SPARSE_BYTE_INSERT(off, data);
} else if (sz == 2) {
new_data = SPARSE_WORD_INSERT(off, data);
} else {
new_data = data;
}
#if 0
printf("CFGWRITE MID%d %d.%d.%d sz %d off %d paddr %lx, data %x new_data %x\n",
mcbus_get_mid(dev), bus , slot, func, sz, off, paddr, data, new_data);
#endif
*dp = new_data;
}
}
static void
mcpcia_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa)
{
u_int64_t *sgtable = arg;
int index = alpha_btop(ba - MCPCIA_ISA_SG_MAPPED_BASE);
@ -807,4 +617,37 @@ mcpcia_intr(void *arg)
alpha_dispatch_intr(NULL, vec);
}
DRIVER_MODULE(mcpcia, mcbus, mcpcia_driver, mcpcia_devclass, 0, 0);
static device_method_t mcpcia_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mcpcia_probe),
DEVMETHOD(device_attach, mcpcia_attach),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, mcpcia_read_ivar),
DEVMETHOD(bus_setup_intr, mcpcia_setup_intr),
DEVMETHOD(bus_teardown_intr, mcpcia_teardown_intr),
DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
DEVMETHOD(bus_release_resource, pci_release_resource),
DEVMETHOD(bus_activate_resource, pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
/* alphapci interface */
DEVMETHOD(alphapci_cvt_dense, mcpcia_cvt_dense),
DEVMETHOD(alphapci_get_bustag, mcpcia_get_bustag),
DEVMETHOD(alphapci_get_rman, mcpcia_get_rman),
/* pcib interface */
DEVMETHOD(pcib_maxslots, mcpcia_maxslots),
DEVMETHOD(pcib_read_config, mcpcia_read_config),
DEVMETHOD(pcib_write_config, mcpcia_write_config),
{ 0, 0 }
};
static driver_t mcpcia_driver = {
"pcib", mcpcia_methods, sizeof (struct mcpcia_softc)
};
DRIVER_MODULE(pcib, mcbus, mcpcia_driver, mcpcia_devclass, 0, 0);

View file

@ -0,0 +1,59 @@
#
# Copyright (c) 2000 Doug Rabson
# 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$
#
#include <sys/bus.h>
#include <alpha/pci/pcibus.h>
INTERFACE alphapci;
CODE {
static void *null_cvt(device_t dev, vm_offset_t ba)
{
return 0;
}
};
METHOD void * cvt_dense {
device_t dev;
vm_offset_t ba;
} DEFAULT null_cvt;
METHOD void * cvt_bwx {
device_t dev;
vm_offset_t ba;
} DEFAULT null_cvt;
METHOD struct alpha_busspace * get_bustag {
device_t dev;
int type;
} DEFAULT pci_get_bustag;
METHOD struct rman * get_rman {
device_t dev;
int type;
} DEFAULT pci_get_rman;

View file

@ -94,105 +94,14 @@ struct apecs_softc {
#define APECS_SOFTC(dev) (struct apecs_softc*) device_get_softc(dev)
static alpha_chipset_inb_t apecs_swiz_inb;
static alpha_chipset_inw_t apecs_swiz_inw;
static alpha_chipset_inl_t apecs_swiz_inl;
static alpha_chipset_outb_t apecs_swiz_outb;
static alpha_chipset_outw_t apecs_swiz_outw;
static alpha_chipset_outl_t apecs_swiz_outl;
static alpha_chipset_readb_t apecs_swiz_readb;
static alpha_chipset_readw_t apecs_swiz_readw;
static alpha_chipset_readl_t apecs_swiz_readl;
static alpha_chipset_writeb_t apecs_swiz_writeb;
static alpha_chipset_writew_t apecs_swiz_writew;
static alpha_chipset_writel_t apecs_swiz_writel;
static alpha_chipset_maxdevs_t apecs_swiz_maxdevs;
static alpha_chipset_cfgreadb_t apecs_swiz_cfgreadb;
static alpha_chipset_cfgreadw_t apecs_swiz_cfgreadw;
static alpha_chipset_cfgreadl_t apecs_swiz_cfgreadl;
static alpha_chipset_cfgwriteb_t apecs_swiz_cfgwriteb;
static alpha_chipset_cfgwritew_t apecs_swiz_cfgwritew;
static alpha_chipset_cfgwritel_t apecs_swiz_cfgwritel;
static alpha_chipset_addrcvt_t apecs_cvt_dense;
static alpha_chipset_read_hae_t apecs_read_hae;
static alpha_chipset_write_hae_t apecs_write_hae;
static alpha_chipset_t apecs_swiz_chipset = {
apecs_swiz_inb,
apecs_swiz_inw,
apecs_swiz_inl,
apecs_swiz_outb,
apecs_swiz_outw,
apecs_swiz_outl,
apecs_swiz_readb,
apecs_swiz_readw,
apecs_swiz_readl,
apecs_swiz_writeb,
apecs_swiz_writew,
apecs_swiz_writel,
apecs_swiz_maxdevs,
apecs_swiz_cfgreadb,
apecs_swiz_cfgreadw,
apecs_swiz_cfgreadl,
apecs_swiz_cfgwriteb,
apecs_swiz_cfgwritew,
apecs_swiz_cfgwritel,
apecs_cvt_dense,
NULL,
apecs_read_hae,
apecs_write_hae,
};
static int
apecs_swiz_maxdevs(u_int b)
{
return 12; /* XXX */
}
static u_int8_t
apecs_swiz_inb(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_BYTE(KV(APECS_PCI_SIO), port);
}
static u_int16_t
apecs_swiz_inw(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_WORD(KV(APECS_PCI_SIO), port);
}
static u_int32_t
apecs_swiz_inl(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_LONG(KV(APECS_PCI_SIO), port);
}
static void
apecs_swiz_outb(u_int32_t port, u_int8_t data)
{
SPARSE_WRITE_BYTE(KV(APECS_PCI_SIO), port, data);
alpha_wmb();
}
static void
apecs_swiz_outw(u_int32_t port, u_int16_t data)
{
SPARSE_WRITE_WORD(KV(APECS_PCI_SIO), port, data);
alpha_wmb();
}
static void
apecs_swiz_outl(u_int32_t port, u_int32_t data)
{
SPARSE_WRITE_LONG(KV(APECS_PCI_SIO), port, data);
alpha_wmb();
}
/*
* Memory functions.
*
@ -204,14 +113,14 @@ apecs_swiz_outl(u_int32_t port, u_int32_t data)
static u_int32_t apecs_hae_mem;
#define REG1 (1UL << 24)
static __inline void
apecs_swiz_set_hae_mem(u_int32_t *pa)
static u_int32_t
apecs_set_hae_mem(void *arg, u_int32_t pa)
{
int s;
u_int32_t msb;
if(*pa >= REG1){
msb = *pa & 0xf8000000;
*pa -= msb;
if (pa >= REG1){
msb = pa & 0xf8000000;
pa -= msb;
s = splhigh();
if (msb != apecs_hae_mem) {
apecs_hae_mem = msb;
@ -221,217 +130,7 @@ apecs_swiz_set_hae_mem(u_int32_t *pa)
}
splx(s);
}
}
static u_int8_t
apecs_swiz_readb(u_int32_t pa)
{
alpha_mb();
apecs_swiz_set_hae_mem(&pa);
return SPARSE_READ_BYTE(KV(APECS_PCI_SPARSE), pa);
}
static u_int16_t
apecs_swiz_readw(u_int32_t pa)
{
alpha_mb();
apecs_swiz_set_hae_mem(&pa);
return SPARSE_READ_WORD(KV(APECS_PCI_SPARSE), pa);
}
static u_int32_t
apecs_swiz_readl(u_int32_t pa)
{
alpha_mb();
apecs_swiz_set_hae_mem(&pa);
return SPARSE_READ_LONG(KV(APECS_PCI_SPARSE), pa);
}
static void
apecs_swiz_writeb(u_int32_t pa, u_int8_t data)
{
apecs_swiz_set_hae_mem(&pa);
SPARSE_WRITE_BYTE(KV(APECS_PCI_SPARSE), pa, data);
alpha_wmb();
}
static void
apecs_swiz_writew(u_int32_t pa, u_int16_t data)
{
apecs_swiz_set_hae_mem(&pa);
SPARSE_WRITE_WORD(KV(APECS_PCI_SPARSE), pa, data);
alpha_wmb();
}
static void
apecs_swiz_writel(u_int32_t pa, u_int32_t data)
{
apecs_swiz_set_hae_mem(&pa);
SPARSE_WRITE_LONG(KV(APECS_PCI_SPARSE), pa, data);
alpha_wmb();
}
#define APECS_SWIZ_CFGOFF(b, s, f, r) \
(((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
#define APECS_TYPE1_SETUP(b,s,old_haxr2) if((b)) { \
do { \
(s) = splhigh(); \
(old_haxr2) = REGVAL(EPIC_HAXR2); \
alpha_mb(); \
REGVAL(EPIC_HAXR2) = (old_haxr2) | 0x1; \
alpha_mb(); \
} while(0); \
}
#define APECS_TYPE1_TEARDOWN(b,s,old_haxr2) if((b)) { \
do { \
alpha_mb(); \
REGVAL(EPIC_HAXR2) = (old_haxr2); \
alpha_mb(); \
splx((s)); \
} while(0); \
}
#define SWIZ_CFGREAD(b, s, f, r, width, type) \
type val = ~0; \
int ipl = 0; \
u_int32_t old_haxr2 = 0; \
struct apecs_softc* sc = APECS_SOFTC(apecs0); \
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(sc->cfg0_base, off); \
alpha_mb(); \
APECS_TYPE1_SETUP(b,ipl,old_haxr2); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \
} \
APECS_TYPE1_TEARDOWN(b,ipl,old_haxr2); \
return val;
#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) \
int ipl = 0; \
u_int32_t old_haxr2 = 0; \
struct apecs_softc* sc = APECS_SOFTC(apecs0); \
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(sc->cfg0_base, off); \
alpha_mb(); \
APECS_TYPE1_SETUP(b,ipl,old_haxr2); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \
alpha_wmb(); \
} \
APECS_TYPE1_TEARDOWN(b,ipl,old_haxr2); \
return;
#if 1
static u_int8_t
apecs_swiz_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
SWIZ_CFGREAD(b, s, f, r, BYTE, u_int8_t);
}
static u_int16_t
apecs_swiz_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
SWIZ_CFGREAD(b, s, f, r, WORD, u_int16_t);
}
static u_int32_t
apecs_swiz_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
SWIZ_CFGREAD(b, s, f, r, LONG, u_int32_t);
}
static void
apecs_swiz_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
SWIZ_CFGWRITE(b, s, f, r, data, BYTE, u_int8_t);
}
static void
apecs_swiz_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
SWIZ_CFGWRITE(b, s, f, r, data, WORD, u_int16_t);
}
static void
apecs_swiz_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
SWIZ_CFGWRITE(b, s, f, r, data, LONG, u_int32_t);
}
#else
static u_int8_t
apecs_swiz_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
struct apecs_softc* sc = APECS_SOFTC(apecs0);
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r);
alpha_mb();
if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_BYTE_OFFSET(off)), 1)) return ~0;
return SPARSE_READ_BYTE(sc->cfg0_base, off);
}
static u_int16_t
apecs_swiz_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
struct apecs_softc* sc = APECS_SOFTC(apecs0);
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r);
alpha_mb();
if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_WORD_OFFSET(off)), 2)) return ~0;
return SPARSE_READ_WORD(sc->cfg0_base, off);
}
static u_int32_t
apecs_swiz_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
struct apecs_softc* sc = APECS_SOFTC(apecs0);
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r);
alpha_mb();
if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_LONG_OFFSET(off)), 4)) return ~0;
return SPARSE_READ_LONG(sc->cfg0_base, off);
}
static void
apecs_swiz_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
struct apecs_softc* sc = APECS_SOFTC(apecs0);
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r);
if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_BYTE_OFFSET(off)), 1)) return;
SPARSE_WRITE_BYTE(sc->cfg0_base, off, data);
alpha_wmb();
}
static void
apecs_swiz_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
struct apecs_softc* sc = APECS_SOFTC(apecs0);
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r);
if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_WORD_OFFSET(off)), 2)) return;
SPARSE_WRITE_WORD(sc->cfg0_base, off, data);
alpha_wmb();
}
static void
apecs_swiz_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
struct apecs_softc* sc = APECS_SOFTC(apecs0);
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r);
if (badaddr((caddr_t)(sc->cfg0_base + SPARSE_LONG_OFFSET(off)), 4)) return;
SPARSE_WRITE_LONG(sc->cfg0_base, off, data);
alpha_wmb();
}
#endif
static vm_offset_t
apecs_cvt_dense(vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (addr | APECS_PCI_DENSE);
return pa;
}
static u_int64_t
@ -444,7 +143,7 @@ static void
apecs_write_hae(u_int64_t hae)
{
u_int32_t pa = hae;
apecs_swiz_set_hae_mem(&pa);
apecs_set_hae_mem(0, pa);
}
static int apecs_probe(device_t dev);
@ -495,7 +194,7 @@ apecs_sgmap_invalidate(void)
}
static void
apecs_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa)
apecs_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa)
{
u_int64_t *sgtable = arg;
int index = alpha_btop(ba - APECS_SGMAP_BASE);
@ -544,10 +243,18 @@ void
apecs_init()
{
static int initted = 0;
static struct swiz_space io_space, mem_space;
if (initted) return;
initted = 1;
swiz_init_space(&io_space, KV(APECS_PCI_SIO));
swiz_init_space_hae(&mem_space, KV(APECS_PCI_SPARSE),
apecs_set_hae_mem, 0);
busspace_isa_io = (struct alpha_busspace *) &io_space;
busspace_isa_mem = (struct alpha_busspace *) &mem_space;
chipset = apecs_swiz_chipset;
if (platform.pci_intr_init)

View file

@ -34,6 +34,15 @@
#include <machine/bus.h>
#include <sys/rman.h>
#include <pci/pcivar.h>
#include <machine/swiz.h>
#include <alpha/pci/apecsreg.h>
#include <alpha/pci/apecsvar.h>
#include "alphapci_if.h"
#include "pcib_if.h"
#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa)
static devclass_t pcib_devclass;
@ -50,13 +59,109 @@ apecs_pcib_probe(device_t dev)
static int
apecs_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
if (which == PCIB_IVAR_HOSE) {
if (which == PCIB_IVAR_BUS) {
*result = 0;
return 0;
}
return ENOENT;
}
static void *
apecs_pcib_cvt_dense(device_t dev, vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (void *) KV(addr | APECS_PCI_DENSE);
}
static int
apecs_pcib_maxslots(device_t dev)
{
return 31;
}
#define APECS_SWIZ_CFGOFF(b, s, f, r) \
(((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
#define APECS_TYPE1_SETUP(b,s,old_haxr2) if((b)) { \
do { \
(s) = splhigh(); \
(old_haxr2) = REGVAL(EPIC_HAXR2); \
alpha_mb(); \
REGVAL(EPIC_HAXR2) = (old_haxr2) | 0x1; \
alpha_mb(); \
} while(0); \
}
#define APECS_TYPE1_TEARDOWN(b,s,old_haxr2) if((b)) { \
do { \
alpha_mb(); \
REGVAL(EPIC_HAXR2) = (old_haxr2); \
alpha_mb(); \
splx((s)); \
} while(0); \
}
#define SWIZ_CFGREAD(b, s, f, r, width, type) do { \
type val = ~0; \
int ipl = 0; \
u_int32_t old_haxr2 = 0; \
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); \
vm_offset_t kv = \
SPARSE_##width##_ADDRESS(KV(APECS_PCI_CONF), off); \
alpha_mb(); \
APECS_TYPE1_SETUP(b,ipl,old_haxr2); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \
} \
APECS_TYPE1_TEARDOWN(b,ipl,old_haxr2); \
return val; \
} while (0)
#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) do { \
int ipl = 0; \
u_int32_t old_haxr2 = 0; \
vm_offset_t off = APECS_SWIZ_CFGOFF(b, s, f, r); \
vm_offset_t kv = \
SPARSE_##width##_ADDRESS(KV(APECS_PCI_CONF), off); \
alpha_mb(); \
APECS_TYPE1_SETUP(b,ipl,old_haxr2); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \
alpha_wmb(); \
} \
APECS_TYPE1_TEARDOWN(b,ipl,old_haxr2); \
return; \
} while (0)
u_int32_t
apecs_pcib_read_config(device_t dev, int b, int s, int f,
int reg, int width)
{
switch (width) {
case 1:
SWIZ_CFGREAD(b, s, f, reg, BYTE, u_int8_t);
case 2:
SWIZ_CFGREAD(b, s, f, reg, WORD, u_int16_t);
case 4:
SWIZ_CFGREAD(b, s, f, reg, LONG, u_int32_t);
}
return ~0;
}
static void
apecs_pcib_write_config(device_t dev, int b, int s, int f,
int reg, u_int32_t val, int width)
{
switch (width) {
case 1:
SWIZ_CFGWRITE(b, s, f, reg, val, BYTE, u_int8_t);
case 2:
SWIZ_CFGWRITE(b, s, f, reg, val, WORD, u_int16_t);
case 4:
SWIZ_CFGWRITE(b, s, f, reg, val, LONG, u_int32_t);
}
}
static device_method_t apecs_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, apecs_pcib_probe),
@ -72,6 +177,14 @@ static device_method_t apecs_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* alphapci interface */
DEVMETHOD(alphapci_cvt_dense, apecs_pcib_cvt_dense),
/* pcib interface */
DEVMETHOD(pcib_maxslots, apecs_pcib_maxslots),
DEVMETHOD(pcib_read_config, apecs_pcib_read_config),
DEVMETHOD(pcib_write_config, apecs_pcib_write_config),
{ 0, 0 }
};

View file

@ -26,5 +26,8 @@
* $FreeBSD$
*/
extern void apecs_init(void);
struct device;
extern void apecs_init(void);
u_int32_t apecs_pcib_read_config(struct device *dev, int b, int s, int f,
int reg, int width);

131
sys/alpha/pci/bwx.c Normal file
View file

@ -0,0 +1,131 @@
/*-
* Copyright (c) 2000 Doug Rabson
* 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$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <machine/bus.h>
#include <machine/bwx.h>
static u_int8_t
bwx_read_1(struct alpha_busspace *space, size_t offset)
{
struct bwx_space *bwx = (struct bwx_space *) space;
alpha_mb();
return ldbu(bwx->base + offset);
}
static u_int16_t
bwx_read_2(struct alpha_busspace *space, size_t offset)
{
struct bwx_space *bwx = (struct bwx_space *) space;
alpha_mb();
return ldwu(bwx->base + offset);
}
static u_int32_t
bwx_read_4(struct alpha_busspace *space, size_t offset)
{
struct bwx_space *bwx = (struct bwx_space *) space;
alpha_mb();
return ldl(bwx->base + offset);
}
static void
bwx_write_1(struct alpha_busspace *space, size_t offset, u_int8_t data)
{
struct bwx_space *bwx = (struct bwx_space *) space;
stb(bwx->base + offset, data);
alpha_mb();
}
static void
bwx_write_2(struct alpha_busspace *space, size_t offset, u_int16_t data)
{
struct bwx_space *bwx = (struct bwx_space *) space;
stw(bwx->base + offset, data);
alpha_mb();
}
static void
bwx_write_4(struct alpha_busspace *space, size_t offset, u_int32_t data)
{
struct bwx_space *bwx = (struct bwx_space *) space;
stl(bwx->base + offset, data);
alpha_mb();
}
static struct alpha_busspace_ops bwx_space_ops = {
bwx_read_1,
bwx_read_2,
bwx_read_4,
busspace_generic_read_multi_1,
busspace_generic_read_multi_2,
busspace_generic_read_multi_4,
busspace_generic_read_region_1,
busspace_generic_read_region_2,
busspace_generic_read_region_4,
bwx_write_1,
bwx_write_2,
bwx_write_4,
busspace_generic_write_multi_1,
busspace_generic_write_multi_2,
busspace_generic_write_multi_4,
busspace_generic_write_region_1,
busspace_generic_write_region_2,
busspace_generic_write_region_4,
busspace_generic_set_multi_1,
busspace_generic_set_multi_2,
busspace_generic_set_multi_4,
busspace_generic_set_region_1,
busspace_generic_set_region_2,
busspace_generic_set_region_4,
busspace_generic_copy_region_1,
busspace_generic_copy_region_2,
busspace_generic_copy_region_4,
busspace_generic_barrier,
};
void
bwx_init_space(struct bwx_space *bwx, u_int64_t base)
{
bwx->ops = &bwx_space_ops;
bwx->base = base;
}

View file

@ -116,6 +116,8 @@
#include <vm/vm.h>
#include <vm/vm_page.h>
#include "alphapci_if.h"
#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa)
static devclass_t cia_devclass;
@ -129,533 +131,36 @@ struct cia_softc {
#define CIA_SOFTC(dev) (struct cia_softc*) device_get_softc(dev)
static alpha_chipset_inb_t cia_bwx_inb, cia_swiz_inb;
static alpha_chipset_inw_t cia_bwx_inw, cia_swiz_inw;
static alpha_chipset_inl_t cia_bwx_inl, cia_swiz_inl;
static alpha_chipset_outb_t cia_bwx_outb, cia_swiz_outb;
static alpha_chipset_outw_t cia_bwx_outw, cia_swiz_outw;
static alpha_chipset_outl_t cia_bwx_outl, cia_swiz_outl;
static alpha_chipset_readb_t cia_bwx_readb, cia_swiz_readb;
static alpha_chipset_readw_t cia_bwx_readw, cia_swiz_readw;
static alpha_chipset_readl_t cia_bwx_readl, cia_swiz_readl;
static alpha_chipset_writeb_t cia_bwx_writeb, cia_swiz_writeb;
static alpha_chipset_writew_t cia_bwx_writew, cia_swiz_writew;
static alpha_chipset_writel_t cia_bwx_writel, cia_swiz_writel;
static alpha_chipset_maxdevs_t cia_bwx_maxdevs, cia_swiz_maxdevs;
static alpha_chipset_cfgreadb_t cia_bwx_cfgreadb, cia_swiz_cfgreadb;
static alpha_chipset_cfgreadw_t cia_bwx_cfgreadw, cia_swiz_cfgreadw;
static alpha_chipset_cfgreadl_t cia_bwx_cfgreadl, cia_swiz_cfgreadl;
static alpha_chipset_cfgwriteb_t cia_bwx_cfgwriteb, cia_swiz_cfgwriteb;
static alpha_chipset_cfgwritew_t cia_bwx_cfgwritew, cia_swiz_cfgwritew;
static alpha_chipset_cfgwritel_t cia_bwx_cfgwritel, cia_swiz_cfgwritel;
static alpha_chipset_addrcvt_t cia_cvt_dense, cia_cvt_bwx;
static alpha_chipset_read_hae_t cia_read_hae;
static alpha_chipset_write_hae_t cia_write_hae;
static alpha_chipset_t cia_bwx_chipset = {
cia_bwx_inb,
cia_bwx_inw,
cia_bwx_inl,
cia_bwx_outb,
cia_bwx_outw,
cia_bwx_outl,
cia_bwx_readb,
cia_bwx_readw,
cia_bwx_readl,
cia_bwx_writeb,
cia_bwx_writew,
cia_bwx_writel,
cia_bwx_maxdevs,
cia_bwx_cfgreadb,
cia_bwx_cfgreadw,
cia_bwx_cfgreadl,
cia_bwx_cfgwriteb,
cia_bwx_cfgwritew,
cia_bwx_cfgwritel,
cia_cvt_dense,
cia_cvt_bwx,
cia_read_hae,
cia_write_hae,
};
static alpha_chipset_t cia_swiz_chipset = {
cia_swiz_inb,
cia_swiz_inw,
cia_swiz_inl,
cia_swiz_outb,
cia_swiz_outw,
cia_swiz_outl,
cia_swiz_readb,
cia_swiz_readw,
cia_swiz_readl,
cia_swiz_writeb,
cia_swiz_writew,
cia_swiz_writel,
cia_swiz_maxdevs,
cia_swiz_cfgreadb,
cia_swiz_cfgreadw,
cia_swiz_cfgreadl,
cia_swiz_cfgwriteb,
cia_swiz_cfgwritew,
cia_swiz_cfgwritel,
cia_cvt_dense,
NULL,
cia_read_hae,
cia_write_hae,
};
static u_int8_t
cia_bwx_inb(u_int32_t port)
{
alpha_mb();
return ldbu(KV(CIA_EV56_BWIO+BWX_EV56_INT1 + port));
}
static u_int16_t
cia_bwx_inw(u_int32_t port)
{
alpha_mb();
return ldwu(KV(CIA_EV56_BWIO+BWX_EV56_INT2 + port));
}
static u_int32_t
cia_bwx_inl(u_int32_t port)
{
alpha_mb();
return ldl(KV(CIA_EV56_BWIO+BWX_EV56_INT4 + port));
}
static void
cia_bwx_outb(u_int32_t port, u_int8_t data)
{
stb(KV(CIA_EV56_BWIO+BWX_EV56_INT1 + port), data);
alpha_wmb();
}
static void
cia_bwx_outw(u_int32_t port, u_int16_t data)
{
stw(KV(CIA_EV56_BWIO+BWX_EV56_INT2 + port), data);
alpha_wmb();
}
static void
cia_bwx_outl(u_int32_t port, u_int32_t data)
{
stl(KV(CIA_EV56_BWIO+BWX_EV56_INT4 + port), data);
alpha_wmb();
}
static u_int8_t
cia_bwx_readb(u_int32_t pa)
{
alpha_mb();
return ldbu(KV(CIA_EV56_BWMEM+BWX_EV56_INT1 + pa));
}
static u_int16_t
cia_bwx_readw(u_int32_t pa)
{
alpha_mb();
return ldwu(KV(CIA_EV56_BWMEM+BWX_EV56_INT2 + pa));
}
static u_int32_t
cia_bwx_readl(u_int32_t pa)
{
alpha_mb();
return ldl(KV(CIA_EV56_BWMEM+BWX_EV56_INT4 + pa));
}
static void
cia_bwx_writeb(u_int32_t pa, u_int8_t data)
{
stb(KV(CIA_EV56_BWMEM+BWX_EV56_INT1 + pa), data);
alpha_wmb();
}
static void
cia_bwx_writew(u_int32_t pa, u_int16_t data)
{
stw(KV(CIA_EV56_BWMEM+BWX_EV56_INT2 + pa), data);
alpha_wmb();
}
static void
cia_bwx_writel(u_int32_t pa, u_int32_t data)
{
stl(KV(CIA_EV56_BWMEM+BWX_EV56_INT4 + pa), data);
alpha_wmb();
}
static int
cia_bwx_maxdevs(u_int b)
{
return 12; /* XXX */
}
static void
cia_clear_abort(void)
{
/*
* Some (apparently-common) revisions of EB164 and AlphaStation
* firmware do the Wrong thing with PCI master and target aborts,
* which are caused by accesing the configuration space of devices
* that don't exist (for example).
*
* To work around this, we clear the CIA error register's PCI
* master and target abort bits before touching PCI configuration
* space and check it afterwards. If it indicates a master or target
* abort, the device wasn't there so we return 0xffffffff.
*/
REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT;
alpha_mb();
alpha_pal_draina();
}
static int
cia_check_abort(void)
{
u_int32_t errbits;
int ba = 0;
alpha_pal_draina();
alpha_mb();
errbits = REGVAL(CIA_CSR_CIA_ERR);
if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT))
ba = 1;
if (errbits) {
REGVAL(CIA_CSR_CIA_ERR) = errbits;
alpha_mb();
alpha_pal_draina();
}
return ba;
}
#define CIA_BWX_CFGADDR(b, s, f, r) \
KV(((b) ? CIA_EV56_BWCONF1 : CIA_EV56_BWCONF0) \
| ((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
static u_int8_t
cia_bwx_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r);
u_int8_t data;
cia_clear_abort();
if (badaddr((caddr_t)va, 1)) {
cia_check_abort();
return ~0;
}
data = ldbu(va+BWX_EV56_INT1);
if (cia_check_abort())
return ~0;
return data;
}
static u_int16_t
cia_bwx_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r);
u_int16_t data;
cia_clear_abort();
if (badaddr((caddr_t)va, 2)) {
cia_check_abort();
return ~0;
}
data = ldwu(va+BWX_EV56_INT2);
if (cia_check_abort())
return ~0;
return data;
}
static u_int32_t
cia_bwx_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r);
u_int32_t data;
cia_clear_abort();
if (badaddr((caddr_t)va, 4)) {
cia_check_abort();
return ~0;
}
data = ldl(va+BWX_EV56_INT4);
if (cia_check_abort())
return ~0;
return data;
}
static void
cia_bwx_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r);
cia_clear_abort();
if (badaddr((caddr_t)va, 1)) return;
stb(va+BWX_EV56_INT1, data);
cia_check_abort();
}
static void
cia_bwx_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r);
if (badaddr((caddr_t)va, 2)) return;
stw(va+BWX_EV56_INT2, data);
cia_check_abort();
}
static void
cia_bwx_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r);
if (badaddr((caddr_t)va, 4)) return;
stl(va+BWX_EV56_INT4, data);
cia_check_abort();
}
static u_int8_t
cia_swiz_inb(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_BYTE(KV(CIA_PCI_SIO1), port);
}
static u_int16_t
cia_swiz_inw(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_WORD(KV(CIA_PCI_SIO1), port);
}
static u_int32_t
cia_swiz_inl(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_LONG(KV(CIA_PCI_SIO1), port);
}
static void
cia_swiz_outb(u_int32_t port, u_int8_t data)
{
SPARSE_WRITE_BYTE(KV(CIA_PCI_SIO1), port, data);
alpha_wmb();
}
static void
cia_swiz_outw(u_int32_t port, u_int16_t data)
{
SPARSE_WRITE_WORD(KV(CIA_PCI_SIO1), port, data);
alpha_wmb();
}
static void
cia_swiz_outl(u_int32_t port, u_int32_t data)
{
SPARSE_WRITE_LONG(KV(CIA_PCI_SIO1), port, data);
alpha_wmb();
}
static __inline void
cia_swiz_set_hae_mem(u_int32_t *pa)
cia_swiz_set_hae_mem(void *arg, u_int32_t pa)
{
/* Only bother with region 1 */
#define REG1 (7 << 29)
if ((cia_hae_mem & REG1) != (*pa & REG1)) {
if ((cia_hae_mem & REG1) != (pa & REG1)) {
/*
* Seems fairly paranoid but this is what Linux does...
*/
u_int32_t msb = *pa & REG1;
u_int32_t msb = pa & REG1;
int s = splhigh();
cia_hae_mem = (cia_hae_mem & ~REG1) | msb;
REGVAL(CIA_CSR_HAE_MEM) = cia_hae_mem;
alpha_mb();
cia_hae_mem = REGVAL(CIA_CSR_HAE_MEM);
splx(s);
*pa -= msb;
}
}
static u_int8_t
cia_swiz_readb(u_int32_t pa)
{
alpha_mb();
cia_swiz_set_hae_mem(&pa);
return SPARSE_READ_BYTE(KV(CIA_PCI_SMEM1), pa);
}
static u_int16_t
cia_swiz_readw(u_int32_t pa)
{
alpha_mb();
cia_swiz_set_hae_mem(&pa);
return SPARSE_READ_WORD(KV(CIA_PCI_SMEM1), pa);
}
static u_int32_t
cia_swiz_readl(u_int32_t pa)
{
alpha_mb();
cia_swiz_set_hae_mem(&pa);
return SPARSE_READ_LONG(KV(CIA_PCI_SMEM1), pa);
}
static void
cia_swiz_writeb(u_int32_t pa, u_int8_t data)
{
cia_swiz_set_hae_mem(&pa);
SPARSE_WRITE_BYTE(KV(CIA_PCI_SMEM1), pa, data);
alpha_wmb();
}
static void
cia_swiz_writew(u_int32_t pa, u_int16_t data)
{
cia_swiz_set_hae_mem(&pa);
SPARSE_WRITE_WORD(KV(CIA_PCI_SMEM1), pa, data);
alpha_wmb();
}
static void
cia_swiz_writel(u_int32_t pa, u_int32_t data)
{
cia_swiz_set_hae_mem(&pa);
SPARSE_WRITE_LONG(KV(CIA_PCI_SMEM1), pa, data);
alpha_wmb();
}
static int
cia_swiz_maxdevs(u_int b)
{
return 12; /* XXX */
}
#define CIA_SWIZ_CFGOFF(b, s, f, r) \
(((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
/* when doing a type 1 pci configuration space access, we
* must set a bit in the CIA_CSR_CFG register & clear it
* when we're done
*/
#define CIA_TYPE1_SETUP(b,s,old_cfg) if((b)) { \
do { \
(s) = splhigh(); \
(old_cfg) = REGVAL(CIA_CSR_CFG); \
alpha_mb(); \
REGVAL(CIA_CSR_CFG) = (old_cfg) | 0x1; \
alpha_mb(); \
} while(0); \
}
#define CIA_TYPE1_TEARDOWN(b,s,old_cfg) if((b)) { \
do { \
alpha_mb(); \
REGVAL(CIA_CSR_CFG) = (old_cfg); \
alpha_mb(); \
splx((s)); \
} while(0); \
}
/*
* From NetBSD:
* Some (apparently-common) revisions of EB164 and AlphaStation
* firmware do the Wrong thing with PCI master and target aborts,
* which are caused by accesing the configuration space of devices
* that don't exist (for example).
*
* To work around this, we clear the CIA error register's PCI
* master and target abort bits before touching PCI configuration
* space and check it afterwards. If it indicates a master or target
* abort, the device wasn't there so we return ~0
*/
#define SWIZ_CFGREAD(b, s, f, r, width, type) \
type val = ~0; \
int ipl = 0; \
u_int32_t old_cfg = 0, errbits; \
vm_offset_t off = CIA_SWIZ_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(CIA_PCI_CONF), off); \
REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT;\
alpha_mb(); \
CIA_TYPE1_SETUP(b,ipl,old_cfg); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \
} \
CIA_TYPE1_TEARDOWN(b,ipl,old_cfg); \
errbits = REGVAL(CIA_CSR_CIA_ERR); \
if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT)) \
val = ~0; \
if (errbits) { \
REGVAL(CIA_CSR_CIA_ERR) = errbits; \
alpha_mb(); \
alpha_pal_draina(); \
} \
return val;
#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) \
int ipl = 0; \
u_int32_t old_cfg = 0; \
vm_offset_t off = CIA_SWIZ_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(CIA_PCI_CONF), off); \
alpha_mb(); \
CIA_TYPE1_SETUP(b,ipl,old_cfg); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \
alpha_wmb(); \
} \
CIA_TYPE1_TEARDOWN(b,ipl,old_cfg); \
return;
static u_int8_t
cia_swiz_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
SWIZ_CFGREAD(b, s, f, r, BYTE, u_int8_t);
}
static u_int16_t
cia_swiz_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
SWIZ_CFGREAD(b, s, f, r, WORD, u_int16_t);
}
static u_int32_t
cia_swiz_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
SWIZ_CFGREAD(b, s, f, r, LONG, u_int32_t);
}
static void
cia_swiz_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
SWIZ_CFGWRITE(b, s, f, r, data, BYTE, u_int8_t);
}
static void
cia_swiz_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
SWIZ_CFGWRITE(b, s, f, r, data, WORD, u_int16_t);
}
static void
cia_swiz_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
SWIZ_CFGWRITE(b, s, f, r, data, LONG, u_int32_t);
}
vm_offset_t
cia_cvt_dense(vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (addr | CIA_PCI_DENSE);
}
vm_offset_t
cia_cvt_bwx(vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (addr |= CIA_EV56_BWMEM);
return pa & ~REG1;
}
static u_int64_t
@ -668,7 +173,7 @@ static void
cia_write_hae(u_int64_t hae)
{
u_int32_t pa = hae;
cia_swiz_set_hae_mem(&pa);
cia_swiz_set_hae_mem(0, pa);
}
static int cia_probe(device_t dev);
@ -756,7 +261,7 @@ cia_sgmap_invalidate_pyxis(void)
}
static void
cia_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa)
cia_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa)
{
u_int64_t *sgtable = arg;
int index = alpha_btop(ba - CIA_SGMAP_BASE);
@ -842,6 +347,10 @@ void
cia_init()
{
static int initted = 0;
static union space {
struct bwx_space bwx;
struct swiz_space swiz;
} io_space, mem_space;
if (initted) return;
initted = 1;
@ -870,16 +379,22 @@ cia_init()
if (alpha_implver() != ALPHA_IMPLVER_EV5
|| alpha_amask(ALPHA_AMASK_BWX)
|| !(cia_config & CNFG_BWEN))
|| !(cia_config & CNFG_BWEN)) {
swiz_init_space(&io_space.swiz, KV(CIA_PCI_SIO1));
swiz_init_space_hae(&mem_space.swiz, KV(CIA_PCI_SMEM1),
cia_swiz_set_hae_mem, 0);
chipset = cia_swiz_chipset;
else
} else {
bwx_init_space(&io_space.bwx, KV(CIA_EV56_BWIO));
bwx_init_space(&mem_space.bwx, KV(CIA_EV56_BWMEM));
chipset = cia_bwx_chipset;
}
cia_hae_mem = REGVAL(CIA_CSR_HAE_MEM);
#if 0
chipset = cia_swiz_chipset; /* XXX */
cia_ispyxis = 0;
#endif
busspace_isa_io = (struct alpha_busspace *) &io_space;
busspace_isa_mem = (struct alpha_busspace *) &mem_space;
if (platform.pci_intr_init)
platform.pci_intr_init();
@ -888,6 +403,8 @@ cia_init()
static int
cia_probe(device_t dev)
{
uintptr_t use_bwx = 1;
if (cia0)
return ENXIO;
cia0 = dev;
@ -897,7 +414,13 @@ cia_probe(device_t dev)
isa_init_intr();
cia_init_sgmap();
if (alpha_implver() != ALPHA_IMPLVER_EV5
|| alpha_amask(ALPHA_AMASK_BWX)
|| !(cia_config & CNFG_BWEN))
use_bwx = 0;
device_add_child(dev, "pcib", 0);
device_set_ivars(dev, (void *)use_bwx);
return 0;
}

View file

@ -25,6 +25,69 @@
*
* $FreeBSD$
*/
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center.
*
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/*
* Copyright (c) 1995, 1996 Carnegie-Mellon University.
* All rights reserved.
*
* Author: Chris G. Demetriou
*
* Permission to use, copy, modify and distribute this software and
* its documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
* FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*/
#include <sys/param.h>
#include <sys/systm.h>
@ -35,6 +98,16 @@
#include <machine/md_var.h>
#include <sys/rman.h>
#include <pci/pcivar.h>
#include <machine/bwx.h>
#include <machine/swiz.h>
#include <alpha/pci/ciareg.h>
#include <alpha/pci/ciavar.h>
#include "alphapci_if.h"
#include "pcib_if.h"
#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa)
static devclass_t pcib_devclass;
@ -51,13 +124,261 @@ cia_pcib_probe(device_t dev)
static int
cia_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
if (which == PCIB_IVAR_HOSE) {
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static void *
cia_pcib_cvt_dense(device_t dev, vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (void *) KV(addr | CIA_PCI_DENSE);
}
static void *
cia_pcib_cvt_bwx(device_t dev, vm_offset_t addr)
{
if ((uintptr_t) device_get_ivars(dev)) {
addr &= 0xffffffffUL;
return (void *) KV(addr | CIA_EV56_BWMEM);
} else {
return 0;
}
}
static void
cia_clear_abort(void)
{
/*
* Some (apparently-common) revisions of EB164 and AlphaStation
* firmware do the Wrong thing with PCI master and target aborts,
* which are caused by accesing the configuration space of devices
* that don't exist (for example).
*
* To work around this, we clear the CIA error register's PCI
* master and target abort bits before touching PCI configuration
* space and check it afterwards. If it indicates a master or target
* abort, the device wasn't there so we return 0xffffffff.
*/
REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT;
alpha_mb();
alpha_pal_draina();
}
static int
cia_check_abort(void)
{
u_int32_t errbits;
int ba = 0;
alpha_pal_draina();
alpha_mb();
errbits = REGVAL(CIA_CSR_CIA_ERR);
if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT))
ba = 1;
if (errbits) {
REGVAL(CIA_CSR_CIA_ERR) = errbits;
alpha_mb();
alpha_pal_draina();
}
return ba;
}
#define CIA_BWX_CFGADDR(b, s, f, r) \
KV(((b) ? CIA_EV56_BWCONF1 : CIA_EV56_BWCONF0) \
| ((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
#define BWX_CFGREAD(b, s, f, r, width, type, op) do { \
vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); \
type data; \
cia_clear_abort(); \
if (badaddr((caddr_t)va, width)) { \
cia_check_abort(); \
return ~0; \
} \
data = op(va); \
if (cia_check_abort()) \
return ~0; \
return data; \
} while (0)
#define BWX_CFGWRITE(b, s, f, r, data, width, type, op) do { \
vm_offset_t va = CIA_BWX_CFGADDR(b, s, f, r); \
cia_clear_abort(); \
if (badaddr((caddr_t)va, width)) return; \
op(va, data); \
cia_check_abort(); \
return; \
} while (0)
#define CIA_SWIZ_CFGOFF(b, s, f, r) \
(((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
/* when doing a type 1 pci configuration space access, we
* must set a bit in the CIA_CSR_CFG register & clear it
* when we're done
*/
#define CIA_TYPE1_SETUP(b,s,old_cfg) if((b)) { \
do { \
(s) = splhigh(); \
(old_cfg) = REGVAL(CIA_CSR_CFG); \
alpha_mb(); \
REGVAL(CIA_CSR_CFG) = (old_cfg) | 0x1; \
alpha_mb(); \
} while(0); \
}
#define CIA_TYPE1_TEARDOWN(b,s,old_cfg) if((b)) { \
do { \
alpha_mb(); \
REGVAL(CIA_CSR_CFG) = (old_cfg); \
alpha_mb(); \
splx((s)); \
} while(0); \
}
/*
* From NetBSD:
* Some (apparently-common) revisions of EB164 and AlphaStation
* firmware do the Wrong thing with PCI master and target aborts,
* which are caused by accesing the configuration space of devices
* that don't exist (for example).
*
* To work around this, we clear the CIA error register's PCI
* master and target abort bits before touching PCI configuration
* space and check it afterwards. If it indicates a master or target
* abort, the device wasn't there so we return ~0
*/
#define SWIZ_CFGREAD(b, s, f, r, width, type) do { \
type val = ~0; \
int ipl = 0; \
u_int32_t old_cfg = 0, errbits; \
vm_offset_t off = CIA_SWIZ_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(CIA_PCI_CONF), off); \
REGVAL(CIA_CSR_CIA_ERR) = CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT; \
alpha_mb(); \
CIA_TYPE1_SETUP(b,ipl,old_cfg); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \
} \
CIA_TYPE1_TEARDOWN(b,ipl,old_cfg); \
errbits = REGVAL(CIA_CSR_CIA_ERR); \
if (errbits & (CIA_ERR_RCVD_MAS_ABT|CIA_ERR_RCVD_TAR_ABT)) \
val = ~0; \
if (errbits) { \
REGVAL(CIA_CSR_CIA_ERR) = errbits; \
alpha_mb(); \
alpha_pal_draina(); \
} \
return val; \
} while (0)
#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) do { \
int ipl = 0; \
u_int32_t old_cfg = 0; \
vm_offset_t off = CIA_SWIZ_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(CIA_PCI_CONF), off); \
alpha_mb(); \
CIA_TYPE1_SETUP(b,ipl,old_cfg); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \
alpha_wmb(); \
} \
CIA_TYPE1_TEARDOWN(b,ipl,old_cfg); \
return; \
} while (0)
static u_int32_t
cia_pcib_swiz_read_config(int b, int s, int f, int reg, int width)
{
switch (width) {
case 1:
SWIZ_CFGREAD(b, s, f, reg, BYTE, u_int8_t);
case 2:
SWIZ_CFGREAD(b, s, f, reg, WORD, u_int16_t);
case 4:
SWIZ_CFGREAD(b, s, f, reg, LONG, u_int32_t);
}
return ~0;
}
static void
cia_pcib_swiz_write_config(int b, int s, int f, int reg,
u_int32_t val, int width)
{
switch (width) {
case 1:
SWIZ_CFGWRITE(b, s, f, reg, val, BYTE, u_int8_t);
case 2:
SWIZ_CFGWRITE(b, s, f, reg, val, WORD, u_int16_t);
case 4:
SWIZ_CFGWRITE(b, s, f, reg, val, LONG, u_int32_t);
}
}
static u_int32_t
cia_pcib_bwx_read_config(int b, int s, int f, int reg, int width)
{
switch (width) {
case 1:
BWX_CFGREAD(b, s, f, reg, 1, u_int8_t, ldbu);
case 2:
BWX_CFGREAD(b, s, f, reg, 2, u_int16_t, ldwu);
case 4:
BWX_CFGREAD(b, s, f, reg, 4, u_int32_t, ldl);
}
return ~0;
}
static void
cia_pcib_bwx_write_config(int b, int s, int f, int reg,
u_int32_t val, int width)
{
switch (width) {
case 1:
BWX_CFGWRITE(b, s, f, reg, val, 1, u_int8_t, stb);
case 2:
BWX_CFGWRITE(b, s, f, reg, val, 2, u_int16_t, stw);
case 4:
BWX_CFGWRITE(b, s, f, reg, val, 4, u_int32_t, stl);
}
}
static int
cia_pcib_maxslots(device_t dev)
{
return 31;
}
static u_int32_t
cia_pcib_read_config(device_t dev, int b, int s, int f,
int reg, int width)
{
if ((uintptr_t) device_get_ivars(dev))
return cia_pcib_bwx_read_config(b, s, f, reg, width);
else
return cia_pcib_swiz_read_config(b, s, f, reg, width);
}
static void
cia_pcib_write_config(device_t dev, int b, int s, int f,
int reg, u_int32_t val, int width)
{
if ((uintptr_t) device_get_ivars(dev))
cia_pcib_bwx_write_config(b, s, f, reg, val, width);
else
cia_pcib_swiz_write_config(b, s, f, reg, val, width);
}
static device_method_t cia_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, cia_pcib_probe),
@ -73,6 +394,15 @@ static device_method_t cia_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, alpha_platform_pci_setup_intr),
DEVMETHOD(bus_teardown_intr, alpha_platform_pci_teardown_intr),
/* alphapci interface */
DEVMETHOD(alphapci_cvt_dense, cia_pcib_cvt_dense),
DEVMETHOD(alphapci_cvt_bwx, cia_pcib_cvt_bwx),
/* pcib interface */
DEVMETHOD(pcib_maxslots, cia_pcib_maxslots),
DEVMETHOD(pcib_read_config, cia_pcib_read_config),
DEVMETHOD(pcib_write_config, cia_pcib_write_config),
{ 0, 0 }
};

View file

@ -1,80 +0,0 @@
/* $FreeBSD$ */
/*
* Copyright (c) 2000 Matthew Jacob
* 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/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <pci/pcivar.h>
static devclass_t pcib_devclass;
static int
dwlpx_pcib_probe(device_t dev)
{
device_set_desc(dev, "DWLPX PCI host bus adapter");
device_add_child(dev, "pci", device_get_unit(dev) << 4);
return (0);
}
static int
dwlpx_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
if (which == PCIB_IVAR_HOSE) {
*result = *(int*) device_get_ivars(dev);
return 0;
}
return ENOENT;
}
static device_method_t dwlpx_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, dwlpx_pcib_probe),
DEVMETHOD(device_attach, bus_generic_attach),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, dwlpx_pcib_read_ivar),
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),
{ 0, 0 }
};
static driver_t dwlpx_pcib_driver = {
"pcib", dwlpx_pcib_methods, 1
};
DRIVER_MODULE(pcib, dwlpx, dwlpx_pcib_driver, pcib_devclass, 0, 0);

View file

@ -65,242 +65,14 @@ struct irongate_softc {
#define IRONGATE_SOFTC(dev) (struct irongate_softc*) device_get_softc(dev)
static alpha_chipset_inb_t irongate_inb;
static alpha_chipset_inw_t irongate_inw;
static alpha_chipset_inl_t irongate_inl;
static alpha_chipset_outb_t irongate_outb;
static alpha_chipset_outw_t irongate_outw;
static alpha_chipset_outl_t irongate_outl;
static alpha_chipset_readb_t irongate_readb;
static alpha_chipset_readw_t irongate_readw;
static alpha_chipset_readl_t irongate_readl;
static alpha_chipset_writeb_t irongate_writeb;
static alpha_chipset_writew_t irongate_writew;
static alpha_chipset_writel_t irongate_writel;
static alpha_chipset_maxdevs_t irongate_maxdevs;
static alpha_chipset_cfgreadb_t irongate_cfgreadb;
static alpha_chipset_cfgreadw_t irongate_cfgreadw;
static alpha_chipset_cfgreadl_t irongate_cfgreadl;
static alpha_chipset_cfgwriteb_t irongate_cfgwriteb;
static alpha_chipset_cfgwritew_t irongate_cfgwritew;
static alpha_chipset_cfgwritel_t irongate_cfgwritel;
static alpha_chipset_addrcvt_t irongate_cvt_dense, irongate_cvt_bwx;
static alpha_chipset_read_hae_t irongate_read_hae;
static alpha_chipset_write_hae_t irongate_write_hae;
static alpha_chipset_t irongate_chipset = {
irongate_inb,
irongate_inw,
irongate_inl,
irongate_outb,
irongate_outw,
irongate_outl,
irongate_readb,
irongate_readw,
irongate_readl,
irongate_writeb,
irongate_writew,
irongate_writel,
irongate_maxdevs,
irongate_cfgreadb,
irongate_cfgreadw,
irongate_cfgreadl,
irongate_cfgwriteb,
irongate_cfgwritew,
irongate_cfgwritel,
irongate_cvt_dense,
irongate_cvt_bwx,
irongate_read_hae,
irongate_write_hae,
};
static u_int8_t
irongate_inb(u_int32_t port)
{
alpha_mb();
return ldbu(KV(IRONGATE_IO + port));
}
static u_int16_t
irongate_inw(u_int32_t port)
{
alpha_mb();
return ldwu(KV(IRONGATE_IO + port));
}
static u_int32_t
irongate_inl(u_int32_t port)
{
alpha_mb();
return ldl(KV(IRONGATE_IO + port));
}
static void
irongate_outb(u_int32_t port, u_int8_t data)
{
stb(KV(IRONGATE_IO + port), data);
alpha_mb();
}
static void
irongate_outw(u_int32_t port, u_int16_t data)
{
stw(KV(IRONGATE_IO + port), data);
alpha_mb();
}
static void
irongate_outl(u_int32_t port, u_int32_t data)
{
stl(KV(IRONGATE_IO + port), data);
alpha_mb();
}
static u_int8_t
irongate_readb(u_int32_t pa)
{
alpha_mb();
return ldbu(KV(IRONGATE_MEM + pa));
}
static u_int16_t
irongate_readw(u_int32_t pa)
{
alpha_mb();
return ldwu(KV(IRONGATE_MEM + pa));
}
static u_int32_t
irongate_readl(u_int32_t pa)
{
alpha_mb();
return ldl(KV(IRONGATE_MEM + pa));
}
static void
irongate_writeb(u_int32_t pa, u_int8_t data)
{
stb(KV(IRONGATE_MEM + pa), data);
alpha_mb();
}
static void
irongate_writew(u_int32_t pa, u_int16_t data)
{
stw(KV(IRONGATE_MEM + pa), data);
alpha_mb();
}
static void
irongate_writel(u_int32_t pa, u_int32_t data)
{
stl(KV(IRONGATE_MEM + pa), data);
alpha_mb();
}
static int
irongate_maxdevs(u_int b)
{
return 12; /* XXX */
}
static void
irongate_clear_abort(void)
{
alpha_mb();
alpha_pal_draina();
}
static int
irongate_check_abort(void)
{
alpha_pal_draina();
alpha_mb();
return 0;
}
#define IRONGATE_CFGADDR(b, s, f, r) \
KV(IRONGATE_CONF | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
#define CFGREAD(h, b, s, f, r, op, width, type) \
vm_offset_t va; \
type data; \
va = IRONGATE_CFGADDR(b, s, f, r); \
irongate_clear_abort(); \
if (badaddr((caddr_t)va, width)) { \
irongate_check_abort(); \
return ~0; \
} \
data = ##op##(va); \
if (irongate_check_abort()) \
return ~0; \
return data;
#define CFWRITE(h, b, s, f, r, data, op, width) \
vm_offset_t va; \
va = IRONGATE_CFGADDR(b, s, f, r); \
irongate_clear_abort(); \
if (badaddr((caddr_t)va, width)) \
return; \
##op##(va, data); \
irongate_check_abort();
static u_int8_t
irongate_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
CFGREAD(h, b, s, f, r, ldbu, 1, u_int8_t)
}
static u_int16_t
irongate_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
CFGREAD(h, b, s, f, r, ldwu, 2, u_int16_t)
}
static u_int32_t
irongate_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
CFGREAD(h, b, s, f, r, ldl, 4, u_int32_t)
}
static void
irongate_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
CFWRITE(h, b, s, f, r, data, stb, 1)
}
static void
irongate_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
CFWRITE(h, b, s, f, r, data, stw, 2)
}
static void
irongate_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
CFWRITE(h, b, s, f, r, data, stl, 4)
}
vm_offset_t
irongate_cvt_bwx(vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (KV(addr | IRONGATE_MEM));
}
vm_offset_t
irongate_cvt_dense(vm_offset_t addr)
{
return irongate_cvt_bwx(addr);
}
/*
* There doesn't appear to be an hae on this platform
*/
@ -347,6 +119,7 @@ void
irongate_init()
{
static int initted = 0;
struct bwx_space io_space, mem_space;
if (initted) return;
initted = 1;
@ -354,6 +127,12 @@ irongate_init()
chipset = irongate_chipset;
alpha_XXX_dmamap_or = 0UL;
bwx_init_space(&io_space, KV(IRONGATE_IO));
bwx_init_space(&mem_space, KV(IRONGATE_MEM));
busspace_isa_io = (kobj_t) &io_space;
busspace_isa_mem = (kobj_t) &mem_space;
if (platform.pci_intr_init)
platform.pci_intr_init();
}
@ -377,10 +156,6 @@ irongate_probe(device_t dev)
static int
irongate_attach(device_t dev)
{
u_int8_t value;
pcicfgregs southbridge;
irongate_init();
if (!platform.iointr) /* XXX */
@ -395,22 +170,6 @@ irongate_attach(device_t dev)
/* no s/g support in this chipset, must use bounce-buffers */
chipset.sgmap = NULL;
/*
* XXX -- The SRM console doesn't properly initialize
* the AcerLabs M1533C southbridge. We must turn off 32-bit
* DMA support.
*/
southbridge.hose = 0;
southbridge.bus = 0;
southbridge.slot = 7;
southbridge.func = 0;
if ((0x153310b9 == pci_cfgread(&southbridge, PCIR_DEVVENDOR, 4))) {
value = (u_int8_t)pci_cfgread(&southbridge, 0x42, 1);
value &= ~0x40;
pci_cfgwrite(&southbridge, 0x42, 0, 1);
}
bus_generic_attach(dev);
return 0;

View file

@ -34,22 +34,39 @@
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/md_var.h>
#include <machine/bwx.h>
#include <sys/rman.h>
#include <pci/pcivar.h>
#include <pci/pcireg.h>
#include <alpha/pci/irongatereg.h>
#include <alpha/pci/irongatevar.h>
#include "alphapci_if.h"
#include "pcib_if.h"
#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa)
static devclass_t pcib_devclass;
static int
irongate_pcib_probe(device_t dev)
{
device_set_desc(dev, "AMD 751 PCI host bus adapter");
device_add_child(dev, "pci", -1);
device_add_child(dev, "pci", 0);
/*
* XXX -- The SRM console doesn't properly initialize
* the AcerLabs M1533C southbridge. We must turn off 32-bit
* DMA support.
*/
if ((0x153310b9 == PCIB_READ_CONFIG(dev, 0, 7, 0,
PCIR_DEVVENDOR, 4))) {
u_int8_t value = PCIB_READ_CONFIG(dev, 0, 7, 0, 0x42, 1);
value &= ~0x40;
PCIB_WRITE_CONFIG(dev, 0, 7, 0, 0x42, 0, 1);
}
return 0;
}
@ -57,13 +74,107 @@ irongate_pcib_probe(device_t dev)
static int
irongate_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
if (which == PCIB_IVAR_HOSE) {
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static void *
irongate_pcib_cvt_dense(device_t dev, vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (void *) KV(addr | IRONGATE_MEM);
}
static void *
irongate_pcib_cvt_bwx(device_t dev, vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (void *) KV(addr | IRONGATE_MEM);
}
static int
irongate_pcib_maxslots(device_t dev)
{
return 31;
}
static void
irongate_clear_abort(void)
{
alpha_mb();
alpha_pal_draina();
}
static int
irongate_check_abort(void)
{
alpha_pal_draina();
alpha_mb();
return 0;
}
#define IRONGATE_CFGADDR(b, s, f, r) \
KV(IRONGATE_CONF | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
#define CFGREAD(b, s, f, r, width, type, op) do { \
vm_offset_t va; \
type data; \
va = IRONGATE_CFGADDR(b, s, f, r); \
irongate_clear_abort(); \
if (badaddr((caddr_t)va, width)) { \
irongate_check_abort(); \
return ~0; \
} \
data = ##op##(va); \
if (irongate_check_abort()) \
return ~0; \
return data; \
} while (0)
#define CFGWRITE(b, s, f, r, data, width, op) do { \
vm_offset_t va; \
va = IRONGATE_CFGADDR(b, s, f, r); \
irongate_clear_abort(); \
if (badaddr((caddr_t)va, width)) \
return; \
##op##(va, data); \
irongate_check_abort(); \
} while (0)
static u_int32_t
irongate_pcib_read_config(device_t dev, int b, int s, int f,
int reg, int width)
{
switch (width) {
case 1:
CFGREAD(b, s, f, reg, 1, u_int8_t, ldbu);
case 2:
CFGREAD(b, s, f, reg, 2, u_int16_t, ldwu);
case 4:
CFGREAD(b, s, f, reg, 4, u_int32_t, ldl);
}
return ~0;
}
static void
irongate_pcib_write_config(device_t dev, int b, int s, int f,
int reg, u_int32_t val, int width)
{
switch (width) {
case 1:
CFGWRITE(b, s, f, reg, val, 1, stb);
case 2:
CFGWRITE(b, s, f, reg, val, 2, stw);
case 4:
CFGWRITE(b, s, f, reg, val, 4, stl);
}
}
static device_method_t irongate_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, irongate_pcib_probe),
@ -79,17 +190,23 @@ static device_method_t irongate_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* alphapci interface */
DEVMETHOD(alphapci_cvt_dense, irongate_pcib_cvt_dense),
DEVMETHOD(alphapci_cvt_bwx, irongate_pcib_cvt_bwx),
/* pcib interface */
DEVMETHOD(pcib_maxslots, irongate_pcib_maxslots),
DEVMETHOD(pcib_read_config, irongate_pcib_read_config),
DEVMETHOD(pcib_write_config, irongate_pcib_write_config),
{ 0, 0 }
};
static driver_t irongate_pcib_driver = {
"pcib",
irongate_pcib_methods,
1,
};
DRIVER_MODULE(pcib, irongate, irongate_pcib_driver, pcib_devclass, 0, 0);

View file

@ -59,97 +59,14 @@ struct lca_softc {
#define LCA_SOFTC(dev) (struct lca_softc*) device_get_softc(dev)
static alpha_chipset_inb_t lca_inb;
static alpha_chipset_inw_t lca_inw;
static alpha_chipset_inl_t lca_inl;
static alpha_chipset_outb_t lca_outb;
static alpha_chipset_outw_t lca_outw;
static alpha_chipset_outl_t lca_outl;
static alpha_chipset_readb_t lca_readb;
static alpha_chipset_readw_t lca_readw;
static alpha_chipset_readl_t lca_readl;
static alpha_chipset_writeb_t lca_writeb;
static alpha_chipset_writew_t lca_writew;
static alpha_chipset_writel_t lca_writel;
static alpha_chipset_maxdevs_t lca_maxdevs;
static alpha_chipset_cfgreadb_t lca_cfgreadb;
static alpha_chipset_cfgreadw_t lca_cfgreadw;
static alpha_chipset_cfgreadl_t lca_cfgreadl;
static alpha_chipset_cfgwriteb_t lca_cfgwriteb;
static alpha_chipset_cfgwritew_t lca_cfgwritew;
static alpha_chipset_cfgwritel_t lca_cfgwritel;
static alpha_chipset_addrcvt_t lca_cvt_dense;
static alpha_chipset_read_hae_t lca_read_hae;
static alpha_chipset_write_hae_t lca_write_hae;
static alpha_chipset_t lca_chipset = {
lca_inb,
lca_inw,
lca_inl,
lca_outb,
lca_outw,
lca_outl,
lca_readb,
lca_readw,
lca_readl,
lca_writeb,
lca_writew,
lca_writel,
lca_maxdevs,
lca_cfgreadb,
lca_cfgreadw,
lca_cfgreadl,
lca_cfgwriteb,
lca_cfgwritew,
lca_cfgwritel,
lca_cvt_dense,
NULL,
lca_read_hae,
lca_write_hae,
};
static u_int8_t
lca_inb(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_BYTE(KV(LCA_PCI_SIO), port);
}
static u_int16_t
lca_inw(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_WORD(KV(LCA_PCI_SIO), port);
}
static u_int32_t
lca_inl(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_LONG(KV(LCA_PCI_SIO), port);
}
static void
lca_outb(u_int32_t port, u_int8_t data)
{
SPARSE_WRITE_BYTE(KV(LCA_PCI_SIO), port, data);
alpha_wmb();
}
static void
lca_outw(u_int32_t port, u_int16_t data)
{
SPARSE_WRITE_WORD(KV(LCA_PCI_SIO), port, data);
alpha_wmb();
}
static void
lca_outl(u_int32_t port, u_int32_t data)
{
SPARSE_WRITE_LONG(KV(LCA_PCI_SIO), port, data);
alpha_wmb();
}
/*
* The LCA HAE is write-only. According to NetBSD, this is where it starts.
*/
@ -161,14 +78,14 @@ static u_int32_t lca_hae_mem = 0x80000000;
*/
#define REG1 (1UL << 24)
static __inline void
lca_set_hae_mem(u_int32_t *pa)
static u_int32_t
lca_set_hae_mem(void *arg, u_int32_t pa)
{
int s;
u_int32_t msb;
if(*pa >= REG1){
msb = *pa & 0xf8000000;
*pa -= msb;
if(pa >= REG1){
msb = pa & 0xf8000000;
pa -= msb;
s = splhigh();
if (msb != lca_hae_mem) {
lca_hae_mem = msb;
@ -178,152 +95,7 @@ lca_set_hae_mem(u_int32_t *pa)
}
splx(s);
}
}
static u_int8_t
lca_readb(u_int32_t pa)
{
alpha_mb();
lca_set_hae_mem(&pa);
return SPARSE_READ_BYTE(KV(LCA_PCI_SPARSE), pa);
}
static u_int16_t
lca_readw(u_int32_t pa)
{
alpha_mb();
lca_set_hae_mem(&pa);
return SPARSE_READ_WORD(KV(LCA_PCI_SPARSE), pa);
}
static u_int32_t
lca_readl(u_int32_t pa)
{
alpha_mb();
lca_set_hae_mem(&pa);
return SPARSE_READ_LONG(KV(LCA_PCI_SPARSE), pa);
}
static void
lca_writeb(u_int32_t pa, u_int8_t data)
{
lca_set_hae_mem(&pa);
SPARSE_WRITE_BYTE(KV(LCA_PCI_SPARSE), pa, data);
alpha_wmb();
}
static void
lca_writew(u_int32_t pa, u_int16_t data)
{
lca_set_hae_mem(&pa);
SPARSE_WRITE_WORD(KV(LCA_PCI_SPARSE), pa, data);
alpha_wmb();
}
static void
lca_writel(u_int32_t pa, u_int32_t data)
{
lca_set_hae_mem(&pa);
SPARSE_WRITE_LONG(KV(LCA_PCI_SPARSE), pa, data);
alpha_wmb();
}
static int
lca_maxdevs(u_int b)
{
return 12; /* XXX */
}
#define LCA_CFGOFF(b, s, f, r) \
((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) \
: ((1 << ((s) + 11)) | ((f) << 8) | (r)))
#define LCA_TYPE1_SETUP(b,s) if ((b)) { \
do { \
(s) = splhigh(); \
alpha_mb(); \
REGVAL(LCA_IOC_CONF) = 1; \
alpha_mb(); \
} while(0); \
}
#define LCA_TYPE1_TEARDOWN(b,s) if ((b)) { \
do { \
alpha_mb(); \
REGVAL(LCA_IOC_CONF) = 0; \
alpha_mb(); \
splx((s)); \
} while(0); \
}
#define CFGREAD(b, s, f, r, width, type) \
type val = ~0; \
int ipl = 0; \
vm_offset_t off = LCA_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(LCA_PCI_CONF), off); \
alpha_mb(); \
LCA_TYPE1_SETUP(b,ipl); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \
} \
LCA_TYPE1_TEARDOWN(b,ipl); \
return val
#define CFGWRITE(b, s, f, r, data, width, type) \
int ipl = 0; \
vm_offset_t off = LCA_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(LCA_PCI_CONF), off); \
alpha_mb(); \
LCA_TYPE1_SETUP(b,ipl); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \
alpha_wmb(); \
} \
LCA_TYPE1_TEARDOWN(b,ipl); \
return
static u_int8_t
lca_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
CFGREAD(b, s, f, r, BYTE, u_int8_t);
}
static u_int16_t
lca_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
CFGREAD(b, s, f, r, WORD, u_int16_t);
}
static u_int32_t
lca_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
CFGREAD(b, s, f, r, LONG, u_int32_t);
}
static void
lca_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
CFGWRITE(b, s, f, r, data, BYTE, u_int8_t);
}
static void
lca_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
CFGWRITE(b, s, f, r, data, WORD, u_int16_t);
}
static void
lca_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
CFGWRITE(b, s, f, r, data, LONG, u_int16_t);
}
static vm_offset_t
lca_cvt_dense(vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (addr | LCA_PCI_DENSE);
return pa;
}
static u_int64_t
@ -336,7 +108,7 @@ static void
lca_write_hae(u_int64_t hae)
{
u_int32_t pa = hae;
lca_set_hae_mem(&pa);
lca_set_hae_mem(0, pa);
}
static int lca_probe(device_t dev);
@ -382,7 +154,7 @@ lca_sgmap_invalidate(void)
}
static void
lca_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa)
lca_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa)
{
u_int64_t *sgtable = arg;
int index = alpha_btop(ba - LCA_SGMAP_BASE);
@ -435,10 +207,18 @@ void
lca_init()
{
static int initted = 0;
static struct swiz_space io_space, mem_space;
if (initted) return;
initted = 1;
swiz_init_space(&io_space, KV(LCA_PCI_SIO));
swiz_init_space_hae(&mem_space, KV(LCA_PCI_SPARSE),
lca_set_hae_mem, 0);
busspace_isa_io = (struct alpha_busspace *) &io_space;
busspace_isa_mem = (struct alpha_busspace *) &mem_space;
/* Type 0 PCI conf access. */
REGVAL64(LCA_IOC_CONF) = 0;

View file

@ -34,6 +34,15 @@
#include <machine/bus.h>
#include <sys/rman.h>
#include <pci/pcivar.h>
#include <machine/swiz.h>
#include <alpha/pci/lcareg.h>
#include <alpha/pci/lcavar.h>
#include "alphapci_if.h"
#include "pcib_if.h"
#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa)
static devclass_t pcib_devclass;
@ -50,13 +59,105 @@ lca_pcib_probe(device_t dev)
static int
lca_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
if (which == PCIB_IVAR_HOSE) {
if (which == PCIB_IVAR_BUS) {
*result = 0;
return 0;
}
return ENOENT;
}
static void *
lca_pcib_cvt_dense(device_t dev, vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (void *) KV(addr | LCA_PCI_DENSE);
}
static int
lca_pcib_maxslots(device_t dev)
{
return 31;
}
#define LCA_CFGOFF(b, s, f, r) \
((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) \
: ((1 << ((s) + 11)) | ((f) << 8) | (r)))
#define LCA_TYPE1_SETUP(b,s) if ((b)) { \
do { \
(s) = splhigh(); \
alpha_mb(); \
REGVAL(LCA_IOC_CONF) = 1; \
alpha_mb(); \
} while(0); \
}
#define LCA_TYPE1_TEARDOWN(b,s) if ((b)) { \
do { \
alpha_mb(); \
REGVAL(LCA_IOC_CONF) = 0; \
alpha_mb(); \
splx((s)); \
} while(0); \
}
#define CFGREAD(b, s, f, r, width, type) do { \
type val = ~0; \
int ipl = 0; \
vm_offset_t off = LCA_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(LCA_PCI_CONF), off); \
alpha_mb(); \
LCA_TYPE1_SETUP(b,ipl); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \
} \
LCA_TYPE1_TEARDOWN(b,ipl); \
return val; \
} while (0)
#define CFGWRITE(b, s, f, r, data, width, type) do { \
int ipl = 0; \
vm_offset_t off = LCA_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(LCA_PCI_CONF), off); \
alpha_mb(); \
LCA_TYPE1_SETUP(b,ipl); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \
alpha_wmb(); \
} \
LCA_TYPE1_TEARDOWN(b,ipl); \
return; \
} while (0)
u_int32_t
lca_pcib_read_config(device_t dev, int b, int s, int f,
int reg, int width)
{
switch (width) {
case 1:
CFGREAD(b, s, f, reg, BYTE, u_int8_t);
case 2:
CFGREAD(b, s, f, reg, WORD, u_int16_t);
case 4:
CFGREAD(b, s, f, reg, LONG, u_int32_t);
}
return ~0;
}
static void
lca_pcib_write_config(device_t dev, int b, int s, int f,
int reg, u_int32_t val, int width)
{
switch (width) {
case 1:
CFGWRITE(b, s, f, reg, val, BYTE, u_int8_t);
case 2:
CFGWRITE(b, s, f, reg, val, WORD, u_int16_t);
case 4:
CFGWRITE(b, s, f, reg, val, LONG, u_int32_t);
}
}
static device_method_t lca_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, lca_pcib_probe),
@ -72,6 +173,14 @@ static device_method_t lca_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* alphapci interface */
DEVMETHOD(alphapci_cvt_dense, lca_pcib_cvt_dense),
/* pcib interface */
DEVMETHOD(pcib_maxslots, lca_pcib_maxslots),
DEVMETHOD(pcib_read_config, lca_pcib_read_config),
DEVMETHOD(pcib_write_config, lca_pcib_write_config),
{ 0, 0 }
};

View file

@ -26,4 +26,8 @@
* $FreeBSD$
*/
struct device;
extern void lca_init(void);
u_int32_t lca_pcib_read_config(struct device *dev, int b, int s, int f,
int reg, int width);

View file

@ -1,80 +0,0 @@
/* $FreeBSD$ */
/*
* Copyright (c) 2000 Matthew Jacob
* 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/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <pci/pcivar.h>
static devclass_t pcib_devclass;
static int
mcpcia_pcib_probe(device_t dev)
{
device_set_desc(dev, "MCPCIA PCI host bus adapter");
device_add_child(dev, "pci", device_get_unit(dev) << 4);
return (0);
}
static int
mcpcia_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
if (which == PCIB_IVAR_HOSE) {
*result = *(int*) device_get_ivars(dev);
return 0;
}
return ENOENT;
}
static device_method_t mcpcia_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, mcpcia_pcib_probe),
DEVMETHOD(device_attach, bus_generic_attach),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, mcpcia_pcib_read_ivar),
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),
{ 0, 0 }
};
static driver_t mcpcia_pcib_driver = {
"pcib", mcpcia_pcib_methods, 1
};
DRIVER_MODULE(pcib, mcpcia, mcpcia_pcib_driver, pcib_devclass, 0, 0);

View file

@ -45,11 +45,15 @@
#include <alpha/pci/pcibus.h>
#include <alpha/isa/isavar.h>
#include "alphapci_if.h"
#include "isa.h"
#define ISA_IRQ_OFFSET 0xe0
#define ISA_IRQ_LEN 0x10
struct alpha_busspace *busspace_isa_io;
struct alpha_busspace *busspace_isa_mem;
char chipset_type[10];
int chipset_bwx = 0;
long chipset_ports = 0;
@ -71,73 +75,6 @@ SYSCTL_LONG(_hw_chipset, OID_AUTO, dense, CTLFLAG_RD, &chipset_dense, 0,
SYSCTL_LONG(_hw_chipset, OID_AUTO, hae_mask, CTLFLAG_RD, &chipset_hae_mask, 0,
"PCI chipset mask for HAE register");
#ifdef notyet
/* return max number of devices on the bus */
int
pci_maxdevs(pcicfgregs *cfg)
{
return chipset.maxdevs(cfg->bus);
}
#endif
/* read configuration space register */
int
pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
{
switch (bytes) {
case 1:
return chipset.cfgreadb(cfg->hose, cfg->bus,
cfg->slot, cfg->func, reg);
case 2:
return chipset.cfgreadw(cfg->hose, cfg->bus,
cfg->slot, cfg->func, reg);
case 4:
return chipset.cfgreadl(cfg->hose, cfg->bus,
cfg->slot, cfg->func, reg);
}
return ~0;
}
/* write configuration space register */
void
pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
{
switch (bytes) {
case 1:
return chipset.cfgwriteb(cfg->hose, cfg->bus,
cfg->slot, cfg->func, reg, data);
case 2:
return chipset.cfgwritew(cfg->hose, cfg->bus,
cfg->slot, cfg->func, reg, data);
case 4:
return chipset.cfgwritel(cfg->hose, cfg->bus,
cfg->slot, cfg->func, reg, data);
}
}
vm_offset_t
pci_cvt_to_dense(vm_offset_t sparse)
{
if(chipset.cvt_to_dense)
return ALPHA_PHYS_TO_K0SEG(chipset.cvt_to_dense(sparse));
else
return NULL;
}
vm_offset_t
pci_cvt_to_bwx(vm_offset_t sparse)
{
if(chipset.cvt_to_bwx)
return ALPHA_PHYS_TO_K0SEG(chipset.cvt_to_bwx(sparse));
else
return NULL;
}
void
alpha_platform_assign_pciintr(pcicfgregs *cfg)
{
@ -274,6 +211,7 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
{
struct rman *rm;
struct resource *rv;
void *va;
switch (type) {
case SYS_RES_IRQ:
@ -290,11 +228,8 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
break;
case SYS_RES_IOPORT:
rm = &port_rman;
break;
case SYS_RES_MEMORY:
rm = &mem_rman;
rm = ALPHAPCI_GET_RMAN(bus, type);
break;
default:
@ -305,21 +240,19 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
if (rv == 0)
return 0;
rman_set_bustag(rv, ALPHAPCI_GET_BUSTAG(bus, type));
rman_set_bushandle(rv, rv->r_start);
switch (type) {
case SYS_RES_MEMORY:
rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM);
rman_set_bushandle(rv, rv->r_start);
va = 0;
if (flags & PCI_RF_DENSE)
rman_set_virtual(rv, (void *) pci_cvt_to_dense(rv->r_start));
va = ALPHAPCI_CVT_DENSE(bus, rv->r_start);
else if (flags & PCI_RF_BWX)
rman_set_virtual(rv, (void *) pci_cvt_to_bwx(rv->r_start));
va = ALPHAPCI_CVT_BWX(bus, rv->r_start);
else
rman_set_virtual(rv, (void *) rv->r_start); /* maybe NULL? */
break;
va = (void *) rv->r_start; /* maybe NULL? */
rman_set_virtual(rv, va);
case SYS_RES_IOPORT:
rman_set_bustag(rv, ALPHA_BUS_SPACE_IO);
rman_set_bushandle(rv, rv->r_start);
break;
}
@ -347,54 +280,32 @@ pci_release_resource(device_t bus, device_t child, int type, int rid,
return (rman_release_resource(r));
}
void
memcpy_fromio(void *d, u_int32_t s, size_t size)
struct alpha_busspace *
pci_get_bustag(device_t dev, int type)
{
char *cp = d;
switch (type) {
case SYS_RES_IOPORT:
return busspace_isa_io;
while (size--)
*cp++ = readb(s++);
case SYS_RES_MEMORY:
return busspace_isa_mem;
}
return 0;
}
void
memcpy_toio(u_int32_t d, void *s, size_t size)
struct rman *
pci_get_rman(device_t dev, int type)
{
char *cp = s;
switch (type) {
case SYS_RES_IOPORT:
return &port_rman;
while (size--)
writeb(d++, *cp++);
}
case SYS_RES_MEMORY:
return &mem_rman;
}
void
memcpy_io(u_int32_t d, u_int32_t s, size_t size)
{
while (size--)
writeb(d++, readb(s++));
}
void
memset_io(u_int32_t d, int val, size_t size)
{
while (size--)
writeb(d++, val);
}
void
memsetw(void *d, int val, size_t size)
{
u_int16_t *sp = d;
while (size--)
*sp++ = val;
}
void
memsetw_io(u_int32_t d, int val, size_t size)
{
while (size--) {
writew(d, val);
d += sizeof(u_int16_t);
}
return 0;
}
#include "opt_ddb.h"

View file

@ -37,3 +37,5 @@ int pci_deactivate_resource(device_t bus, device_t child, int type, int rid,
struct resource *r);
int pci_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *r);
struct alpha_busspace *pci_get_bustag(device_t dev, int type);
struct rman *pci_get_rman(device_t dev, int type);

154
sys/alpha/pci/swiz.c Normal file
View file

@ -0,0 +1,154 @@
/*-
* Copyright (c) 2000 Doug Rabson
* 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$
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/kobj.h>
#include <machine/bus.h>
#include <machine/swiz.h>
static u_int8_t
swiz_read_1(struct alpha_busspace *space, size_t offset)
{
struct swiz_space *swiz = (struct swiz_space *) space;
alpha_mb();
if (swiz->sethae)
offset = swiz->sethae(swiz->arg, offset);
return SPARSE_READ_BYTE(swiz->base, offset);
}
static u_int16_t
swiz_read_2(struct alpha_busspace *space, size_t offset)
{
struct swiz_space *swiz = (struct swiz_space *) space;
alpha_mb();
if (swiz->sethae)
offset = swiz->sethae(swiz->arg, offset);
return SPARSE_READ_WORD(swiz->base, offset);
}
static u_int32_t
swiz_read_4(struct alpha_busspace *space, size_t offset)
{
struct swiz_space *swiz = (struct swiz_space *) space;
alpha_mb();
if (swiz->sethae)
offset = swiz->sethae(swiz->arg, offset);
return SPARSE_READ_LONG(swiz->base, offset);
}
static void
swiz_write_1(struct alpha_busspace *space, size_t offset, u_int8_t data)
{
struct swiz_space *swiz = (struct swiz_space *) space;
if (swiz->sethae)
offset = swiz->sethae(swiz->arg, offset);
SPARSE_WRITE_BYTE(swiz->base, offset, data);
alpha_mb();
}
static void
swiz_write_2(struct alpha_busspace *space, size_t offset, u_int16_t data)
{
struct swiz_space *swiz = (struct swiz_space *) space;
if (swiz->sethae)
offset = swiz->sethae(swiz->arg, offset);
SPARSE_WRITE_WORD(swiz->base, offset, data);
alpha_mb();
}
static void
swiz_write_4(struct alpha_busspace *space, size_t offset, u_int32_t data)
{
struct swiz_space *swiz = (struct swiz_space *) space;
if (swiz->sethae)
offset = swiz->sethae(swiz->arg, offset);
SPARSE_WRITE_LONG(swiz->base, offset, data);
alpha_mb();
}
static struct alpha_busspace_ops swiz_space_ops = {
swiz_read_1,
swiz_read_2,
swiz_read_4,
busspace_generic_read_multi_1,
busspace_generic_read_multi_2,
busspace_generic_read_multi_4,
busspace_generic_read_region_1,
busspace_generic_read_region_2,
busspace_generic_read_region_4,
swiz_write_1,
swiz_write_2,
swiz_write_4,
busspace_generic_write_multi_1,
busspace_generic_write_multi_2,
busspace_generic_write_multi_4,
busspace_generic_write_region_1,
busspace_generic_write_region_2,
busspace_generic_write_region_4,
busspace_generic_set_multi_1,
busspace_generic_set_multi_2,
busspace_generic_set_multi_4,
busspace_generic_set_region_1,
busspace_generic_set_region_2,
busspace_generic_set_region_4,
busspace_generic_copy_region_1,
busspace_generic_copy_region_2,
busspace_generic_copy_region_4,
busspace_generic_barrier,
};
void
swiz_init_space(struct swiz_space *swiz, u_int64_t base)
{
swiz->ops = &swiz_space_ops;
swiz->base = base;
swiz->sethae = 0;
swiz->arg = 0;
}
void swiz_init_space_hae(struct swiz_space *swiz, u_int64_t base,
swiz_sethae_fn sethae, void *arg)
{
swiz->ops = &swiz_space_ops;
swiz->base = base;
swiz->sethae = sethae;
swiz->arg = arg;
}

View file

@ -66,110 +66,27 @@ struct t2_softc {
#define T2_SOFTC(dev) (struct t2_softc*) device_get_softc(dev)
static alpha_chipset_inb_t t2_inb;
static alpha_chipset_inw_t t2_inw;
static alpha_chipset_inl_t t2_inl;
static alpha_chipset_outb_t t2_outb;
static alpha_chipset_outw_t t2_outw;
static alpha_chipset_outl_t t2_outl;
static alpha_chipset_readb_t t2_readb;
static alpha_chipset_readw_t t2_readw;
static alpha_chipset_readl_t t2_readl;
static alpha_chipset_writeb_t t2_writeb;
static alpha_chipset_writew_t t2_writew;
static alpha_chipset_writel_t t2_writel;
static alpha_chipset_maxdevs_t t2_maxdevs;
static alpha_chipset_cfgreadb_t t2_cfgreadb;
static alpha_chipset_cfgreadw_t t2_cfgreadw;
static alpha_chipset_cfgreadl_t t2_cfgreadl;
static alpha_chipset_cfgwriteb_t t2_cfgwriteb;
static alpha_chipset_cfgwritew_t t2_cfgwritew;
static alpha_chipset_cfgwritel_t t2_cfgwritel;
static alpha_chipset_addrcvt_t t2_cvt_dense;
static alpha_chipset_read_hae_t t2_read_hae;
static alpha_chipset_write_hae_t t2_write_hae;
static alpha_chipset_t t2_chipset = {
t2_inb,
t2_inw,
t2_inl,
t2_outb,
t2_outw,
t2_outl,
t2_readb,
t2_readw,
t2_readl,
t2_writeb,
t2_writew,
t2_writel,
t2_maxdevs,
t2_cfgreadb,
t2_cfgreadw,
t2_cfgreadl,
t2_cfgwriteb,
t2_cfgwritew,
t2_cfgwritel,
t2_cvt_dense,
NULL,
t2_read_hae,
t2_write_hae,
};
static u_int8_t
t2_inb(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_BYTE(KV(T2_PCI_SIO), port);
}
static u_int16_t
t2_inw(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_WORD(KV(T2_PCI_SIO), port);
}
static u_int32_t
t2_inl(u_int32_t port)
{
alpha_mb();
return SPARSE_READ_LONG(KV(T2_PCI_SIO), port);
}
static void
t2_outb(u_int32_t port, u_int8_t data)
{
SPARSE_WRITE_BYTE(KV(T2_PCI_SIO), port, data);
alpha_wmb();
}
static void
t2_outw(u_int32_t port, u_int16_t data)
{
SPARSE_WRITE_WORD(KV(T2_PCI_SIO), port, data);
alpha_wmb();
}
static void
t2_outl(u_int32_t port, u_int32_t data)
{
SPARSE_WRITE_LONG(KV(T2_PCI_SIO), port, data);
alpha_wmb();
}
static u_int32_t t2_hae_mem;
#define REG1 (1UL << 24)
static __inline void
t2_set_hae_mem(u_int32_t *pa)
static u_int32_t
t2_set_hae_mem(void *arg, u_int32_t pa)
{
int s;
u_int32_t msb;
if(*pa >= REG1){
msb = *pa & 0xf8000000;
*pa -= msb;
if(pa >= REG1){
msb = pa & 0xf8000000;
pa -= msb;
msb >>= 27; /* t2 puts high bits in the bottom of the register */
s = splhigh();
if (msb != t2_hae_mem) {
@ -180,72 +97,7 @@ t2_set_hae_mem(u_int32_t *pa)
}
splx(s);
}
}
static u_int8_t
t2_readb(u_int32_t pa)
{
alpha_mb();
t2_set_hae_mem(&pa);
return SPARSE_READ_BYTE(KV(T2_PCI_SPARSE), pa);
}
static u_int16_t
t2_readw(u_int32_t pa)
{
alpha_mb();
t2_set_hae_mem(&pa);
return SPARSE_READ_WORD(KV(T2_PCI_SPARSE), pa);
}
static u_int32_t
t2_readl(u_int32_t pa)
{
alpha_mb();
t2_set_hae_mem(&pa);
return SPARSE_READ_LONG(KV(T2_PCI_SPARSE), pa);
}
static void
t2_writeb(u_int32_t pa, u_int8_t data)
{
t2_set_hae_mem(&pa);
SPARSE_WRITE_BYTE(KV(T2_PCI_SPARSE), pa, data);
alpha_wmb();
}
static void
t2_writew(u_int32_t pa, u_int16_t data)
{
t2_set_hae_mem(&pa);
SPARSE_WRITE_WORD(KV(T2_PCI_SPARSE), pa, data);
alpha_wmb();
}
static void
t2_writel(u_int32_t pa, u_int32_t data)
{
t2_set_hae_mem(&pa);
SPARSE_WRITE_LONG(KV(T2_PCI_SPARSE), pa, data);
alpha_wmb();
}
static int
t2_maxdevs(u_int b)
{
return 12; /* XXX */
}
/* XXX config space access? */
static vm_offset_t
t2_cvt_dense(vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (addr | T2_PCI_DENSE);
return pa;
}
static u_int64_t
@ -258,94 +110,7 @@ static void
t2_write_hae(u_int64_t hae)
{
u_int32_t pa = hae;
t2_set_hae_mem(&pa);
}
#define T2_CFGOFF(b, s, f, r) \
((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) \
: ((1 << ((s) + 11)) | ((f) << 8) | (r)))
#define T2_TYPE1_SETUP(b,s,old_hae3) if((b)) { \
do { \
(s) = splhigh(); \
(old_hae3) = REGVAL(T2_HAE0_3); \
alpha_mb(); \
REGVAL(T2_HAE0_3) = (old_hae3) | (1<<30); \
alpha_mb(); \
} while(0); \
}
#define T2_TYPE1_TEARDOWN(b,s,old_hae3) if((b)) { \
do { \
alpha_mb(); \
REGVAL(T2_HAE0_3) = (old_hae3); \
alpha_mb(); \
splx((s)); \
} while(0); \
}
#define SWIZ_CFGREAD(b, s, f, r, width, type) \
type val = ~0; \
int ipl = 0; \
u_int32_t old_hae3 = 0; \
vm_offset_t off = T2_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \
alpha_mb(); \
T2_TYPE1_SETUP(b,ipl,old_hae3); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \
} \
T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \
return val;
#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) \
int ipl = 0; \
u_int32_t old_hae3 = 0; \
vm_offset_t off = T2_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \
alpha_mb(); \
T2_TYPE1_SETUP(b,ipl,old_hae3); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \
alpha_wmb(); \
} \
T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \
return;
static u_int8_t
t2_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
SWIZ_CFGREAD(b, s, f, r, BYTE, u_int8_t);
}
static u_int16_t
t2_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
SWIZ_CFGREAD(b, s, f, r, WORD, u_int16_t);
}
static u_int32_t
t2_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
SWIZ_CFGREAD(b, s, f, r, LONG, u_int32_t);
}
static void
t2_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
SWIZ_CFGWRITE(b, s, f, r, data, BYTE, u_int8_t);
}
static void
t2_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
SWIZ_CFGWRITE(b, s, f, r, data, WORD, u_int16_t);
}
static void
t2_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
SWIZ_CFGWRITE(b, s, f, r, data, LONG, u_int32_t);
t2_set_hae_mem(0, pa);
}
static int t2_probe(device_t dev);
@ -407,7 +172,7 @@ t2_sgmap_invalidate(void)
}
static void
t2_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa)
t2_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa)
{
u_int64_t *sgtable = arg;
int index = alpha_btop(ba - T2_SGMAP_BASE);
@ -468,10 +233,18 @@ void
t2_init()
{
static int initted = 0;
static struct swiz_space io_space, mem_space;
if (initted) return;
initted = 1;
swiz_init_space(&io_space, KV(T2_PCI_SIO));
swiz_init_space_hae(&mem_space, KV(T2_PCI_SPARSE),
t2_set_hae_mem, 0);
busspace_isa_io = (kobj_t) &io_space;
busspace_isa_mem = (kobj_t) &mem_space;
chipset = t2_chipset;
}

View file

@ -34,6 +34,15 @@
#include <machine/bus.h>
#include <sys/rman.h>
#include <pci/pcivar.h>
#include <machine/swiz.h>
#include <alpha/pci/t2reg.h>
#include <alpha/pci/t2var.h>
#include "alphapci_if.h"
#include "pcib_if.h"
#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa)
static devclass_t pcib_devclass;
@ -53,13 +62,108 @@ t2_pcib_probe(device_t dev)
static int
t2_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
if (which == PCIB_IVAR_HOSE) {
if (which == PCIB_IVAR_BUS) {
*result = 0;
return 0;
}
return ENOENT;
}
static void *
t2_pcib_cvt_dense(device_t dev, vm_offset_t addr)
{
addr &= 0xffffffffUL;
return (void *) KV(addr | T2_PCI_DENSE);
}
static int
t2_pcib_maxslots(device_t dev)
{
return 31;
}
#define T2_CFGOFF(b, s, f, r) \
((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) \
: ((1 << ((s) + 11)) | ((f) << 8) | (r)))
#define T2_TYPE1_SETUP(b,s,old_hae3) if((b)) { \
do { \
(s) = splhigh(); \
(old_hae3) = REGVAL(T2_HAE0_3); \
alpha_mb(); \
REGVAL(T2_HAE0_3) = (old_hae3) | (1<<30); \
alpha_mb(); \
} while(0); \
}
#define T2_TYPE1_TEARDOWN(b,s,old_hae3) if((b)) { \
do { \
alpha_mb(); \
REGVAL(T2_HAE0_3) = (old_hae3); \
alpha_mb(); \
splx((s)); \
} while(0); \
}
#define SWIZ_CFGREAD(b, s, f, r, width, type) do { \
type val = ~0; \
int ipl = 0; \
u_int32_t old_hae3 = 0; \
vm_offset_t off = T2_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \
alpha_mb(); \
T2_TYPE1_SETUP(b,ipl,old_hae3); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \
} \
T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \
return val; \
} while (0)
#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) do { \
int ipl = 0; \
u_int32_t old_hae3 = 0; \
vm_offset_t off = T2_CFGOFF(b, s, f, r); \
vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \
alpha_mb(); \
T2_TYPE1_SETUP(b,ipl,old_hae3); \
if (!badaddr((caddr_t)kv, sizeof(type))) { \
SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \
alpha_wmb(); \
} \
T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \
return; \
} while (0)
static u_int32_t
t2_pcib_read_config(device_t dev, int b, int s, int f,
int reg, int width)
{
switch (width) {
case 1:
SWIZ_CFGREAD(b, s, f, reg, BYTE, u_int8_t);
case 2:
SWIZ_CFGREAD(b, s, f, reg, WORD, u_int16_t);
case 4:
SWIZ_CFGREAD(b, s, f, reg, LONG, u_int32_t);
}
return ~0;
}
static void
t2_pcib_write_config(device_t dev, int b, int s, int f,
int reg, u_int32_t val, int width)
{
switch (width) {
case 1:
SWIZ_CFGWRITE(b, s, f, reg, val, BYTE, u_int8_t);
case 2:
SWIZ_CFGWRITE(b, s, f, reg, val, WORD, u_int16_t);
case 4:
SWIZ_CFGWRITE(b, s, f, reg, val, LONG, u_int32_t);
}
}
static device_method_t t2_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, t2_pcib_probe),
@ -75,6 +179,14 @@ static device_method_t t2_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* alphapci interface */
DEVMETHOD(alphapci_cvt_dense, t2_pcib_cvt_dense),
/* pcib interface */
DEVMETHOD(pcib_maxslots, t2_pcib_maxslots),
DEVMETHOD(pcib_read_config, t2_pcib_read_config),
DEVMETHOD(pcib_write_config, t2_pcib_write_config),
{ 0, 0 }
};

View file

@ -26,4 +26,6 @@
* $FreeBSD$
*/
extern vm_offset_t t2_csr_base;
extern void t2_init(void);

View file

@ -67,302 +67,17 @@ static volatile tsunami_pchip *pchip[2] = {pchip0, pchip1};
#define TSUNAMI_SOFTC(dev) (struct tsunami_softc*) device_get_softc(dev)
static alpha_chipset_inb_t tsunami_inb;
static alpha_chipset_inw_t tsunami_inw;
static alpha_chipset_inl_t tsunami_inl;
static alpha_chipset_outb_t tsunami_outb;
static alpha_chipset_outw_t tsunami_outw;
static alpha_chipset_outl_t tsunami_outl;
static alpha_chipset_readb_t tsunami_readb;
static alpha_chipset_readw_t tsunami_readw;
static alpha_chipset_readl_t tsunami_readl;
static alpha_chipset_writeb_t tsunami_writeb;
static alpha_chipset_writew_t tsunami_writew;
static alpha_chipset_writel_t tsunami_writel;
static alpha_chipset_maxdevs_t tsunami_maxdevs;
static alpha_chipset_cfgreadb_t tsunami_cfgreadb;
static alpha_chipset_cfgreadw_t tsunami_cfgreadw;
static alpha_chipset_cfgreadl_t tsunami_cfgreadl;
static alpha_chipset_cfgwriteb_t tsunami_cfgwriteb;
static alpha_chipset_cfgwritew_t tsunami_cfgwritew;
static alpha_chipset_cfgwritel_t tsunami_cfgwritel;
static alpha_chipset_addrcvt_t tsunami_cvt_dense, tsunami_cvt_bwx;
static alpha_chipset_read_hae_t tsunami_read_hae;
static alpha_chipset_write_hae_t tsunami_write_hae;
static alpha_chipset_t tsunami_chipset = {
tsunami_inb,
tsunami_inw,
tsunami_inl,
tsunami_outb,
tsunami_outw,
tsunami_outl,
tsunami_readb,
tsunami_readw,
tsunami_readl,
tsunami_writeb,
tsunami_writew,
tsunami_writel,
tsunami_maxdevs,
tsunami_cfgreadb,
tsunami_cfgreadw,
tsunami_cfgreadl,
tsunami_cfgwriteb,
tsunami_cfgwritew,
tsunami_cfgwritel,
tsunami_cvt_dense,
tsunami_cvt_bwx,
tsunami_read_hae,
tsunami_write_hae,
};
/*
* This setup will only allow for one additional hose
*/
#define ADDR_TO_HOSE(x) ((x) >> 31)
#define STRIP_HOSE(x) ((x) & 0x7fffffff)
static void tsunami_intr_enable __P((int));
static void tsunami_intr_disable __P((int));
static u_int8_t
tsunami_inb(u_int32_t port)
{
int hose = ADDR_TO_HOSE(port);
port = STRIP_HOSE(port);
alpha_mb();
return ldbu(KV(TSUNAMI_IO(hose) + port));
}
static u_int16_t
tsunami_inw(u_int32_t port)
{
int hose = ADDR_TO_HOSE(port);
port = STRIP_HOSE(port);
alpha_mb();
return ldwu(KV(TSUNAMI_IO(hose) + port));
}
static u_int32_t
tsunami_inl(u_int32_t port)
{
int hose = ADDR_TO_HOSE(port);
port = STRIP_HOSE(port);
alpha_mb();
return ldl(KV(TSUNAMI_IO(hose) + port));
}
static void
tsunami_outb(u_int32_t port, u_int8_t data)
{
int hose = ADDR_TO_HOSE(port);
port = STRIP_HOSE(port);
stb(KV(TSUNAMI_IO(hose) + port), data);
alpha_mb();
}
static void
tsunami_outw(u_int32_t port, u_int16_t data)
{
int hose = ADDR_TO_HOSE(port);
port = STRIP_HOSE(port);
stw(KV(TSUNAMI_IO(hose) + port), data);
alpha_mb();
}
static void
tsunami_outl(u_int32_t port, u_int32_t data)
{
int hose = ADDR_TO_HOSE(port);
port = STRIP_HOSE(port);
stl(KV(TSUNAMI_IO(hose) + port), data);
alpha_mb();
}
static u_int8_t
tsunami_readb(u_int32_t pa)
{
int hose = ADDR_TO_HOSE(pa);
pa = STRIP_HOSE(pa);
alpha_mb();
return ldbu(KV(TSUNAMI_MEM(hose) + pa));
}
static u_int16_t
tsunami_readw(u_int32_t pa)
{
int hose = ADDR_TO_HOSE(pa);
pa = STRIP_HOSE(pa);
alpha_mb();
return ldwu(KV(TSUNAMI_MEM(hose) + pa));
}
static u_int32_t
tsunami_readl(u_int32_t pa)
{
int hose = ADDR_TO_HOSE(pa);
pa = STRIP_HOSE(pa);
alpha_mb();
return ldl(KV(TSUNAMI_MEM(hose) + pa));
}
static void
tsunami_writeb(u_int32_t pa, u_int8_t data)
{
int hose = ADDR_TO_HOSE(pa);
pa = STRIP_HOSE(pa);
stb(KV(TSUNAMI_MEM(hose) + pa), data);
alpha_mb();
}
static void
tsunami_writew(u_int32_t pa, u_int16_t data)
{
int hose = ADDR_TO_HOSE(pa);
pa = STRIP_HOSE(pa);
stw(KV(TSUNAMI_MEM(hose) + pa), data);
alpha_mb();
}
static void
tsunami_writel(u_int32_t pa, u_int32_t data)
{
int hose = ADDR_TO_HOSE(pa);
pa = STRIP_HOSE(pa);
stl(KV(TSUNAMI_MEM(hose) + pa), data);
alpha_mb();
}
static int
tsunami_maxdevs(u_int b)
{
return 12; /* XXX */
}
static void
tsunami_clear_abort(void)
{
alpha_mb();
alpha_pal_draina();
}
static int
tsunami_check_abort(void)
{
/* u_int32_t errbits;*/
int ba = 0;
alpha_pal_draina();
alpha_mb();
#if 0
errbits = REGVAL(TSUNAMI_CSR_TSUNAMI_ERR);
if (errbits & (TSUNAMI_ERR_RCVD_MAS_ABT|TSUNAMI_ERR_RCVD_TAR_ABT))
ba = 1;
if (errbits) {
REGVAL(TSUNAMI_CSR_TSUNAMI_ERR) = errbits;
alpha_mb();
alpha_pal_draina();
}
#endif
return ba;
}
#define TSUNAMI_CFGADDR(b, s, f, r, h) \
KV(TSUNAMI_CONF(h) | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
#define CFGREAD(h, b, s, f, r, op, width, type) \
int bus; \
vm_offset_t va; \
type data; \
if (h == (u_int8_t)-1) \
h = tsunami_hose_from_bus(b); \
bus = tsunami_bus_within_hose(h, b); \
va = TSUNAMI_CFGADDR(bus, s, f, r, h); \
tsunami_clear_abort(); \
if (badaddr((caddr_t)va, width)) { \
tsunami_check_abort(); \
return ~0; \
} \
data = ##op##(va); \
if (tsunami_check_abort()) \
return ~0; \
return data;
#define CFWRITE(h, b, s, f, r, data, op, width) \
int bus; \
vm_offset_t va; \
if (h == (u_int8_t)-1) \
h = tsunami_hose_from_bus(b); \
bus = tsunami_bus_within_hose(h, b); \
va = TSUNAMI_CFGADDR(bus, s, f, r, h); \
tsunami_clear_abort(); \
if (badaddr((caddr_t)va, width)) \
return; \
##op##(va, data); \
tsunami_check_abort();
static u_int8_t
tsunami_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
CFGREAD(h, b, s, f, r, ldbu, 1, u_int8_t)
}
static u_int16_t
tsunami_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
CFGREAD(h, b, s, f, r, ldwu, 2, u_int16_t)
}
static u_int32_t
tsunami_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
CFGREAD(h, b, s, f, r, ldl, 4, u_int32_t)
}
static void
tsunami_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
CFWRITE(h, b, s, f, r, data, stb, 1)
}
static void
tsunami_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
CFWRITE(h, b, s, f, r, data, stw, 2)
}
static void
tsunami_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
CFWRITE(h, b, s, f, r, data, stl, 4)
}
vm_offset_t
tsunami_cvt_bwx(vm_offset_t addr)
{
int hose;
vm_offset_t laddr;
laddr = addr & 0xffffffffUL;
hose = ADDR_TO_HOSE(laddr);
laddr = STRIP_HOSE(addr);
laddr |= TSUNAMI_MEM(hose);
return (KV(laddr));
}
vm_offset_t
tsunami_cvt_dense(vm_offset_t addr)
{
return tsunami_cvt_bwx(addr);
}
/*
* There doesn't appear to be an hae on this platform
*/
@ -394,10 +109,6 @@ static device_method_t tsunami_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
DEVMETHOD(bus_release_resource, pci_release_resource),
DEVMETHOD(bus_activate_resource, pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
DEVMETHOD(bus_setup_intr, tsunami_setup_intr),
DEVMETHOD(bus_teardown_intr, tsunami_teardown_intr),
@ -478,7 +189,7 @@ tsunami_sgmap_invalidate(void)
}
static void
tsunami_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa)
tsunami_sgmap_map(void *arg, bus_addr_t ba, vm_offset_t pa)
{
u_int64_t *sgtable = arg;
int index = alpha_btop(ba - TSUNAMI_SGMAP_BASE);
@ -522,10 +233,21 @@ void
tsunami_init()
{
static int initted = 0;
static struct bwx_space io_space;
static struct bwx_space mem_space;
if (initted) return;
initted = 1;
/*
* Define two temporary spaces for bootstrap i/o on hose 0.
*/
bwx_init_space(&io_space, KV(TSUNAMI_IO(0)));
bwx_init_space(&mem_space, KV(TSUNAMI_MEM(0)));
busspace_isa_io = (kobj_t) &io_space;
busspace_isa_mem = (kobj_t) &mem_space;
chipset = tsunami_chipset;
platform.pci_intr_enable = tsunami_intr_enable;
platform.pci_intr_disable = tsunami_intr_disable;
@ -539,7 +261,6 @@ static int
tsunami_probe(device_t dev)
{
device_t child;
int *hose;
int i;
if (tsunami0)
return ENXIO;
@ -554,18 +275,13 @@ tsunami_probe(device_t dev)
isa_init_intr();
for(i = 0; i < tsunami_num_pchips; i++) {
hose = malloc(sizeof(int), M_DEVBUF, M_NOWAIT);
*hose = i;
child = device_add_child(dev, "pcib", i);
device_set_ivars(child, hose);
pchip_init(pchip[i], i);
}
return 0;
}
static int
tsunami_attach(device_t dev)
{

View file

@ -38,113 +38,215 @@
#include <pci/pcivar.h>
#include <alpha/pci/tsunamireg.h>
#include <alpha/pci/tsunamivar.h>
#include <alpha/pci/pcibus.h>
#include <machine/resource.h>
#include <machine/bwx.h>
#include "alphapci_if.h"
#include "pcib_if.h"
struct tsunami_hose_softc {
struct bwx_space io; /* accessor for ports */
struct bwx_space mem; /* accessor for memory */
struct rman io_rman; /* resource manager for ports */
struct rman mem_rman; /* resource manager for memory */
};
static devclass_t pcib_devclass;
int tsunami_hoses[TSUNAMI_MAXHOSES+1] = {1,-1,-1,-1,-1};
int tsunami_maxhoseno = 0;
extern int tsunami_num_pchips;
/*
* This comment attempts to explain why and how we are mapping from
* the DEQ assigned bus numbers to the FreeBSD assigned numbers.
*
* FreeBSD must number buses with monotonically increasing numbers for a
* variety of reasons (pciconf, newbus, etc).
*
* DEQ numbers them (from what I can tell) on a per-hose bases. And
* for some reason they seem to always leave bus 1 unused.
*
* When generating config space addrs, we need to know if we are
* directly on the primary bus on that hose, or if we are behind a ppb.
* We keep track of this by assigning hoses monotonically increasing
* numbers. This fits nicely with DEQ not using bus number 1; I
* assume that is what it as intended for. I guess we'll see if they
* come out with a system using more than one pchip..
*
* Next, we must attempt to map the FreeBSD assigned numbers to the
* numbers assigned by DEQ in order to generate proper config space
* addrs. We store the next number past the 0th bus of our hose and
* do subtraction to determine what the DEQ number should have been,
* given a FreeBSD bus number. This is disgusting & quite possibly
* wrong.
*/
int
tsunami_bus_within_hose(int hose, int bus)
{
if (hose == bus)
return 0;
else
return ( (bus - tsunami_hoses[hose]) + 1);
}
/*
* this function supports pciconf ioctls
*/
int
tsunami_hose_from_bus(int bus)
{
int i;
if (bus < tsunami_maxhoseno)
return bus;
for (i = 1; i <= TSUNAMI_MAXHOSES && tsunami_hoses[i] != -1; i++){
if(tsunami_hoses[i] >= bus)
return i-1;
}
return i-1;
}
static int
tsunami_pcib_probe(device_t dev)
{
static int error;
struct tsunami_hose_softc *sc = device_get_softc(dev);
device_t child;
int lastbus;
device_set_desc(dev, "21271 PCI host bus adapter");
child = device_add_child(dev, "pci", -1);
if (tsunami_maxhoseno) {
lastbus = (device_get_unit(child) - 1);
if (lastbus == 0) /* didn't have a ppb on hose 0 */
lastbus++;
tsunami_hoses[tsunami_maxhoseno] = lastbus;
}
if ((error = device_delete_child(dev, child)))
panic("tsunami_pcib_probe: device_delete_child failed\n");
child = device_add_child(dev, "pci", tsunami_maxhoseno);
bwx_init_space(&sc->io, KV(TSUNAMI_IO(device_get_unit(dev))));
bwx_init_space(&sc->mem, KV(TSUNAMI_MEM(device_get_unit(dev))));
if (tsunami_maxhoseno != device_get_unit(child)) {
printf("tsunami_pcib_probe: wanted unit %d ",
tsunami_maxhoseno);
printf(" got unit %d\n", device_get_unit(child));
panic("tsunami_pcib_probe: incorrect bus numbering");
sc->io_rman.rm_start = 0;
sc->io_rman.rm_end = ~0u;
sc->io_rman.rm_type = RMAN_ARRAY;
sc->io_rman.rm_descr = "I/O ports";
if (rman_init(&sc->io_rman)
|| rman_manage_region(&sc->io_rman, 0x0, (1L << 32)))
panic("tsunami_pcib_probe: io_rman");
sc->mem_rman.rm_start = 0;
sc->mem_rman.rm_end = ~0u;
sc->mem_rman.rm_type = RMAN_ARRAY;
sc->mem_rman.rm_descr = "I/O memory";
if (rman_init(&sc->mem_rman)
|| rman_manage_region(&sc->mem_rman, 0x0, (1L << 32)))
panic("tsunami_pcib_probe: mem_rman");
/*
* Replace the temporary bootstrap spaces with real onys. This
* isn't stictly necessary but it keeps things tidy.
*/
if (device_get_unit(dev) == 0) {
busspace_isa_io = (kobj_t) &sc->io;
busspace_isa_mem = (kobj_t) &sc->mem;
}
tsunami_maxhoseno++;
return 0;
}
static int
tsunami_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
if (which == PCIB_IVAR_HOSE) {
*result = *(int*) device_get_ivars(dev);
return 0;
if (which == PCIB_IVAR_BUS) {
*result = 0;
}
return ENOENT;
}
static void *
tsunami_pcib_cvt_dense(device_t dev, vm_offset_t addr)
{
int h = device_get_unit(dev);
addr &= 0xffffffffUL;
return (void *) KV(addr | TSUNAMI_MEM(h));
}
static void *
tsunami_pcib_cvt_bwx(device_t dev, vm_offset_t addr)
{
int h = device_get_unit(dev);
addr &= 0xffffffffUL;
return (void *) KV(addr | TSUNAMI_MEM(h));
}
static kobj_t
tsunami_pcib_get_bustag(device_t dev, int type)
{
struct tsunami_hose_softc *sc = device_get_softc(dev);
switch (type) {
case SYS_RES_IOPORT:
return (kobj_t) &sc->io;
case SYS_RES_MEMORY:
return (kobj_t) &sc->mem;
}
return 0;
}
static struct rman *
tsunami_pcib_get_rman(device_t dev, int type)
{
struct tsunami_hose_softc *sc = device_get_softc(dev);
switch (type) {
case SYS_RES_IOPORT:
return &sc->io_rman;
case SYS_RES_MEMORY:
return &sc->mem_rman;
}
return 0;
}
static int
tsunami_pcib_maxslots(device_t dev)
{
return 31;
}
static void
tsunami_clear_abort(void)
{
alpha_mb();
alpha_pal_draina();
}
static int
tsunami_check_abort(void)
{
/* u_int32_t errbits;*/
int ba = 0;
alpha_pal_draina();
alpha_mb();
#if 0
errbits = REGVAL(TSUNAMI_CSR_TSUNAMI_ERR);
if (errbits & (TSUNAMI_ERR_RCVD_MAS_ABT|TSUNAMI_ERR_RCVD_TAR_ABT))
ba = 1;
if (errbits) {
REGVAL(TSUNAMI_CSR_TSUNAMI_ERR) = errbits;
alpha_mb();
alpha_pal_draina();
}
#endif
return ba;
}
#define TSUNAMI_CFGADDR(b, s, f, r, h) \
KV(TSUNAMI_CONF(h) | ((b) << 16) | ((s) << 11) | ((f) << 8) | (r))
#define CFGREAD(h, b, s, f, r, op, width, type) do { \
vm_offset_t va; \
type data; \
va = TSUNAMI_CFGADDR(b, s, f, r, h); \
tsunami_clear_abort(); \
if (badaddr((caddr_t)va, width)) { \
tsunami_check_abort(); \
return ~0; \
} \
data = ##op##(va); \
if (tsunami_check_abort()) \
return ~0; \
return data; \
} while (0)
#define CFGWRITE(h, b, s, f, r, data, op, width) do { \
vm_offset_t va; \
va = TSUNAMI_CFGADDR(b, s, f, r, h); \
tsunami_clear_abort(); \
if (badaddr((caddr_t)va, width)) \
return; \
##op##(va, data); \
tsunami_check_abort(); \
} while (0)
static u_int32_t
tsunami_pcib_read_config(device_t dev, int b, int s, int f,
int reg, int width)
{
int h = device_get_unit(dev);
switch (width) {
case 1:
CFGREAD(h, b, s, f, reg, ldbu, 1, u_int8_t);
case 2:
CFGREAD(h, b, s, f, reg, ldwu, 2, u_int16_t);
case 4:
CFGREAD(h, b, s, f, reg, ldl, 4, u_int32_t);
}
return ~0;
}
static void
tsunami_pcib_write_config(device_t dev, int b, int s, int f,
int reg, u_int32_t val, int width)
{
int h = device_get_unit(dev);
switch (width) {
case 1:
CFGWRITE(h, b, s, f, reg, val, stb, 1);
case 2:
CFGWRITE(h, b, s, f, reg, val, stw, 2);
case 4:
CFGWRITE(h, b, s, f, reg, val, stl, 4);
}
}
static device_method_t tsunami_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, tsunami_pcib_probe),
@ -153,13 +255,24 @@ static device_method_t tsunami_pcib_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, tsunami_pcib_read_ivar),
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_alloc_resource, pci_alloc_resource),
DEVMETHOD(bus_release_resource, pci_release_resource),
DEVMETHOD(bus_activate_resource, pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
DEVMETHOD(bus_setup_intr, alpha_platform_pci_setup_intr),
DEVMETHOD(bus_teardown_intr, alpha_platform_pci_teardown_intr),
/* alphapci interface */
DEVMETHOD(alphapci_cvt_dense, tsunami_pcib_cvt_dense),
DEVMETHOD(alphapci_cvt_bwx, tsunami_pcib_cvt_bwx),
DEVMETHOD(alphapci_get_bustag, tsunami_pcib_get_bustag),
DEVMETHOD(alphapci_get_rman, tsunami_pcib_get_rman),
/* pcib interface */
DEVMETHOD(pcib_maxslots, tsunami_pcib_maxslots),
DEVMETHOD(pcib_read_config, tsunami_pcib_read_config),
DEVMETHOD(pcib_write_config, tsunami_pcib_write_config),
{ 0, 0 }
};
@ -167,7 +280,7 @@ static device_method_t tsunami_pcib_methods[] = {
static driver_t tsunami_pcib_driver = {
"pcib",
tsunami_pcib_methods,
1,
sizeof(struct tsunami_hose_softc),
};

View file

@ -88,6 +88,9 @@
#include <alpha/pci/pcibus.h>
#include <pci/pcivar.h>
#include "alphapci_if.h"
#include "pcib_if.h"
static devclass_t dwlpx_devclass;
static device_t dwlpxs[DWLPX_NIONODE][DWLPX_NHOSE];
@ -101,6 +104,10 @@ struct dwlpx_softc {
vm_offset_t dmem_base; /* dense memory */
vm_offset_t smem_base; /* sparse memory */
vm_offset_t io_base; /* sparse i/o */
struct swiz_space io_space; /* accessor for ports */
struct swiz_space mem_space; /* accessor for memory */
struct rman io_rman; /* resource manager for ports */
struct rman mem_rman; /* resource manager for memory */
int bushose; /* our bus && hose */
u_int : 26,
nhpc : 2, /* how many HPCs */
@ -108,34 +115,8 @@ struct dwlpx_softc {
sgmapsz : 3; /* Scatter Gather map size */
};
static int dwlpx_probe(device_t dev);
static int dwlpx_attach(device_t dev);
static int dwlpx_setup_intr(device_t, device_t, struct resource *, int,
driver_intr_t *, void *, void **);
static int
dwlpx_teardown_intr(device_t, device_t, struct resource *, void *);
static driver_intr_t dwlpx_intr;
static device_method_t dwlpx_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, dwlpx_probe),
DEVMETHOD(device_attach, dwlpx_attach),
/* Bus interface */
DEVMETHOD(bus_setup_intr, dwlpx_setup_intr),
DEVMETHOD(bus_teardown_intr, dwlpx_teardown_intr),
DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
DEVMETHOD(bus_release_resource, pci_release_resource),
DEVMETHOD(bus_activate_resource, pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
{ 0, 0 }
};
static driver_t dwlpx_driver = {
"dwlpx", dwlpx_methods, sizeof (struct dwlpx_softc)
};
static u_int32_t imaskcache[DWLPX_NIONODE][DWLPX_NHOSE][NHPC];
static void dwlpx_eintr(unsigned long);
@ -152,391 +133,9 @@ static void dwlpx_eintr(unsigned long);
#define DWLPx_SG_MAPPED_SIZE(x) ((x) * PAGE_SIZE)
static void dwlpx_dma_init(struct dwlpx_softc *);
#define DWLPX_SOFTC(dev) (struct dwlpx_softc *) device_get_softc(dev)
static struct dwlpx_softc *dwlpx_root;
static alpha_chipset_inb_t dwlpx_inb;
static alpha_chipset_inw_t dwlpx_inw;
static alpha_chipset_inl_t dwlpx_inl;
static alpha_chipset_outb_t dwlpx_outb;
static alpha_chipset_outw_t dwlpx_outw;
static alpha_chipset_outl_t dwlpx_outl;
static alpha_chipset_readb_t dwlpx_readb;
static alpha_chipset_readw_t dwlpx_readw;
static alpha_chipset_readl_t dwlpx_readl;
static alpha_chipset_writeb_t dwlpx_writeb;
static alpha_chipset_writew_t dwlpx_writew;
static alpha_chipset_writel_t dwlpx_writel;
static alpha_chipset_maxdevs_t dwlpx_maxdevs;
static alpha_chipset_cfgreadb_t dwlpx_cfgreadb;
static alpha_chipset_cfgreadw_t dwlpx_cfgreadw;
static alpha_chipset_cfgreadl_t dwlpx_cfgreadl;
static alpha_chipset_cfgwriteb_t dwlpx_cfgwriteb;
static alpha_chipset_cfgwritew_t dwlpx_cfgwritew;
static alpha_chipset_cfgwritel_t dwlpx_cfgwritel;
static alpha_chipset_t dwlpx_chipset = {
dwlpx_inb,
dwlpx_inw,
dwlpx_inl,
dwlpx_outb,
dwlpx_outw,
dwlpx_outl,
dwlpx_readb,
dwlpx_readw,
dwlpx_readl,
dwlpx_writeb,
dwlpx_writew,
dwlpx_writel,
dwlpx_maxdevs,
dwlpx_cfgreadb,
dwlpx_cfgreadw,
dwlpx_cfgreadl,
dwlpx_cfgwriteb,
dwlpx_cfgwritew,
dwlpx_cfgwritel,
};
#define DWLPX_IONODE(port) ((port >> 29) & 0x7)
#define DWLPX_HOSE(port) ((port >> 27) & 0x3)
#define DWLPX_INST(port) dwlpxs[DWLPX_IONODE(port)][DWLPX_HOSE(port)]
#define DWLPX_ADDR(port) (port & 0x07ffffff)
static u_int8_t
dwlpx_inb(u_int32_t port)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(port));
return SPARSE_READ_BYTE(sc->io_base, DWLPX_ADDR(port));
}
static u_int16_t
dwlpx_inw(u_int32_t port)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(port));
return SPARSE_READ_WORD(sc->io_base, DWLPX_ADDR(port));
}
static u_int32_t
dwlpx_inl(u_int32_t port)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(port));
return SPARSE_READ_LONG(sc->io_base, DWLPX_ADDR(port));
}
static void
dwlpx_outb(u_int32_t port, u_int8_t data)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(port));
SPARSE_WRITE_BYTE(sc->io_base, DWLPX_ADDR(port), data);
alpha_mb();
}
static void
dwlpx_outw(u_int32_t port, u_int16_t data)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(port));
SPARSE_WRITE_WORD(sc->io_base, DWLPX_ADDR(port), data);
alpha_mb();
}
static void
dwlpx_outl(u_int32_t port, u_int32_t data)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(port));
SPARSE_WRITE_LONG(sc->io_base, DWLPX_ADDR(port), data);
alpha_mb();
}
static u_int8_t
dwlpx_readb(u_int32_t pa)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(pa));
return SPARSE_READ_BYTE(sc->smem_base, DWLPX_ADDR(pa));
}
static u_int16_t
dwlpx_readw(u_int32_t pa)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(pa));
return SPARSE_READ_WORD(sc->smem_base, DWLPX_ADDR(pa));
}
static u_int32_t
dwlpx_readl(u_int32_t pa)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(pa));
return SPARSE_READ_LONG(sc->smem_base, DWLPX_ADDR(pa));
}
static void
dwlpx_writeb(u_int32_t pa, u_int8_t data)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(pa));
SPARSE_WRITE_BYTE(sc->smem_base, DWLPX_ADDR(pa), data);
alpha_mb();
}
static void
dwlpx_writew(u_int32_t pa, u_int16_t data)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(pa));
SPARSE_WRITE_WORD(sc->smem_base, DWLPX_ADDR(pa), data);
alpha_mb();
}
static void
dwlpx_writel(u_int32_t pa, u_int32_t data)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(DWLPX_INST(pa));
SPARSE_WRITE_LONG(sc->smem_base, DWLPX_ADDR(pa), data);
alpha_mb();
}
static int
dwlpx_maxdevs(u_int b)
{
return (DWLPX_MAXDEV);
}
static u_int32_t dwlpx_cfgread(u_int, u_int, u_int, u_int, u_int, int);
static void dwlpx_cfgwrite(u_int, u_int, u_int, u_int, u_int, int, u_int32_t);
#if 0
#define RCFGP printf
#else
#define RCFGP if (0) printf
#endif
static u_int32_t
dwlpx_cfgread(u_int bh, u_int bus, u_int slot, u_int func, u_int off, int sz)
{
struct dwlpx_softc *sc;
device_t dev;
u_int32_t *dp, data, rvp, pci_idsel, hpcdev;
unsigned long paddr;
int hose, ionode;
int s = 0, i;
RCFGP("CFGREAD %u.%u.%u.%u.%u.%d", bh, bus, slot, func, off, sz);
rvp = data = ~0;
if (bh == (u_int8_t)-1)
bh = bus >> 4;
ionode = ((bh >> 2) & 0x7);
hose = (bh & 0x3);
dev = dwlpxs[ionode][hose];
if (dev == (device_t) 0) {
RCFGP(" (no dev)\n");
return (data);
}
sc = DWLPX_SOFTC(dev);
bus &= 0xf;
if (sc->nhpc < 1) {
RCFGP(" (no hpcs)\n");
return (data);
} else if (sc->nhpc < 2 && slot >= 4) {
RCFGP(" (bad hpcs (%d) <> bad slot (%d))\n", sc->nhpc, slot);
return (data);
} else if (sc->nhpc < 3 && slot >= 8) {
RCFGP(" (bad hpcs (%d) <> bad slot (%d))\n", sc->nhpc, slot);
return (data);
} else if (slot >= DWLPX_MAXDEV) {
RCFGP(" (bad slot (%d))\n", slot);
return (data);
}
hpcdev = slot >> 2;
pci_idsel = (1 << ((slot & 0x3) + 2));
paddr = (hpcdev << 22) | (pci_idsel << 16) | (func << 13);
if (bus) {
paddr &= 0x1fffff;
paddr |= (bus << 21);
alpha_pal_draina();
s = splhigh();
/*
* Set up HPCs for type 1 cycles.
*/
for (i = 0; i < sc->nhpc; i++) {
rvp = REGVAL(PCIA_CTL(i)+sc->sysbase) | PCIA_CTL_T1CYC;
alpha_mb();
REGVAL(PCIA_CTL(i) + sc->sysbase) = rvp;
alpha_mb();
}
}
paddr |= ((unsigned long) ((off >> 2) << 7));
paddr |= ((sz - 1) << 3);
paddr |= DWLPX_PCI_CONF;
paddr |= ((unsigned long) hose) << 34;
paddr |= ((unsigned long) ionode) << 36;
paddr |= 1L << 39;
dp = (u_int32_t *)KV(paddr);
RCFGP(" hose %d node%d paddr 0x%lx", bh, ionode+4, paddr);
if (badaddr(dp, sizeof (*dp)) == 0) {
data = *dp;
}
if (bus) {
alpha_pal_draina();
for (i = 0; i < sc->nhpc; i++) {
rvp = REGVAL(PCIA_CTL(i)+sc->sysbase) & ~PCIA_CTL_T1CYC;
alpha_mb();
REGVAL(PCIA_CTL(i) + sc->sysbase) = rvp;
alpha_mb();
}
(void) splx(s);
}
if (data != ~0) {
if (sz == 1) {
rvp = SPARSE_BYTE_EXTRACT(off, data);
} else if (sz == 2) {
rvp = SPARSE_WORD_EXTRACT(off, data);
} else {
rvp = data;
}
} else {
rvp = data;
}
RCFGP(" data %x->0x%x\n", data, rvp);
return (rvp);
}
#if 0
#define WCFGP printf
#else
#define WCFGP if (0) printf
#endif
static void
dwlpx_cfgwrite(u_int bh, u_int bus, u_int slot, u_int func, u_int off,
int sz, u_int32_t data)
{
int hose, ionode;
int s = 0, i;
u_int32_t *dp, rvp, pci_idsel, hpcdev;
unsigned long paddr;
struct dwlpx_softc *sc;
device_t dev;
WCFGP("CFGWRITE %u.%u.%u.%u.%u.%d", bh, bus, slot, func, off, sz);
if (bh == (u_int8_t)-1)
bh = bus >> 4;
ionode = ((bh >> 2) & 0x7);
hose = (bh & 0x3);
dev = dwlpxs[ionode][hose];
if (dev == (device_t) 0) {
WCFGP(" (no dev)\n");
return;
}
sc = DWLPX_SOFTC(dev);
bus &= 0xf;
if (sc->nhpc < 1) {
WCFGP(" (no hpcs)\n");
return;
} else if (sc->nhpc < 2 && slot >= 4) {
WCFGP(" (bad hpcs (%d) <> bad slot (%d))\n", sc->nhpc, slot);
return;
} else if (sc->nhpc < 3 && slot >= 8) {
WCFGP(" (bad hpcs (%d) <> bad slot (%d))\n", sc->nhpc, slot);
return;
} else if (slot >= DWLPX_MAXDEV) {
WCFGP(" (bad slot (%d))\n", slot);
return;
}
hpcdev = slot >> 2;
pci_idsel = (1 << ((slot & 0x3) + 2));
paddr = (hpcdev << 22) | (pci_idsel << 16) | (func << 13);
bus = 0;
if (bus) {
paddr &= 0x1fffff;
paddr |= (bus << 21);
alpha_pal_draina();
s = splhigh();
/*
* Set up HPCs for type 1 cycles.
*/
for (i = 0; i < sc->nhpc; i++) {
rvp = REGVAL(PCIA_CTL(i)+sc->sysbase) | PCIA_CTL_T1CYC;
alpha_mb();
REGVAL(PCIA_CTL(i) + sc->sysbase) = rvp;
alpha_mb();
}
}
paddr |= ((unsigned long) ((off >> 2) << 7));
paddr |= ((sz - 1) << 3);
paddr |= DWLPX_PCI_CONF;
paddr |= ((unsigned long) hose) << 34;
paddr |= ((unsigned long) ionode) << 36;
paddr |= 1L << 39;
dp = (u_int32_t *)KV(paddr);
WCFGP(" hose %d node%d paddr 0x%lx\n", bh, ionode+4, paddr);
if (badaddr(dp, sizeof (*dp)) == 0) {
u_int32_t new_data;
if (sz == 1) {
new_data = SPARSE_BYTE_INSERT(off, data);
} else if (sz == 2) {
new_data = SPARSE_WORD_INSERT(off, data);
} else {
new_data = data;
}
*dp = new_data;
}
if (bus) {
alpha_pal_draina();
for (i = 0; i < sc->nhpc; i++) {
rvp = REGVAL(PCIA_CTL(i)+sc->sysbase) & ~PCIA_CTL_T1CYC;
alpha_mb();
REGVAL(PCIA_CTL(i) + sc->sysbase) = rvp;
alpha_mb();
}
(void) splx(s);
}
}
static u_int8_t
dwlpx_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r)
{
return (u_int8_t) dwlpx_cfgread(h, b, s, f, r, 1);
}
static u_int16_t
dwlpx_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r)
{
return (u_int16_t) dwlpx_cfgread(h, b, s, f, r, 2);
}
static u_int32_t
dwlpx_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r)
{
return dwlpx_cfgread(h, b, s, f, r, 4);
}
static void
dwlpx_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data)
{
dwlpx_cfgwrite(h, b, s, f, r, 1, (u_int32_t) data);
}
static void
dwlpx_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data)
{
dwlpx_cfgwrite(h, b, s, f, r, 2, (u_int32_t) data);
}
static void
dwlpx_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data)
{
dwlpx_cfgwrite(h, b, s, f, r, 4, (u_int32_t) data);
}
static int
dwlpx_probe(device_t dev)
{
@ -586,7 +185,7 @@ dwlpx_probe(device_t dev)
pci_init_resources();
}
child = device_add_child(dev, "pcib", device_get_unit(dev));
child = device_add_child(dev, "pci", -1);
device_set_ivars(child, &sc->bushose);
return (0);
}
@ -604,15 +203,35 @@ dwlpx_attach(device_t dev)
io = kft_get_node(dev) - 4;
hose = kft_get_hosenum(dev);
chipset = dwlpx_chipset;
/* chipset.intrdev = dev; */
sc->sysbase = DWLPX_BASE(io + 4, hose);
regs = (vm_offset_t) KV(sc->sysbase);
sc->dmem_base = regs + DWLPX_PCI_DENSE;
sc->smem_base = regs + DWLPX_PCI_SPARSE;
sc->io_base = regs + DWLPX_PCI_IOSPACE;
/*
* Maybe initialise busspace_isa_io and busspace_isa_mem
* here. Does the 8200 actually have any ISA slots?
*/
swiz_init_space(&sc->io_space, sc->io_base);
swiz_init_space(&sc->mem_space, sc->smem_base);
sc->io_rman.rm_start = 0;
sc->io_rman.rm_end = ~0u;
sc->io_rman.rm_type = RMAN_ARRAY;
sc->io_rman.rm_descr = "I/O ports";
if (rman_init(&sc->io_rman)
|| rman_manage_region(&sc->io_rman, 0x0, (1L << 32)))
panic("dwlpx_attach: io_rman");
sc->mem_rman.rm_start = 0;
sc->mem_rman.rm_end = ~0u;
sc->mem_rman.rm_type = RMAN_ARRAY;
sc->mem_rman.rm_descr = "I/O memory";
if (rman_init(&sc->mem_rman)
|| rman_manage_region(&sc->mem_rman, 0x0, (1L << 32)))
panic("dwlpx_attach: mem_rman");
/*
* Set up interrupt stuff for this DWLPX.
*
@ -757,6 +376,7 @@ static int
dwlpx_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
driver_intr_t *intr, void *arg, void **cookiep)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(dev);
int slot, ionode, hose, error, vector, intpin;
error = rman_activate_resource(irq);
@ -765,9 +385,8 @@ dwlpx_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
intpin = pci_get_intpin(child);
slot = pci_get_slot(child);
hose = pci_get_hose(child);
ionode = hose >> 2;
hose &= 0x3;
ionode = sc->bushose >> 2;
hose = sc->bushose & 0x3;
vector = DWLPX_MVEC(ionode, hose, slot);
error = alpha_setup_intr(vector, intr, arg, cookiep,
@ -783,19 +402,258 @@ dwlpx_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
static int
dwlpx_teardown_intr(device_t dev, device_t child, struct resource *irq, void *c)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(dev);
int slot, ionode, hose, vector, intpin;
intpin = pci_get_intpin(child);
slot = pci_get_slot(child);
hose = pci_get_hose(child);
ionode = hose >> 2;
hose &= 0x3;
ionode = sc->bushose >> 2;
hose = sc->bushose & 0x3;
vector = DWLPX_MVEC(ionode, hose, slot);
dwlpx_enadis_intr(vector, intpin, 0);
alpha_teardown_intr(c);
return rman_deactivate_resource(irq);
}
static int
dwlpx_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static void *
dwlpx_cvt_dense(device_t dev, vm_offset_t addr)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(dev);
addr &= 0xffffffffUL;
return (void *) KV(addr | sc->dmem_base);
}
static kobj_t
dwlpx_get_bustag(device_t dev, int type)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(dev);
switch (type) {
case SYS_RES_IOPORT:
return (kobj_t) &sc->io_space;
case SYS_RES_MEMORY:
return (kobj_t) &sc->mem_space;
}
return 0;
}
static struct rman *
dwlpx_get_rman(device_t dev, int type)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(dev);
switch (type) {
case SYS_RES_IOPORT:
return &sc->io_rman;
case SYS_RES_MEMORY:
return &sc->mem_rman;
}
return 0;
}
static int
dwlpx_maxslots(device_t dev)
{
return (DWLPX_MAXDEV);
}
static u_int32_t
dwlpx_read_config(device_t dev, int bus, int slot, int func,
int off, int sz)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(dev);
u_int32_t *dp, data, rvp, pci_idsel, hpcdev;
unsigned long paddr;
int hose, ionode;
int secondary = 0, s = 0, i;
rvp = data = ~0;
ionode = ((sc->bushose >> 2) & 0x7);
hose = (sc->bushose & 0x3);
if (sc->nhpc < 1)
return (data);
else if (sc->nhpc < 2 && slot >= 4)
return (data);
else if (sc->nhpc < 3 && slot >= 8)
return (data);
else if (slot >= DWLPX_MAXDEV)
return (data);
hpcdev = slot >> 2;
pci_idsel = (1 << ((slot & 0x3) + 2));
paddr = (hpcdev << 22) | (pci_idsel << 16) | (func << 13);
if (secondary) {
paddr &= 0x1fffff;
paddr |= (secondary << 21);
#if 0
printf("read secondary %d reg %x (paddr %lx)",
secondary, offset, tag);
#endif
alpha_pal_draina();
s = splhigh();
/*
* Set up HPCs for type 1 cycles.
*/
for (i = 0; i < sc->nhpc; i++) {
rvp = REGVAL(PCIA_CTL(i)+sc->sysbase) | PCIA_CTL_T1CYC;
alpha_mb();
REGVAL(PCIA_CTL(i) + sc->sysbase) = rvp;
alpha_mb();
}
}
paddr |= ((unsigned long) ((off >> 2) << 7));
paddr |= ((sz - 1) << 3);
paddr |= DWLPX_PCI_CONF;
paddr |= ((unsigned long) hose) << 34;
paddr |= ((unsigned long) ionode) << 36;
paddr |= 1L << 39;
dp = (u_int32_t *)KV(paddr);
#if 0
printf("CFGREAD %d.%d.%d.%d.%d.%d.%d -> paddr 0x%lx",
ionode+4, hose, bus, slot, func, off, sz, paddr);
#endif
if (badaddr(dp, sizeof (*dp)) == 0) {
data = *dp;
}
if (secondary) {
alpha_pal_draina();
for (i = 0; i < sc->nhpc; i++) {
rvp = REGVAL(PCIA_CTL(i)+sc->sysbase) & ~PCIA_CTL_T1CYC;
alpha_mb();
REGVAL(PCIA_CTL(i) + sc->sysbase) = rvp;
alpha_mb();
}
(void) splx(s);
}
if (data != ~0) {
if (sz == 1) {
rvp = SPARSE_BYTE_EXTRACT(off, data);
} else if (sz == 2) {
rvp = SPARSE_WORD_EXTRACT(off, data);
} else {
rvp = data;
}
} else {
rvp = data;
}
#if 0
printf(" data 0x%x -> 0x%x\n", data, rvp);
#endif
return (rvp);
}
static void
dwlpx_write_config(device_t dev, int bus, int slot, int func,
int off, u_int32_t data, int sz)
{
struct dwlpx_softc *sc = DWLPX_SOFTC(dev);
int hose, ionode;
int secondary = 0, s = 0, i;
u_int32_t *dp, rvp, pci_idsel, hpcdev;
unsigned long paddr;
ionode = ((sc->bushose >> 2) & 0x7);
hose = (sc->bushose & 0x3);
if (sc->nhpc < 1)
return;
else if (sc->nhpc < 2 && slot >= 4)
return;
else if (sc->nhpc < 3 && slot >= 8)
return;
else if (slot >= DWLPX_MAXDEV)
return;
hpcdev = slot >> 2;
pci_idsel = (1 << ((slot & 0x3) + 2));
paddr = (hpcdev << 22) | (pci_idsel << 16) | (func << 13);
if (secondary) {
paddr &= 0x1fffff;
paddr |= (secondary << 21);
#if 0
printf("write secondary %d reg %x (paddr %lx)",
secondary, offset, tag);
#endif
alpha_pal_draina();
s = splhigh();
/*
* Set up HPCs for type 1 cycles.
*/
for (i = 0; i < sc->nhpc; i++) {
rvp = REGVAL(PCIA_CTL(i)+sc->sysbase) | PCIA_CTL_T1CYC;
alpha_mb();
REGVAL(PCIA_CTL(i) + sc->sysbase) = rvp;
alpha_mb();
}
}
paddr |= ((unsigned long) ((off >> 2) << 7));
paddr |= ((sz - 1) << 3);
paddr |= DWLPX_PCI_CONF;
paddr |= ((unsigned long) hose) << 34;
paddr |= ((unsigned long) ionode) << 36;
paddr |= 1L << 39;
dp = (u_int32_t *)KV(paddr);
if (badaddr(dp, sizeof (*dp)) == 0) {
u_int32_t new_data;
if (sz == 1) {
new_data = SPARSE_BYTE_INSERT(off, data);
} else if (sz == 2) {
new_data = SPARSE_WORD_INSERT(off, data);
} else {
new_data = data;
}
#if 0
printf("CFGWRITE %d.%d.%d.%d.%d.%d.%d paddr 0x%lx data 0x%x -> 0x%x\n",
ionode+4, hose, bus, slot, func, off, sz, paddr, data, new_data);
#endif
*dp = new_data;
}
if (secondary) {
alpha_pal_draina();
for (i = 0; i < sc->nhpc; i++) {
rvp = REGVAL(PCIA_CTL(i)+sc->sysbase) & ~PCIA_CTL_T1CYC;
alpha_mb();
REGVAL(PCIA_CTL(i) + sc->sysbase) = rvp;
alpha_mb();
}
(void) splx(s);
}
}
static void
dwlpx_dma_init(struct dwlpx_softc *sc)
{
@ -971,4 +829,36 @@ dwlpx_eintr(unsigned long vec)
}
}
DRIVER_MODULE(dwlpx, kft, dwlpx_driver, dwlpx_devclass, 0, 0);
static device_method_t dwlpx_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, dwlpx_probe),
DEVMETHOD(device_attach, dwlpx_attach),
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, dwlpx_read_ivar),
DEVMETHOD(bus_setup_intr, dwlpx_setup_intr),
DEVMETHOD(bus_teardown_intr, dwlpx_teardown_intr),
DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
DEVMETHOD(bus_release_resource, pci_release_resource),
DEVMETHOD(bus_activate_resource, pci_activate_resource),
DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource),
/* alphapci interface */
DEVMETHOD(alphapci_cvt_dense, dwlpx_cvt_dense),
DEVMETHOD(alphapci_get_bustag, dwlpx_get_bustag),
DEVMETHOD(alphapci_get_rman, dwlpx_get_rman),
/* pcib interface */
DEVMETHOD(pcib_maxslots, dwlpx_maxslots),
DEVMETHOD(pcib_read_config, dwlpx_read_config),
DEVMETHOD(pcib_write_config, dwlpx_write_config),
{ 0, 0 }
};
static driver_t dwlpx_driver = {
"pcib", dwlpx_methods, sizeof (struct dwlpx_softc)
};
DRIVER_MODULE(pcib, kft, dwlpx_driver, dwlpx_devclass, 0, 0);

View file

@ -143,7 +143,7 @@ kft_probe(device_t dev)
if (kd == NULL)
continue;
kd->kd_name = "dwlpx";
kd->kd_name = "pcib";
kd->kd_node = sc->sc_node;
kd->kd_dtype = sc->sc_dtype;
kd->kd_hosenum = hose;

View file

@ -41,35 +41,49 @@
#include <machine/segments.h>
#include <machine/pc/bios.h>
#include "pcib_if.h"
static int cfgmech;
static int devmax;
static int usebios;
static int pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcibios_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcibios_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcibios_cfgopen(void);
static int pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcireg_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcireg_cfgopen(void);
/* read configuration space register */
int
pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
static int
nexus_pcib_maxslots(device_t dev)
{
return 31;
}
static u_int32_t
nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
int reg, int bytes)
{
return(usebios ?
pcibios_cfgread(cfg, reg, bytes) :
pcireg_cfgread(cfg, reg, bytes));
pcibios_cfgread(bus, slot, func, reg, bytes) :
pcireg_cfgread(bus, slot, func, reg, bytes));
}
/* write configuration space register */
void
pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
static void
nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
int reg, u_int32_t data, int bytes)
{
return(usebios ?
pcibios_cfgwrite(cfg, reg, data, bytes) :
pcireg_cfgwrite(cfg, reg, data, bytes));
pcibios_cfgwrite(bus, slot, func, reg, data, bytes) :
pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
}
/* initialise access to PCI configuration space */
@ -89,7 +103,7 @@ pci_cfgopen(void)
/* config space access using BIOS functions */
static int
pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
{
struct bios_regs args;
u_int mask;
@ -110,7 +124,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
default:
return(-1);
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
/* check call results? */
@ -118,7 +132,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
struct bios_regs args;
@ -135,7 +149,7 @@ pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
default:
return;
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.ecx = data;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
@ -200,12 +214,12 @@ pci_cfgdisable(void)
}
static int
pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
{
int data = -1;
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
@ -225,11 +239,11 @@ pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
case 1:
@ -373,7 +387,7 @@ pcireg_cfgopen(void)
static devclass_t pcib_devclass;
static const char *
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
nexus_pcib_is_host_bridge(int bus, int slot, int func,
u_int32_t id, u_int8_t class, u_int8_t subclass,
u_int8_t *busnum)
{
@ -386,8 +400,8 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
case 0x12258086:
s = "Intel 824?? host to PCI bridge";
/* XXX This is a guess */
/* *busnum = pci_cfgread(cfg, 0x41, 1); */
*busnum = cfg->bus;
/* *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x41, 1); */
*busnum = bus;
break;
case 0x71208086:
s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
@ -421,7 +435,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
break;
case 0x84c48086:
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x4a, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x4a, 1);
break;
case 0x84ca8086:
/*
@ -435,13 +449,17 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
* Since the MIOC doesn't have a pci bus attached, we
* pretend it wasn't there.
*/
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
pxb[0] = nexus_pcib_read_config(0, bus, slot, func,
0xd0, 1); /* BUSNO[0] */
pxb[1] = nexus_pcib_read_config(0, bus, slot, func,
0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = nexus_pcib_read_config(0, bus, slot, func,
0xd3, 1); /* BUSNO[1] */
pxb[3] = nexus_pcib_read_config(0, bus, slot, func,
0xd4, 1) + 1; /* SUBA[1]+1 */
return NULL;
case 0x84cb8086:
switch (cfg->slot) {
switch (slot) {
case 0x12:
s = "Intel 82454NX PXB#0, Bus#A";
*busnum = pxb[0];
@ -513,19 +531,19 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
/* RCC -- vendor 0x1166 */
case 0x00051166:
s = "RCC HE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00061166:
/* FALLTHROUGH */
case 0x00081166:
s = "RCC host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00091166:
s = "RCC LE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
/* Integrated Micro Solutions -- vendor 0x10e0 */
@ -549,7 +567,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
static void
nexus_pcib_identify(driver_t *driver, device_t parent)
{
pcicfgregs probe;
int bus, slot, func;
u_int8_t hdrtype;
int found = 0;
int pcifunchigh;
@ -557,19 +575,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
if (pci_cfgopen() == 0)
return;
probe.hose = 0;
probe.bus = 0;
bus = 0;
retry:
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
probe.func = 0;
hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1);
for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
func = 0;
hdrtype = nexus_pcib_read_config(0, bus, slot, func,
PCIR_HEADERTYPE, 1);
if (hdrtype & PCIM_MFDEV)
pcifunchigh = 7;
else
pcifunchigh = 0;
for (probe.func = 0;
probe.func <= pcifunchigh;
probe.func++) {
for (func = 0; func <= pcifunchigh; func++) {
/*
* Read the IDs and class from the device.
*/
@ -578,14 +594,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
device_t child;
const char *s;
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
id = nexus_pcib_read_config(0, bus, slot, func,
PCIR_DEVVENDOR, 4);
if (id == -1)
continue;
class = pci_cfgread(&probe, PCIR_CLASS, 1);
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
class = nexus_pcib_read_config(0, bus, slot, func,
PCIR_CLASS, 1);
subclass = nexus_pcib_read_config(0, bus, slot, func,
PCIR_SUBCLASS, 1);
s = nexus_pcib_is_host_bridge(&probe, id,
class, subclass,
s = nexus_pcib_is_host_bridge(bus, slot, func,
id, class, subclass,
&busnum);
if (s) {
/*
@ -601,8 +620,8 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
}
}
}
if (found824xx && probe.bus == 0) {
probe.bus++;
if (found824xx && bus == 0) {
bus++;
goto retry;
}
@ -629,6 +648,17 @@ nexus_pcib_probe(device_t dev)
return ENXIO;
}
static int
nexus_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static device_method_t nexus_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, nexus_pcib_identify),
@ -640,6 +670,7 @@ static device_method_t nexus_pcib_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, nexus_pcib_read_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@ -647,6 +678,11 @@ static device_method_t nexus_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, nexus_pcib_maxslots),
DEVMETHOD(pcib_read_config, nexus_pcib_read_config),
DEVMETHOD(pcib_write_config, nexus_pcib_write_config),
{ 0, 0 }
};

View file

@ -41,35 +41,49 @@
#include <machine/segments.h>
#include <machine/pc/bios.h>
#include "pcib_if.h"
static int cfgmech;
static int devmax;
static int usebios;
static int pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcibios_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcibios_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcibios_cfgopen(void);
static int pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcireg_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcireg_cfgopen(void);
/* read configuration space register */
int
pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
static int
nexus_pcib_maxslots(device_t dev)
{
return 31;
}
static u_int32_t
nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
int reg, int bytes)
{
return(usebios ?
pcibios_cfgread(cfg, reg, bytes) :
pcireg_cfgread(cfg, reg, bytes));
pcibios_cfgread(bus, slot, func, reg, bytes) :
pcireg_cfgread(bus, slot, func, reg, bytes));
}
/* write configuration space register */
void
pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
static void
nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
int reg, u_int32_t data, int bytes)
{
return(usebios ?
pcibios_cfgwrite(cfg, reg, data, bytes) :
pcireg_cfgwrite(cfg, reg, data, bytes));
pcibios_cfgwrite(bus, slot, func, reg, data, bytes) :
pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
}
/* initialise access to PCI configuration space */
@ -89,7 +103,7 @@ pci_cfgopen(void)
/* config space access using BIOS functions */
static int
pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
{
struct bios_regs args;
u_int mask;
@ -110,7 +124,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
default:
return(-1);
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
/* check call results? */
@ -118,7 +132,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
struct bios_regs args;
@ -135,7 +149,7 @@ pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
default:
return;
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.ecx = data;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
@ -200,12 +214,12 @@ pci_cfgdisable(void)
}
static int
pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
{
int data = -1;
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
@ -225,11 +239,11 @@ pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
case 1:
@ -373,7 +387,7 @@ pcireg_cfgopen(void)
static devclass_t pcib_devclass;
static const char *
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
nexus_pcib_is_host_bridge(int bus, int slot, int func,
u_int32_t id, u_int8_t class, u_int8_t subclass,
u_int8_t *busnum)
{
@ -386,8 +400,8 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
case 0x12258086:
s = "Intel 824?? host to PCI bridge";
/* XXX This is a guess */
/* *busnum = pci_cfgread(cfg, 0x41, 1); */
*busnum = cfg->bus;
/* *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x41, 1); */
*busnum = bus;
break;
case 0x71208086:
s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
@ -421,7 +435,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
break;
case 0x84c48086:
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x4a, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x4a, 1);
break;
case 0x84ca8086:
/*
@ -435,13 +449,17 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
* Since the MIOC doesn't have a pci bus attached, we
* pretend it wasn't there.
*/
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
pxb[0] = nexus_pcib_read_config(0, bus, slot, func,
0xd0, 1); /* BUSNO[0] */
pxb[1] = nexus_pcib_read_config(0, bus, slot, func,
0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = nexus_pcib_read_config(0, bus, slot, func,
0xd3, 1); /* BUSNO[1] */
pxb[3] = nexus_pcib_read_config(0, bus, slot, func,
0xd4, 1) + 1; /* SUBA[1]+1 */
return NULL;
case 0x84cb8086:
switch (cfg->slot) {
switch (slot) {
case 0x12:
s = "Intel 82454NX PXB#0, Bus#A";
*busnum = pxb[0];
@ -513,19 +531,19 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
/* RCC -- vendor 0x1166 */
case 0x00051166:
s = "RCC HE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00061166:
/* FALLTHROUGH */
case 0x00081166:
s = "RCC host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00091166:
s = "RCC LE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
/* Integrated Micro Solutions -- vendor 0x10e0 */
@ -549,7 +567,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
static void
nexus_pcib_identify(driver_t *driver, device_t parent)
{
pcicfgregs probe;
int bus, slot, func;
u_int8_t hdrtype;
int found = 0;
int pcifunchigh;
@ -557,19 +575,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
if (pci_cfgopen() == 0)
return;
probe.hose = 0;
probe.bus = 0;
bus = 0;
retry:
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
probe.func = 0;
hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1);
for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
func = 0;
hdrtype = nexus_pcib_read_config(0, bus, slot, func,
PCIR_HEADERTYPE, 1);
if (hdrtype & PCIM_MFDEV)
pcifunchigh = 7;
else
pcifunchigh = 0;
for (probe.func = 0;
probe.func <= pcifunchigh;
probe.func++) {
for (func = 0; func <= pcifunchigh; func++) {
/*
* Read the IDs and class from the device.
*/
@ -578,14 +594,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
device_t child;
const char *s;
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
id = nexus_pcib_read_config(0, bus, slot, func,
PCIR_DEVVENDOR, 4);
if (id == -1)
continue;
class = pci_cfgread(&probe, PCIR_CLASS, 1);
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
class = nexus_pcib_read_config(0, bus, slot, func,
PCIR_CLASS, 1);
subclass = nexus_pcib_read_config(0, bus, slot, func,
PCIR_SUBCLASS, 1);
s = nexus_pcib_is_host_bridge(&probe, id,
class, subclass,
s = nexus_pcib_is_host_bridge(bus, slot, func,
id, class, subclass,
&busnum);
if (s) {
/*
@ -601,8 +620,8 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
}
}
}
if (found824xx && probe.bus == 0) {
probe.bus++;
if (found824xx && bus == 0) {
bus++;
goto retry;
}
@ -629,6 +648,17 @@ nexus_pcib_probe(device_t dev)
return ENXIO;
}
static int
nexus_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static device_method_t nexus_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, nexus_pcib_identify),
@ -640,6 +670,7 @@ static device_method_t nexus_pcib_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, nexus_pcib_read_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@ -647,6 +678,11 @@ static device_method_t nexus_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, nexus_pcib_maxslots),
DEVMETHOD(pcib_read_config, nexus_pcib_read_config),
DEVMETHOD(pcib_write_config, nexus_pcib_write_config),
{ 0, 0 }
};

View file

@ -907,6 +907,7 @@ pci/pci_compat.c optional pci compat_oldpci \
pci/pcic_p.c optional pcic pci
pci/pcisupport.c optional pci
pci/pci_if.m optional pci
pci/pcib_if.m optional pci
pci/simos.c optional simos
pci/uhci_pci.c optional uhci
pci/xrpu.c optional xrpu

View file

@ -27,6 +27,7 @@ alpha/alpha/api_up1000.c optional api_up1000
alpha/alpha/atomic.s standard
alpha/alpha/autoconf.c standard
alpha/alpha/busdma_machdep.c standard
alpha/alpha/busspace.c standard
alpha/alpha/clock.c standard
alpha/alpha/clock_if.m standard
alpha/alpha/cpuconf.c standard
@ -83,12 +84,14 @@ alpha/isa/mcclock_isa.c optional isa
alpha/mcbus/mcbus.c optional dec_kn300
alpha/mcbus/mcmem.c optional dec_kn300
alpha/mcbus/mcpcia.c optional dec_kn300
alpha/pci/alphapci_if.m optional pci
alpha/pci/apecs.c optional dec_2100_a50
alpha/pci/apecs.c optional dec_eb64plus
alpha/pci/apecs.c optional dec_1000a
alpha/pci/apecs_pci.c optional dec_2100_a50
alpha/pci/apecs_pci.c optional dec_eb64plus
alpha/pci/apecs_pci.c optional dec_1000a
alpha/pci/bwx.c optional pci
alpha/pci/cia.c optional dec_eb164
alpha/pci/cia.c optional dec_kn20aa
alpha/pci/cia.c optional dec_st550
@ -97,18 +100,17 @@ alpha/pci/cia_pci.c optional dec_eb164
alpha/pci/cia_pci.c optional dec_kn20aa
alpha/pci/cia_pci.c optional dec_st550
alpha/pci/cia_pci.c optional dec_1000a
alpha/pci/dwlpx_pci.c optional dec_kn8ae
alpha/pci/irongate.c optional api_up1000
alpha/pci/irongate_pci.c optional api_up1000
alpha/pci/lca.c optional dec_axppci_33
alpha/pci/lca_pci.c optional dec_axppci_33
alpha/pci/mcpcia_pci.c optional dec_kn300
alpha/pci/pci_eb164_intr.s optional dec_eb164
alpha/pci/pci_eb164_intr.s optional dec_kn20aa
alpha/pci/pci_eb164_intr.s optional dec_st550
alpha/pci/pci_eb64plus_intr.s optional dec_2100_a50
alpha/pci/pci_eb64plus_intr.s optional dec_eb64plus
alpha/pci/pcibus.c optional pci
alpha/pci/swiz.c optional pci
alpha/pci/t2.c optional dec_2100_a500
alpha/pci/t2_pci.c optional dec_2100_a500
alpha/pci/tsunami.c optional dec_st6600

View file

@ -5715,7 +5715,7 @@ ahc_setup_data(struct ahc_softc *ahc, struct ccb_scsiio *csio,
panic("ahc_setup_data - Transfer size "
"larger than can device max");
seg.ds_addr = (bus_addr_t)csio->data_ptr;
seg.ds_addr = (intptr_t)csio->data_ptr;
seg.ds_len = csio->dxfer_len;
ahc_execute_scb(scb, &seg, 1, 0);
}

View file

@ -519,7 +519,7 @@ ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
{
struct ata_pci_softc *sc = device_get_softc(dev);
int masterdev = pci_get_progif(dev) & PCIP_STORAGE_IDE_MASTERDEV;
int unit = (int)device_get_ivars(child);
int unit = (intptr_t)device_get_ivars(child);
int myrid;
if (type == SYS_RES_IOPORT) {

View file

@ -48,6 +48,7 @@
#include <vm/vm_object.h>
#include <machine/clock.h>
#include <machine/md_var.h>
#include <machine/bus.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-disk.h>

View file

@ -43,6 +43,7 @@
#endif
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-disk.h>
#include <machine/bus.h>
#if NPCI > 0

View file

@ -39,6 +39,7 @@
#include <sys/bus.h>
#include <sys/malloc.h>
#include <machine/clock.h>
#include <machine/bus.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-all.h>

View file

@ -160,7 +160,7 @@ atkbdc_configure(void)
#if defined(__i386__)
tag = I386_BUS_SPACE_IO;
#elif defined(__alpha__)
tag = ALPHA_BUS_SPACE_IO;
tag = busspace_isa_io;
#endif
#if notyet

View file

@ -48,6 +48,7 @@
#include <machine/md_var.h>
#include <machine/pc/bios.h>
#include <machine/bus.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/vgareg.h>

View file

@ -216,15 +216,6 @@ static struct ispmdvec mdvec_2200 = {
static int isp_pci_probe (device_t);
static int isp_pci_attach (device_t);
/* This distinguishing define is not right, but it does work */
#ifdef __alpha__
#define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO
#define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM
#else
#define IO_SPACE_MAPPING I386_BUS_SPACE_IO
#define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM
#endif
struct isp_pcisoftc {
struct ispsoftc pci_isp;
device_t pci_dev;

View file

@ -160,7 +160,7 @@ atkbdc_configure(void)
#if defined(__i386__)
tag = I386_BUS_SPACE_IO;
#elif defined(__alpha__)
tag = ALPHA_BUS_SPACE_IO;
tag = busspace_isa_io;
#endif
#if notyet

View file

@ -222,12 +222,12 @@ mdstrategy_malloc(struct bio *bp)
if (secno < sc->nsecp) {
secpp = &sc->secp[secno];
if ((u_int)*secpp > 255) {
if ((uintptr_t)*secpp > 255) {
secp = *secpp;
secval = 0;
} else {
secp = 0;
secval = (u_int) *secpp;
secval = (uintptr_t) *secpp;
}
} else {
secpp = 0;
@ -262,7 +262,7 @@ mdstrategy_malloc(struct bio *bp)
if (secp)
FREE(secp, M_MDSECT);
if (secpp)
*secpp = (u_char *)uc;
*secpp = (u_char *)(uintptr_t)uc;
} else {
if (!secpp) {
MALLOC(secpp, u_char **, (secno + nsec + 1) * sizeof(u_char *), M_MD, M_WAITOK);
@ -276,7 +276,7 @@ mdstrategy_malloc(struct bio *bp)
if (i == DEV_BSIZE) {
if (secp)
FREE(secp, M_MDSECT);
*secpp = (u_char *)uc;
*secpp = (u_char *)(uintptr_t)uc;
} else {
if (!secp)
MALLOC(secp, u_char *, DEV_BSIZE, M_MDSECT, M_WAITOK);

View file

@ -56,6 +56,8 @@
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include "pcib_if.h"
#ifdef __alpha__
#include <machine/rpb.h>
#endif
@ -64,6 +66,8 @@
#include <machine/smp.h>
#endif /* APIC_IO */
static devclass_t pci_devclass;
struct pci_quirk {
u_int32_t devid; /* Vendor/device of the card */
int type;
@ -177,7 +181,7 @@ pci_fixancient(pcicfgregs *cfg)
/* read config data specific to header type 1 device (PCI to PCI bridge) */
static void *
pci_readppb(pcicfgregs *cfg)
pci_readppb(device_t pcib, int b, int s, int f)
{
pcih1cfgregs *p;
@ -187,35 +191,43 @@ pci_readppb(pcicfgregs *cfg)
bzero(p, sizeof *p);
p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_1, 2);
p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_1, 2);
p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_1, 2);
p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_1, 2);
p->seclat = pci_cfgread(cfg, PCIR_SECLAT_1, 1);
p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_1, 1);
p->iobase = PCI_PPBIOBASE (pci_cfgread(cfg, PCIR_IOBASEH_1, 2),
pci_cfgread(cfg, PCIR_IOBASEL_1, 1));
p->iolimit = PCI_PPBIOLIMIT (pci_cfgread(cfg, PCIR_IOLIMITH_1, 2),
pci_cfgread(cfg, PCIR_IOLIMITL_1, 1));
p->iobase = PCI_PPBIOBASE (PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_IOBASEH_1, 2),
PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_IOBASEL_1, 1));
p->iolimit = PCI_PPBIOLIMIT (PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_IOLIMITH_1, 2),
PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_IOLIMITL_1, 1));
p->membase = PCI_PPBMEMBASE (0,
pci_cfgread(cfg, PCIR_MEMBASE_1, 2));
PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_MEMBASE_1, 2));
p->memlimit = PCI_PPBMEMLIMIT (0,
pci_cfgread(cfg, PCIR_MEMLIMIT_1, 2));
PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_MEMLIMIT_1, 2));
p->pmembase = PCI_PPBMEMBASE (
(pci_addr_t)pci_cfgread(cfg, PCIR_PMBASEH_1, 4),
pci_cfgread(cfg, PCIR_PMBASEL_1, 2));
(pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEH_1, 4),
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEL_1, 2));
p->pmemlimit = PCI_PPBMEMLIMIT (
(pci_addr_t)pci_cfgread(cfg, PCIR_PMLIMITH_1, 4),
pci_cfgread(cfg, PCIR_PMLIMITL_1, 2));
(pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_PMLIMITH_1, 4),
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMLIMITL_1, 2));
return (p);
}
/* read config data specific to header type 2 device (PCI to CardBus bridge) */
static void *
pci_readpcb(pcicfgregs *cfg)
pci_readpcb(device_t pcib, int b, int s, int f)
{
pcih2cfgregs *p;
@ -225,60 +237,63 @@ pci_readpcb(pcicfgregs *cfg)
bzero(p, sizeof *p);
p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_2, 2);
p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_2, 2);
p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_2, 2);
p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_2, 2);
p->seclat = pci_cfgread(cfg, PCIR_SECLAT_2, 1);
p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_2, 1);
p->membase0 = pci_cfgread(cfg, PCIR_MEMBASE0_2, 4);
p->memlimit0 = pci_cfgread(cfg, PCIR_MEMLIMIT0_2, 4);
p->membase1 = pci_cfgread(cfg, PCIR_MEMBASE1_2, 4);
p->memlimit1 = pci_cfgread(cfg, PCIR_MEMLIMIT1_2, 4);
p->membase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE0_2, 4);
p->memlimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT0_2, 4);
p->membase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE1_2, 4);
p->memlimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT1_2, 4);
p->iobase0 = pci_cfgread(cfg, PCIR_IOBASE0_2, 4);
p->iolimit0 = pci_cfgread(cfg, PCIR_IOLIMIT0_2, 4);
p->iobase1 = pci_cfgread(cfg, PCIR_IOBASE1_2, 4);
p->iolimit1 = pci_cfgread(cfg, PCIR_IOLIMIT1_2, 4);
p->iobase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE0_2, 4);
p->iolimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT0_2, 4);
p->iobase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE1_2, 4);
p->iolimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT1_2, 4);
p->pccardif = pci_cfgread(cfg, PCIR_PCCARDIF_2, 4);
p->pccardif = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PCCARDIF_2, 4);
return p;
}
/* extract header type specific config data */
static void
pci_hdrtypedata(pcicfgregs *cfg)
pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg)
{
#define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w)
switch (cfg->hdrtype) {
case 0:
cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_0, 2);
cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_0, 2);
cfg->subvendor = REG(PCIR_SUBVEND_0, 2);
cfg->subdevice = REG(PCIR_SUBDEV_0, 2);
cfg->nummaps = PCI_MAXMAPS_0;
break;
case 1:
cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_1, 2);
cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_1, 2);
cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_1, 1);
cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_1, 1);
cfg->subvendor = REG(PCIR_SUBVEND_1, 2);
cfg->subdevice = REG(PCIR_SUBDEV_1, 2);
cfg->secondarybus = REG(PCIR_SECBUS_1, 1);
cfg->subordinatebus = REG(PCIR_SUBBUS_1, 1);
cfg->nummaps = PCI_MAXMAPS_1;
cfg->hdrspec = pci_readppb(cfg);
cfg->hdrspec = pci_readppb(pcib, b, s, f);
break;
case 2:
cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_2, 2);
cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_2, 2);
cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_2, 1);
cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_2, 1);
cfg->subvendor = REG(PCIR_SUBVEND_2, 2);
cfg->subdevice = REG(PCIR_SUBDEV_2, 2);
cfg->secondarybus = REG(PCIR_SECBUS_2, 1);
cfg->subordinatebus = REG(PCIR_SUBBUS_2, 1);
cfg->nummaps = PCI_MAXMAPS_2;
cfg->hdrspec = pci_readpcb(cfg);
cfg->hdrspec = pci_readpcb(pcib, b, s, f);
break;
}
#undef REG
}
/* read configuration header into pcicfgrect structure */
static struct pci_devinfo *
pci_readcfg(pcicfgregs *probe)
pci_read_device(device_t pcib, int b, int s, int f)
{
#define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w)
pcicfgregs *cfg = NULL;
struct pci_devinfo *devlist_entry;
struct devlist *devlist_head;
@ -287,8 +302,7 @@ pci_readcfg(pcicfgregs *probe)
devlist_entry = NULL;
if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) {
if (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVVENDOR, 4) != -1) {
devlist_entry = malloc(sizeof(struct pci_devinfo),
M_DEVBUF, M_WAITOK);
if (devlist_entry == NULL)
@ -297,23 +311,22 @@ pci_readcfg(pcicfgregs *probe)
cfg = &devlist_entry->cfg;
cfg->hose = probe->hose;
cfg->bus = probe->bus;
cfg->slot = probe->slot;
cfg->func = probe->func;
cfg->vendor = pci_cfgread(cfg, PCIR_VENDOR, 2);
cfg->device = pci_cfgread(cfg, PCIR_DEVICE, 2);
cfg->cmdreg = pci_cfgread(cfg, PCIR_COMMAND, 2);
cfg->statreg = pci_cfgread(cfg, PCIR_STATUS, 2);
cfg->baseclass = pci_cfgread(cfg, PCIR_CLASS, 1);
cfg->subclass = pci_cfgread(cfg, PCIR_SUBCLASS, 1);
cfg->progif = pci_cfgread(cfg, PCIR_PROGIF, 1);
cfg->revid = pci_cfgread(cfg, PCIR_REVID, 1);
cfg->hdrtype = pci_cfgread(cfg, PCIR_HEADERTYPE, 1);
cfg->cachelnsz = pci_cfgread(cfg, PCIR_CACHELNSZ, 1);
cfg->lattimer = pci_cfgread(cfg, PCIR_LATTIMER, 1);
cfg->intpin = pci_cfgread(cfg, PCIR_INTPIN, 1);
cfg->intline = pci_cfgread(cfg, PCIR_INTLINE, 1);
cfg->bus = b;
cfg->slot = s;
cfg->func = f;
cfg->vendor = REG(PCIR_VENDOR, 2);
cfg->device = REG(PCIR_DEVICE, 2);
cfg->cmdreg = REG(PCIR_COMMAND, 2);
cfg->statreg = REG(PCIR_STATUS, 2);
cfg->baseclass = REG(PCIR_CLASS, 1);
cfg->subclass = REG(PCIR_SUBCLASS, 1);
cfg->progif = REG(PCIR_PROGIF, 1);
cfg->revid = REG(PCIR_REVID, 1);
cfg->hdrtype = REG(PCIR_HEADERTYPE, 1);
cfg->cachelnsz = REG(PCIR_CACHELNSZ, 1);
cfg->lattimer = REG(PCIR_LATTIMER, 1);
cfg->intpin = REG(PCIR_INTPIN, 1);
cfg->intline = REG(PCIR_INTLINE, 1);
#ifdef __alpha__
alpha_platform_assign_pciintr(cfg);
#endif
@ -346,14 +359,14 @@ pci_readcfg(pcicfgregs *probe)
}
#endif /* APIC_IO */
cfg->mingnt = pci_cfgread(cfg, PCIR_MINGNT, 1);
cfg->maxlat = pci_cfgread(cfg, PCIR_MAXLAT, 1);
cfg->mingnt = REG(PCIR_MINGNT, 1);
cfg->maxlat = REG(PCIR_MAXLAT, 1);
cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0;
cfg->hdrtype &= ~PCIM_MFDEV;
pci_fixancient(cfg);
pci_hdrtypedata(cfg);
pci_hdrtypedata(pcib, b, s, f, cfg);
STAILQ_INSERT_TAIL(devlist_head, devlist_entry, pci_links);
@ -376,6 +389,7 @@ pci_readcfg(pcicfgregs *probe)
pci_generation++;
}
return (devlist_entry);
#undef REG
}
#if 0
@ -541,6 +555,7 @@ pci_devlist_get_parent(pcicfgregs *cfg)
static int
pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
device_t pci, pcib;
struct pci_io *io;
const char *name;
int error;
@ -782,17 +797,30 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case PCIOCREAD:
io = (struct pci_io *)data;
switch(io->pi_width) {
pcicfgregs probe;
case 4:
case 2:
case 1:
probe.hose = -1;
probe.bus = io->pi_sel.pc_bus;
probe.slot = io->pi_sel.pc_dev;
probe.func = io->pi_sel.pc_func;
io->pi_data = pci_cfgread(&probe,
io->pi_reg, io->pi_width);
error = 0;
/*
* Assume that the user-level bus number is
* actually the pciN instance number. We map
* from that to the real pcib+bus combination.
*/
pci = devclass_get_device(pci_devclass,
io->pi_sel.pc_bus);
if (pci) {
int b = pcib_get_bus(pci);
pcib = device_get_parent(pci);
io->pi_data =
PCIB_READ_CONFIG(pcib,
b,
io->pi_sel.pc_dev,
io->pi_sel.pc_func,
io->pi_reg,
io->pi_width);
error = 0;
} else {
error = ENODEV;
}
break;
default:
error = ENODEV;
@ -803,17 +831,30 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case PCIOCWRITE:
io = (struct pci_io *)data;
switch(io->pi_width) {
pcicfgregs probe;
case 4:
case 2:
case 1:
probe.hose = -1;
probe.bus = io->pi_sel.pc_bus;
probe.slot = io->pi_sel.pc_dev;
probe.func = io->pi_sel.pc_func;
pci_cfgwrite(&probe,
io->pi_reg, io->pi_data, io->pi_width);
error = 0;
/*
* Assume that the user-level bus number is
* actually the pciN instance number. We map
* from that to the real pcib+bus combination.
*/
pci = devclass_get_device(pci_devclass,
io->pi_sel.pc_bus);
if (pci) {
int b = pcib_get_bus(pci);
pcib = device_get_parent(pci);
PCIB_WRITE_CONFIG(pcib,
b,
io->pi_sel.pc_dev,
io->pi_sel.pc_func,
io->pi_reg,
io->pi_data,
io->pi_width);
error = 0;
} else {
error = ENODEV;
}
break;
default:
error = ENODEV;
@ -850,7 +891,6 @@ static struct cdevsw pcicdev = {
#include "pci_if.h"
/*
* New style pci driver. Parent device is either a pci-host-bridge or a
* pci-pci-bridge. Both kinds are represented by instances of pcib.
@ -882,15 +922,17 @@ pci_print_verbose(struct pci_devinfo *dinfo)
}
static int
pci_porten(pcicfgregs *cfg)
pci_porten(device_t pcib, int b, int s, int f)
{
return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0);
return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2)
& PCIM_CMD_PORTEN) != 0;
}
static int
pci_memen(pcicfgregs *cfg)
pci_memen(device_t pcib, int b, int s, int f)
{
return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0);
return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2)
& PCIM_CMD_MEMEN) != 0;
}
/*
@ -898,10 +940,9 @@ pci_memen(pcicfgregs *cfg)
* register is a 32bit map register or 2 if it is a 64bit register.
*/
static int
pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
pci_add_map(device_t pcib, int b, int s, int f, int reg,
struct resource_list *rl)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
struct resource_list *rl = &dinfo->resources;
u_int32_t map;
u_int64_t base;
u_int8_t ln2size;
@ -910,14 +951,14 @@ pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
int type;
map = pci_cfgread(cfg, reg, 4);
map = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4);
if (map == 0 || map == 0xffffffff)
return 1; /* skip invalid entry */
pci_cfgwrite(cfg, reg, 0xffffffff, 4);
testval = pci_cfgread(cfg, reg, 4);
pci_cfgwrite(cfg, reg, map, 4);
PCIB_WRITE_CONFIG(pcib, b, s, f, reg, 0xffffffff, 4);
testval = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4);
PCIB_WRITE_CONFIG(pcib, b, s, f, reg, map, 4);
base = pci_mapbase(map);
if (pci_maptype(map) & PCI_MAPMEM)
@ -928,72 +969,24 @@ pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
ln2range = pci_maprange(testval);
if (ln2range == 64) {
/* Read the other half of a 64bit map register */
base |= (u_int64_t) pci_cfgread(cfg, reg + 4, 4) << 32;
base |= (u_int64_t) PCIB_READ_CONFIG(pcib, b, s, f, reg + 4, 4) << 32;
}
#ifdef __alpha__
/*
* XXX: encode hose number in the base addr,
* This will go away once the bus_space functions
* can deal with multiple hoses
*/
if (cfg->hose) {
u_int32_t mask, shift, maxh;
switch (hwrpb->rpb_type) {
case ST_DEC_4100:
mask = 0xc0000000;
shift = 30;
maxh = 4; /* not a hose. MCPCIA instance # */
break;
case ST_DEC_21000:
mask = 0xf8000000;
shift = 27;
maxh = 32;
break;
case ST_DEC_6600:
mask = 0x80000000;
shift = 31;
maxh = 2;
break;
default:
mask = 0;
shift = 0;
maxh = 0;
break;
}
if (base & mask) {
printf("base addr = 0x%llx\n", (long long) base);
printf("mask addr = 0x%lx\n", (long) mask);
printf("hacked addr = 0x%llx\n", (long long)
(base | ((u_int64_t)cfg->hose << shift)));
panic("hose encoding hack would clobber base addr");
/* NOTREACHED */
}
if (cfg->hose >= maxh) {
panic("Hose %d - can only encode %d hose(s)",
cfg->hose, maxh);
/* NOTREACHED */
}
base |= ((u_int64_t)cfg->hose << shift);
}
#endif
if (bootverbose) {
printf("\tmap[%02x]: type %x, range %2d, base %08x, size %2d",
reg, pci_maptype(map), ln2range,
(unsigned int) base, ln2size);
if (type == SYS_RES_IOPORT && !pci_porten(cfg))
if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f))
printf(", port disabled\n");
else if (type == SYS_RES_MEMORY && !pci_memen(cfg))
else if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f))
printf(", memory disabled\n");
else
printf(", enabled\n");
}
if (type == SYS_RES_IOPORT && !pci_porten(cfg))
if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f))
return 1;
if (type == SYS_RES_MEMORY && !pci_memen(cfg))
if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f))
return 1;
resource_list_add(rl, type, reg,
@ -1004,21 +997,22 @@ pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
}
static void
pci_add_resources(device_t dev, pcicfgregs* cfg)
pci_add_resources(device_t pcib, int b, int s, int f, device_t dev)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
pcicfgregs *cfg = &dinfo->cfg;
struct resource_list *rl = &dinfo->resources;
struct pci_quirk *q;
int i;
for (i = 0; i < cfg->nummaps;) {
i += pci_add_map(dev, cfg, PCIR_MAPS + i*4);
i += pci_add_map(pcib, b, s, f, PCIR_MAPS + i*4, rl);
}
for (q = &pci_quirks[0]; q->devid; q++) {
if (q->devid == ((cfg->device << 16) | cfg->vendor)
&& q->type == PCI_QUIRK_MAP_REG)
pci_add_map(dev, cfg, q->arg1);
pci_add_map(pcib, b, s, f, q->arg1, rl);
}
if (cfg->intpin > 0 && cfg->intline != 255)
@ -1029,26 +1023,17 @@ pci_add_resources(device_t dev, pcicfgregs* cfg)
static void
pci_add_children(device_t dev, int busno)
{
pcicfgregs probe;
device_t pcib = device_get_parent(dev);
int maxslots;
int s, f;
#ifdef SIMOS
#undef PCI_SLOTMAX
#define PCI_SLOTMAX 0
#endif
bzero(&probe, sizeof probe);
#ifdef __alpha__
probe.hose = pcib_get_hose(dev);
#endif
#ifdef __i386__
probe.hose = 0;
#endif
probe.bus = busno;
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
maxslots = PCIB_MAXSLOTS(pcib);
for (s = 0; s <= maxslots; s++) {
int pcifunchigh = 0;
for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
struct pci_devinfo *dinfo = pci_readcfg(&probe);
for (f = 0; f <= pcifunchigh; f++) {
struct pci_devinfo *dinfo =
pci_read_device(pcib, busno, s, f);
if (dinfo != NULL) {
if (dinfo->cfg.mfdev)
pcifunchigh = 7;
@ -1056,19 +1041,31 @@ pci_add_children(device_t dev, int busno)
pci_print_verbose(dinfo);
dinfo->cfg.dev = device_add_child(dev, NULL, -1);
device_set_ivars(dinfo->cfg.dev, dinfo);
pci_add_resources(dinfo->cfg.dev, &dinfo->cfg);
pci_add_resources(pcib, busno, s, f,
dinfo->cfg.dev);
}
}
}
}
static int
pci_new_probe(device_t dev)
pci_probe(device_t dev)
{
static int once;
device_set_desc(dev, "PCI bus");
pci_add_children(dev, device_get_unit(dev));
if (bootverbose)
device_printf(dev, "physical bus=%d\n", pcib_get_bus(dev));
/*
* Since there can be multiple independantly numbered PCI
* busses on some large alpha systems, we can't use the unit
* number to decide what bus we are probing. We ask the parent
* pcib what our bus number is.
*/
pci_add_children(dev, pcib_get_bus(dev));
if (!once) {
make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644, "pci");
once++;
@ -1227,12 +1224,6 @@ pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case PCI_IVAR_SUBORDINATEBUS:
*result = cfg->subordinatebus;
break;
case PCI_IVAR_HOSE:
/*
* Pass up to parent bridge.
*/
*result = pcib_get_hose(dev);
break;
default:
return ENOENT;
}
@ -1340,7 +1331,10 @@ pci_read_config_method(device_t dev, device_t child, int reg, int width)
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
return pci_cfgread(cfg, reg, width);
return PCIB_READ_CONFIG(device_get_parent(dev),
cfg->bus, cfg->slot, cfg->func,
reg, width);
}
static void
@ -1349,7 +1343,10 @@ pci_write_config_method(device_t dev, device_t child, int reg,
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
pci_cfgwrite(cfg, reg, val, width);
PCIB_WRITE_CONFIG(device_get_parent(dev),
cfg->bus, cfg->slot, cfg->func,
reg, val, width);
}
static int
@ -1369,7 +1366,7 @@ pci_modevent(module_t mod, int what, void *arg)
static device_method_t pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pci_new_probe),
DEVMETHOD(device_probe, pci_probe),
DEVMETHOD(device_attach, bus_generic_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),

71
sys/dev/pci/pcib_if.m Normal file
View file

@ -0,0 +1,71 @@
#
# Copyright (c) 2000 Doug Rabson
# 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$
#
#include <sys/bus.h>
INTERFACE pcib;
#
# Return the number of slots on the attached PCI bus.
#
METHOD int maxslots {
device_t dev;
};
#
# Read configuration space on the PCI bus. The bus, slot and func
# arguments determine the device which is being read and the reg
# argument is a byte offset into configuration space for that
# device. The width argument (which should be 1, 2 or 4) specifies how
# many byte of configuration space to read from that offset.
#
METHOD u_int32_t read_config {
device_t dev;
int bus;
int slot;
int func;
int reg;
int width;
};
#
# Write configuration space on the PCI bus. The bus, slot and func
# arguments determine the device which is being written and the reg
# argument is a byte offset into configuration space for that
# device. The value field is written to the configuration space, with
# the number of bytes written depending on the width argument.
#
METHOD void write_config {
device_t dev;
int bus;
int slot;
int func;
int reg;
u_int32_t value;
int width;
};

View file

@ -82,7 +82,6 @@ typedef struct pcicfg {
u_int8_t mfdev; /* multi-function device (from hdrtype reg) */
u_int8_t nummaps; /* actual number of PCI maps used */
u_int8_t hose; /* hose which bus is attached to */
u_int8_t bus; /* config space bus address */
u_int8_t slot; /* config space slot address */
u_int8_t func; /* config space function number */
@ -156,6 +155,7 @@ const char *pci_chip_match(struct device *dev);
int pci_cfgread (pcicfgregs *cfg, int reg, int bytes);
void pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes);
#ifdef __alpha__
vm_offset_t pci_cvt_to_dense (vm_offset_t);
vm_offset_t pci_cvt_to_bwx (vm_offset_t);
@ -192,7 +192,6 @@ enum pci_device_ivars {
PCI_IVAR_FUNCTION,
PCI_IVAR_SECONDARYBUS,
PCI_IVAR_SUBORDINATEBUS,
PCI_IVAR_HOSE,
};
/*
@ -229,7 +228,6 @@ PCI_ACCESSOR(slot, SLOT, u_int8_t)
PCI_ACCESSOR(function, FUNCTION, u_int8_t)
PCI_ACCESSOR(secondarybus, SECONDARYBUS, u_int8_t)
PCI_ACCESSOR(subordinatebus, SUBORDINATEBUS, u_int8_t)
PCI_ACCESSOR(hose, HOSE, u_int32_t)
static __inline u_int32_t
pci_read_config(device_t dev, int reg, int width)
@ -249,7 +247,7 @@ pci_write_config(device_t dev, int reg, u_int32_t val, int width)
/*typedef enum pci_device_ivars pcib_device_ivars;*/
enum pcib_device_ivars {
PCIB_IVAR_HOSE,
PCIB_IVAR_BUS
};
#define PCIB_ACCESSOR(A, B, T) \
@ -267,7 +265,7 @@ static __inline void pcib_set_ ## A(device_t dev, T t) \
BUS_WRITE_IVAR(device_get_parent(dev), dev, PCIB_IVAR_ ## B, v); \
}
PCIB_ACCESSOR(hose, HOSE, u_int32_t)
PCIB_ACCESSOR(bus, BUS, u_int32_t)
#endif

View file

@ -34,6 +34,7 @@
#include <sys/kernel.h>
#include <machine/console.h>
#include <machine/bus.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/vgareg.h>

View file

@ -34,6 +34,7 @@
#include <sys/kernel.h>
#include <machine/console.h>
#include <machine/bus.h>
#include <dev/fb/fbreg.h>
#include <dev/fb/vgareg.h>

View file

@ -34,6 +34,7 @@
#include <machine/console.h>
#include <machine/md_var.h>
#include <machine/bus.h>
#include <dev/fb/fbreg.h>
#include <dev/syscons/syscons.h>

View file

@ -1505,7 +1505,7 @@ static int ti_attach(dev)
rid = TI_PCI_LOMEM;
sc->ti_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
0, ~0, 1, RF_ACTIVE);
0, ~0, 1, RF_ACTIVE|PCI_RF_DENSE);
if (sc->ti_res == NULL) {
printf ("ti%d: couldn't map memory\n", unit);
@ -1517,22 +1517,6 @@ static int ti_attach(dev)
sc->ti_bhandle = rman_get_bushandle(sc->ti_res);
sc->ti_vhandle = (vm_offset_t)rman_get_virtual(sc->ti_res);
/*
* XXX FIXME: rman_get_virtual() on the alpha is currently
* broken and returns a physical address instead of a kernel
* virtual address. Consequently, we need to do a little
* extra mangling of the vhandle on the alpha. This should
* eventually be fixed! The whole idea here is to get rid
* of platform dependencies.
*/
#ifdef __alpha__
if (pci_cvt_to_bwx(sc->ti_vhandle))
sc->ti_vhandle = pci_cvt_to_bwx(sc->ti_vhandle);
else
sc->ti_vhandle = pci_cvt_to_dense(sc->ti_vhandle);
sc->ti_vhandle = ALPHA_PHYS_TO_K0SEG(sc->ti_vhandle);
#endif
/* Allocate interrupt */
rid = 0;

View file

@ -41,35 +41,49 @@
#include <machine/segments.h>
#include <machine/pc/bios.h>
#include "pcib_if.h"
static int cfgmech;
static int devmax;
static int usebios;
static int pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcibios_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcibios_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcibios_cfgopen(void);
static int pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcireg_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcireg_cfgopen(void);
/* read configuration space register */
int
pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
static int
nexus_pcib_maxslots(device_t dev)
{
return 31;
}
static u_int32_t
nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
int reg, int bytes)
{
return(usebios ?
pcibios_cfgread(cfg, reg, bytes) :
pcireg_cfgread(cfg, reg, bytes));
pcibios_cfgread(bus, slot, func, reg, bytes) :
pcireg_cfgread(bus, slot, func, reg, bytes));
}
/* write configuration space register */
void
pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
static void
nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
int reg, u_int32_t data, int bytes)
{
return(usebios ?
pcibios_cfgwrite(cfg, reg, data, bytes) :
pcireg_cfgwrite(cfg, reg, data, bytes));
pcibios_cfgwrite(bus, slot, func, reg, data, bytes) :
pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
}
/* initialise access to PCI configuration space */
@ -89,7 +103,7 @@ pci_cfgopen(void)
/* config space access using BIOS functions */
static int
pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
{
struct bios_regs args;
u_int mask;
@ -110,7 +124,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
default:
return(-1);
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
/* check call results? */
@ -118,7 +132,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
struct bios_regs args;
@ -135,7 +149,7 @@ pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
default:
return;
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.ecx = data;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
@ -200,12 +214,12 @@ pci_cfgdisable(void)
}
static int
pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
{
int data = -1;
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
@ -225,11 +239,11 @@ pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
case 1:
@ -373,7 +387,7 @@ pcireg_cfgopen(void)
static devclass_t pcib_devclass;
static const char *
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
nexus_pcib_is_host_bridge(int bus, int slot, int func,
u_int32_t id, u_int8_t class, u_int8_t subclass,
u_int8_t *busnum)
{
@ -386,8 +400,8 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
case 0x12258086:
s = "Intel 824?? host to PCI bridge";
/* XXX This is a guess */
/* *busnum = pci_cfgread(cfg, 0x41, 1); */
*busnum = cfg->bus;
/* *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x41, 1); */
*busnum = bus;
break;
case 0x71208086:
s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
@ -421,7 +435,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
break;
case 0x84c48086:
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x4a, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x4a, 1);
break;
case 0x84ca8086:
/*
@ -435,13 +449,17 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
* Since the MIOC doesn't have a pci bus attached, we
* pretend it wasn't there.
*/
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
pxb[0] = nexus_pcib_read_config(0, bus, slot, func,
0xd0, 1); /* BUSNO[0] */
pxb[1] = nexus_pcib_read_config(0, bus, slot, func,
0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = nexus_pcib_read_config(0, bus, slot, func,
0xd3, 1); /* BUSNO[1] */
pxb[3] = nexus_pcib_read_config(0, bus, slot, func,
0xd4, 1) + 1; /* SUBA[1]+1 */
return NULL;
case 0x84cb8086:
switch (cfg->slot) {
switch (slot) {
case 0x12:
s = "Intel 82454NX PXB#0, Bus#A";
*busnum = pxb[0];
@ -513,19 +531,19 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
/* RCC -- vendor 0x1166 */
case 0x00051166:
s = "RCC HE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00061166:
/* FALLTHROUGH */
case 0x00081166:
s = "RCC host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00091166:
s = "RCC LE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
/* Integrated Micro Solutions -- vendor 0x10e0 */
@ -549,7 +567,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
static void
nexus_pcib_identify(driver_t *driver, device_t parent)
{
pcicfgregs probe;
int bus, slot, func;
u_int8_t hdrtype;
int found = 0;
int pcifunchigh;
@ -557,19 +575,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
if (pci_cfgopen() == 0)
return;
probe.hose = 0;
probe.bus = 0;
bus = 0;
retry:
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
probe.func = 0;
hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1);
for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
func = 0;
hdrtype = nexus_pcib_read_config(0, bus, slot, func,
PCIR_HEADERTYPE, 1);
if (hdrtype & PCIM_MFDEV)
pcifunchigh = 7;
else
pcifunchigh = 0;
for (probe.func = 0;
probe.func <= pcifunchigh;
probe.func++) {
for (func = 0; func <= pcifunchigh; func++) {
/*
* Read the IDs and class from the device.
*/
@ -578,14 +594,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
device_t child;
const char *s;
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
id = nexus_pcib_read_config(0, bus, slot, func,
PCIR_DEVVENDOR, 4);
if (id == -1)
continue;
class = pci_cfgread(&probe, PCIR_CLASS, 1);
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
class = nexus_pcib_read_config(0, bus, slot, func,
PCIR_CLASS, 1);
subclass = nexus_pcib_read_config(0, bus, slot, func,
PCIR_SUBCLASS, 1);
s = nexus_pcib_is_host_bridge(&probe, id,
class, subclass,
s = nexus_pcib_is_host_bridge(bus, slot, func,
id, class, subclass,
&busnum);
if (s) {
/*
@ -601,8 +620,8 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
}
}
}
if (found824xx && probe.bus == 0) {
probe.bus++;
if (found824xx && bus == 0) {
bus++;
goto retry;
}
@ -629,6 +648,17 @@ nexus_pcib_probe(device_t dev)
return ENXIO;
}
static int
nexus_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static device_method_t nexus_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, nexus_pcib_identify),
@ -640,6 +670,7 @@ static device_method_t nexus_pcib_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, nexus_pcib_read_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@ -647,6 +678,11 @@ static device_method_t nexus_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, nexus_pcib_maxslots),
DEVMETHOD(pcib_read_config, nexus_pcib_read_config),
DEVMETHOD(pcib_write_config, nexus_pcib_write_config),
{ 0, 0 }
};

View file

@ -41,35 +41,49 @@
#include <machine/segments.h>
#include <machine/pc/bios.h>
#include "pcib_if.h"
static int cfgmech;
static int devmax;
static int usebios;
static int pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcibios_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcibios_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcibios_cfgopen(void);
static int pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcireg_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcireg_cfgopen(void);
/* read configuration space register */
int
pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
static int
nexus_pcib_maxslots(device_t dev)
{
return 31;
}
static u_int32_t
nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
int reg, int bytes)
{
return(usebios ?
pcibios_cfgread(cfg, reg, bytes) :
pcireg_cfgread(cfg, reg, bytes));
pcibios_cfgread(bus, slot, func, reg, bytes) :
pcireg_cfgread(bus, slot, func, reg, bytes));
}
/* write configuration space register */
void
pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
static void
nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
int reg, u_int32_t data, int bytes)
{
return(usebios ?
pcibios_cfgwrite(cfg, reg, data, bytes) :
pcireg_cfgwrite(cfg, reg, data, bytes));
pcibios_cfgwrite(bus, slot, func, reg, data, bytes) :
pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
}
/* initialise access to PCI configuration space */
@ -89,7 +103,7 @@ pci_cfgopen(void)
/* config space access using BIOS functions */
static int
pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
{
struct bios_regs args;
u_int mask;
@ -110,7 +124,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
default:
return(-1);
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
/* check call results? */
@ -118,7 +132,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
struct bios_regs args;
@ -135,7 +149,7 @@ pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
default:
return;
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.ecx = data;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
@ -200,12 +214,12 @@ pci_cfgdisable(void)
}
static int
pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
{
int data = -1;
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
@ -225,11 +239,11 @@ pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
case 1:
@ -373,7 +387,7 @@ pcireg_cfgopen(void)
static devclass_t pcib_devclass;
static const char *
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
nexus_pcib_is_host_bridge(int bus, int slot, int func,
u_int32_t id, u_int8_t class, u_int8_t subclass,
u_int8_t *busnum)
{
@ -386,8 +400,8 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
case 0x12258086:
s = "Intel 824?? host to PCI bridge";
/* XXX This is a guess */
/* *busnum = pci_cfgread(cfg, 0x41, 1); */
*busnum = cfg->bus;
/* *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x41, 1); */
*busnum = bus;
break;
case 0x71208086:
s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
@ -421,7 +435,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
break;
case 0x84c48086:
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x4a, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x4a, 1);
break;
case 0x84ca8086:
/*
@ -435,13 +449,17 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
* Since the MIOC doesn't have a pci bus attached, we
* pretend it wasn't there.
*/
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
pxb[0] = nexus_pcib_read_config(0, bus, slot, func,
0xd0, 1); /* BUSNO[0] */
pxb[1] = nexus_pcib_read_config(0, bus, slot, func,
0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = nexus_pcib_read_config(0, bus, slot, func,
0xd3, 1); /* BUSNO[1] */
pxb[3] = nexus_pcib_read_config(0, bus, slot, func,
0xd4, 1) + 1; /* SUBA[1]+1 */
return NULL;
case 0x84cb8086:
switch (cfg->slot) {
switch (slot) {
case 0x12:
s = "Intel 82454NX PXB#0, Bus#A";
*busnum = pxb[0];
@ -513,19 +531,19 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
/* RCC -- vendor 0x1166 */
case 0x00051166:
s = "RCC HE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00061166:
/* FALLTHROUGH */
case 0x00081166:
s = "RCC host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00091166:
s = "RCC LE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
/* Integrated Micro Solutions -- vendor 0x10e0 */
@ -549,7 +567,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
static void
nexus_pcib_identify(driver_t *driver, device_t parent)
{
pcicfgregs probe;
int bus, slot, func;
u_int8_t hdrtype;
int found = 0;
int pcifunchigh;
@ -557,19 +575,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
if (pci_cfgopen() == 0)
return;
probe.hose = 0;
probe.bus = 0;
bus = 0;
retry:
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
probe.func = 0;
hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1);
for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
func = 0;
hdrtype = nexus_pcib_read_config(0, bus, slot, func,
PCIR_HEADERTYPE, 1);
if (hdrtype & PCIM_MFDEV)
pcifunchigh = 7;
else
pcifunchigh = 0;
for (probe.func = 0;
probe.func <= pcifunchigh;
probe.func++) {
for (func = 0; func <= pcifunchigh; func++) {
/*
* Read the IDs and class from the device.
*/
@ -578,14 +594,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
device_t child;
const char *s;
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
id = nexus_pcib_read_config(0, bus, slot, func,
PCIR_DEVVENDOR, 4);
if (id == -1)
continue;
class = pci_cfgread(&probe, PCIR_CLASS, 1);
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
class = nexus_pcib_read_config(0, bus, slot, func,
PCIR_CLASS, 1);
subclass = nexus_pcib_read_config(0, bus, slot, func,
PCIR_SUBCLASS, 1);
s = nexus_pcib_is_host_bridge(&probe, id,
class, subclass,
s = nexus_pcib_is_host_bridge(bus, slot, func,
id, class, subclass,
&busnum);
if (s) {
/*
@ -601,8 +620,8 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
}
}
}
if (found824xx && probe.bus == 0) {
probe.bus++;
if (found824xx && bus == 0) {
bus++;
goto retry;
}
@ -629,6 +648,17 @@ nexus_pcib_probe(device_t dev)
return ENXIO;
}
static int
nexus_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static device_method_t nexus_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, nexus_pcib_identify),
@ -640,6 +670,7 @@ static device_method_t nexus_pcib_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, nexus_pcib_read_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@ -647,6 +678,11 @@ static device_method_t nexus_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, nexus_pcib_maxslots),
DEVMETHOD(pcib_read_config, nexus_pcib_read_config),
DEVMETHOD(pcib_write_config, nexus_pcib_write_config),
{ 0, 0 }
};

View file

@ -41,35 +41,49 @@
#include <machine/segments.h>
#include <machine/pc/bios.h>
#include "pcib_if.h"
static int cfgmech;
static int devmax;
static int usebios;
static int pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcibios_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcibios_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcibios_cfgopen(void);
static int pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcireg_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcireg_cfgopen(void);
/* read configuration space register */
int
pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
static int
nexus_pcib_maxslots(device_t dev)
{
return 31;
}
static u_int32_t
nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
int reg, int bytes)
{
return(usebios ?
pcibios_cfgread(cfg, reg, bytes) :
pcireg_cfgread(cfg, reg, bytes));
pcibios_cfgread(bus, slot, func, reg, bytes) :
pcireg_cfgread(bus, slot, func, reg, bytes));
}
/* write configuration space register */
void
pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
static void
nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
int reg, u_int32_t data, int bytes)
{
return(usebios ?
pcibios_cfgwrite(cfg, reg, data, bytes) :
pcireg_cfgwrite(cfg, reg, data, bytes));
pcibios_cfgwrite(bus, slot, func, reg, data, bytes) :
pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
}
/* initialise access to PCI configuration space */
@ -89,7 +103,7 @@ pci_cfgopen(void)
/* config space access using BIOS functions */
static int
pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
{
struct bios_regs args;
u_int mask;
@ -110,7 +124,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
default:
return(-1);
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
/* check call results? */
@ -118,7 +132,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
struct bios_regs args;
@ -135,7 +149,7 @@ pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
default:
return;
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.ecx = data;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
@ -200,12 +214,12 @@ pci_cfgdisable(void)
}
static int
pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
{
int data = -1;
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
@ -225,11 +239,11 @@ pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
case 1:
@ -373,7 +387,7 @@ pcireg_cfgopen(void)
static devclass_t pcib_devclass;
static const char *
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
nexus_pcib_is_host_bridge(int bus, int slot, int func,
u_int32_t id, u_int8_t class, u_int8_t subclass,
u_int8_t *busnum)
{
@ -386,8 +400,8 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
case 0x12258086:
s = "Intel 824?? host to PCI bridge";
/* XXX This is a guess */
/* *busnum = pci_cfgread(cfg, 0x41, 1); */
*busnum = cfg->bus;
/* *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x41, 1); */
*busnum = bus;
break;
case 0x71208086:
s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
@ -421,7 +435,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
break;
case 0x84c48086:
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x4a, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x4a, 1);
break;
case 0x84ca8086:
/*
@ -435,13 +449,17 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
* Since the MIOC doesn't have a pci bus attached, we
* pretend it wasn't there.
*/
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
pxb[0] = nexus_pcib_read_config(0, bus, slot, func,
0xd0, 1); /* BUSNO[0] */
pxb[1] = nexus_pcib_read_config(0, bus, slot, func,
0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = nexus_pcib_read_config(0, bus, slot, func,
0xd3, 1); /* BUSNO[1] */
pxb[3] = nexus_pcib_read_config(0, bus, slot, func,
0xd4, 1) + 1; /* SUBA[1]+1 */
return NULL;
case 0x84cb8086:
switch (cfg->slot) {
switch (slot) {
case 0x12:
s = "Intel 82454NX PXB#0, Bus#A";
*busnum = pxb[0];
@ -513,19 +531,19 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
/* RCC -- vendor 0x1166 */
case 0x00051166:
s = "RCC HE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00061166:
/* FALLTHROUGH */
case 0x00081166:
s = "RCC host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00091166:
s = "RCC LE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
/* Integrated Micro Solutions -- vendor 0x10e0 */
@ -549,7 +567,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
static void
nexus_pcib_identify(driver_t *driver, device_t parent)
{
pcicfgregs probe;
int bus, slot, func;
u_int8_t hdrtype;
int found = 0;
int pcifunchigh;
@ -557,19 +575,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
if (pci_cfgopen() == 0)
return;
probe.hose = 0;
probe.bus = 0;
bus = 0;
retry:
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
probe.func = 0;
hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1);
for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
func = 0;
hdrtype = nexus_pcib_read_config(0, bus, slot, func,
PCIR_HEADERTYPE, 1);
if (hdrtype & PCIM_MFDEV)
pcifunchigh = 7;
else
pcifunchigh = 0;
for (probe.func = 0;
probe.func <= pcifunchigh;
probe.func++) {
for (func = 0; func <= pcifunchigh; func++) {
/*
* Read the IDs and class from the device.
*/
@ -578,14 +594,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
device_t child;
const char *s;
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
id = nexus_pcib_read_config(0, bus, slot, func,
PCIR_DEVVENDOR, 4);
if (id == -1)
continue;
class = pci_cfgread(&probe, PCIR_CLASS, 1);
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
class = nexus_pcib_read_config(0, bus, slot, func,
PCIR_CLASS, 1);
subclass = nexus_pcib_read_config(0, bus, slot, func,
PCIR_SUBCLASS, 1);
s = nexus_pcib_is_host_bridge(&probe, id,
class, subclass,
s = nexus_pcib_is_host_bridge(bus, slot, func,
id, class, subclass,
&busnum);
if (s) {
/*
@ -601,8 +620,8 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
}
}
}
if (found824xx && probe.bus == 0) {
probe.bus++;
if (found824xx && bus == 0) {
bus++;
goto retry;
}
@ -629,6 +648,17 @@ nexus_pcib_probe(device_t dev)
return ENXIO;
}
static int
nexus_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static device_method_t nexus_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, nexus_pcib_identify),
@ -640,6 +670,7 @@ static device_method_t nexus_pcib_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, nexus_pcib_read_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@ -647,6 +678,11 @@ static device_method_t nexus_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, nexus_pcib_maxslots),
DEVMETHOD(pcib_read_config, nexus_pcib_read_config),
DEVMETHOD(pcib_write_config, nexus_pcib_write_config),
{ 0, 0 }
};

View file

@ -41,35 +41,49 @@
#include <machine/segments.h>
#include <machine/pc/bios.h>
#include "pcib_if.h"
static int cfgmech;
static int devmax;
static int usebios;
static int pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcibios_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcibios_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcibios_cfgopen(void);
static int pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes);
static void pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes);
static int pcireg_cfgread(int bus, int slot, int func, int reg,
int bytes);
static void pcireg_cfgwrite(int bus, int slot, int func, int reg,
int data, int bytes);
static int pcireg_cfgopen(void);
/* read configuration space register */
int
pci_cfgread(pcicfgregs *cfg, int reg, int bytes)
static int
nexus_pcib_maxslots(device_t dev)
{
return 31;
}
static u_int32_t
nexus_pcib_read_config(device_t dev, int bus, int slot, int func,
int reg, int bytes)
{
return(usebios ?
pcibios_cfgread(cfg, reg, bytes) :
pcireg_cfgread(cfg, reg, bytes));
pcibios_cfgread(bus, slot, func, reg, bytes) :
pcireg_cfgread(bus, slot, func, reg, bytes));
}
/* write configuration space register */
void
pci_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
static void
nexus_pcib_write_config(device_t dev, int bus, int slot, int func,
int reg, u_int32_t data, int bytes)
{
return(usebios ?
pcibios_cfgwrite(cfg, reg, data, bytes) :
pcireg_cfgwrite(cfg, reg, data, bytes));
pcibios_cfgwrite(bus, slot, func, reg, data, bytes) :
pcireg_cfgwrite(bus, slot, func, reg, data, bytes));
}
/* initialise access to PCI configuration space */
@ -89,7 +103,7 @@ pci_cfgopen(void)
/* config space access using BIOS functions */
static int
pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcibios_cfgread(int bus, int slot, int func, int reg, int bytes)
{
struct bios_regs args;
u_int mask;
@ -110,7 +124,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
default:
return(-1);
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
/* check call results? */
@ -118,7 +132,7 @@ pcibios_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcibios_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
struct bios_regs args;
@ -135,7 +149,7 @@ pcibios_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
default:
return;
}
args.ebx = (cfg->bus << 8) | (cfg->slot << 3) | (cfg->func);
args.ebx = (bus << 8) | (slot << 3) | func;
args.ecx = data;
args.edi = reg;
bios32(&args, PCIbios.ventry, GSEL(GCODE_SEL, SEL_KPL));
@ -200,12 +214,12 @@ pci_cfgdisable(void)
}
static int
pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
{
int data = -1;
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
@ -225,11 +239,11 @@ pcireg_cfgread(pcicfgregs *cfg, int reg, int bytes)
}
static void
pcireg_cfgwrite(pcicfgregs *cfg, int reg, int data, int bytes)
pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
{
int port;
port = pci_cfgenable(cfg->bus, cfg->slot, cfg->func, reg, bytes);
port = pci_cfgenable(bus, slot, func, reg, bytes);
if (port != 0) {
switch (bytes) {
case 1:
@ -373,7 +387,7 @@ pcireg_cfgopen(void)
static devclass_t pcib_devclass;
static const char *
nexus_pcib_is_host_bridge(pcicfgregs *cfg,
nexus_pcib_is_host_bridge(int bus, int slot, int func,
u_int32_t id, u_int8_t class, u_int8_t subclass,
u_int8_t *busnum)
{
@ -386,8 +400,8 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
case 0x12258086:
s = "Intel 824?? host to PCI bridge";
/* XXX This is a guess */
/* *busnum = pci_cfgread(cfg, 0x41, 1); */
*busnum = cfg->bus;
/* *busnum = nexus_pcib_read_config(0, bus, slot, func, 0x41, 1); */
*busnum = bus;
break;
case 0x71208086:
s = "Intel 82810 (i810 GMCH) Host To Hub bridge";
@ -421,7 +435,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
break;
case 0x84c48086:
s = "Intel 82454KX/GX (Orion) host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x4a, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x4a, 1);
break;
case 0x84ca8086:
/*
@ -435,13 +449,17 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
* Since the MIOC doesn't have a pci bus attached, we
* pretend it wasn't there.
*/
pxb[0] = pci_cfgread(cfg, 0xd0, 1); /* BUSNO[0] */
pxb[1] = pci_cfgread(cfg, 0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = pci_cfgread(cfg, 0xd3, 1); /* BUSNO[1] */
pxb[3] = pci_cfgread(cfg, 0xd4, 1) + 1; /* SUBA[1]+1 */
pxb[0] = nexus_pcib_read_config(0, bus, slot, func,
0xd0, 1); /* BUSNO[0] */
pxb[1] = nexus_pcib_read_config(0, bus, slot, func,
0xd1, 1) + 1; /* SUBA[0]+1 */
pxb[2] = nexus_pcib_read_config(0, bus, slot, func,
0xd3, 1); /* BUSNO[1] */
pxb[3] = nexus_pcib_read_config(0, bus, slot, func,
0xd4, 1) + 1; /* SUBA[1]+1 */
return NULL;
case 0x84cb8086:
switch (cfg->slot) {
switch (slot) {
case 0x12:
s = "Intel 82454NX PXB#0, Bus#A";
*busnum = pxb[0];
@ -513,19 +531,19 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
/* RCC -- vendor 0x1166 */
case 0x00051166:
s = "RCC HE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00061166:
/* FALLTHROUGH */
case 0x00081166:
s = "RCC host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
case 0x00091166:
s = "RCC LE host to PCI bridge";
*busnum = pci_cfgread(cfg, 0x44, 1);
*busnum = nexus_pcib_read_config(0, bus, slot, func, 0x44, 1);
break;
/* Integrated Micro Solutions -- vendor 0x10e0 */
@ -549,7 +567,7 @@ nexus_pcib_is_host_bridge(pcicfgregs *cfg,
static void
nexus_pcib_identify(driver_t *driver, device_t parent)
{
pcicfgregs probe;
int bus, slot, func;
u_int8_t hdrtype;
int found = 0;
int pcifunchigh;
@ -557,19 +575,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
if (pci_cfgopen() == 0)
return;
probe.hose = 0;
probe.bus = 0;
bus = 0;
retry:
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
probe.func = 0;
hdrtype = pci_cfgread(&probe, PCIR_HEADERTYPE, 1);
for (slot = 0; slot <= PCI_SLOTMAX; slot++) {
func = 0;
hdrtype = nexus_pcib_read_config(0, bus, slot, func,
PCIR_HEADERTYPE, 1);
if (hdrtype & PCIM_MFDEV)
pcifunchigh = 7;
else
pcifunchigh = 0;
for (probe.func = 0;
probe.func <= pcifunchigh;
probe.func++) {
for (func = 0; func <= pcifunchigh; func++) {
/*
* Read the IDs and class from the device.
*/
@ -578,14 +594,17 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
device_t child;
const char *s;
id = pci_cfgread(&probe, PCIR_DEVVENDOR, 4);
id = nexus_pcib_read_config(0, bus, slot, func,
PCIR_DEVVENDOR, 4);
if (id == -1)
continue;
class = pci_cfgread(&probe, PCIR_CLASS, 1);
subclass = pci_cfgread(&probe, PCIR_SUBCLASS, 1);
class = nexus_pcib_read_config(0, bus, slot, func,
PCIR_CLASS, 1);
subclass = nexus_pcib_read_config(0, bus, slot, func,
PCIR_SUBCLASS, 1);
s = nexus_pcib_is_host_bridge(&probe, id,
class, subclass,
s = nexus_pcib_is_host_bridge(bus, slot, func,
id, class, subclass,
&busnum);
if (s) {
/*
@ -601,8 +620,8 @@ nexus_pcib_identify(driver_t *driver, device_t parent)
}
}
}
if (found824xx && probe.bus == 0) {
probe.bus++;
if (found824xx && bus == 0) {
bus++;
goto retry;
}
@ -629,6 +648,17 @@ nexus_pcib_probe(device_t dev)
return ENXIO;
}
static int
nexus_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result)
{
switch (which) {
case PCIB_IVAR_BUS:
*result = 0;
return 0;
}
return ENOENT;
}
static device_method_t nexus_pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, nexus_pcib_identify),
@ -640,6 +670,7 @@ static device_method_t nexus_pcib_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, nexus_pcib_read_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@ -647,6 +678,11 @@ static device_method_t nexus_pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, nexus_pcib_maxslots),
DEVMETHOD(pcib_read_config, nexus_pcib_read_config),
DEVMETHOD(pcib_write_config, nexus_pcib_write_config),
{ 0, 0 }
};

View file

@ -37,6 +37,7 @@
#include <isa/pnpreg.h>
#include <isa/pnpvar.h>
#include <machine/clock.h>
#include <machine/bus.h>
typedef struct _pnp_id {
u_int32_t vendor_id;

View file

@ -1505,7 +1505,7 @@ static int ti_attach(dev)
rid = TI_PCI_LOMEM;
sc->ti_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
0, ~0, 1, RF_ACTIVE);
0, ~0, 1, RF_ACTIVE|PCI_RF_DENSE);
if (sc->ti_res == NULL) {
printf ("ti%d: couldn't map memory\n", unit);
@ -1517,22 +1517,6 @@ static int ti_attach(dev)
sc->ti_bhandle = rman_get_bushandle(sc->ti_res);
sc->ti_vhandle = (vm_offset_t)rman_get_virtual(sc->ti_res);
/*
* XXX FIXME: rman_get_virtual() on the alpha is currently
* broken and returns a physical address instead of a kernel
* virtual address. Consequently, we need to do a little
* extra mangling of the vhandle on the alpha. This should
* eventually be fixed! The whole idea here is to get rid
* of platform dependencies.
*/
#ifdef __alpha__
if (pci_cvt_to_bwx(sc->ti_vhandle))
sc->ti_vhandle = pci_cvt_to_bwx(sc->ti_vhandle);
else
sc->ti_vhandle = pci_cvt_to_dense(sc->ti_vhandle);
sc->ti_vhandle = ALPHA_PHYS_TO_K0SEG(sc->ti_vhandle);
#endif
/* Allocate interrupt */
rid = 0;

View file

@ -216,15 +216,6 @@ static struct ispmdvec mdvec_2200 = {
static int isp_pci_probe (device_t);
static int isp_pci_attach (device_t);
/* This distinguishing define is not right, but it does work */
#ifdef __alpha__
#define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO
#define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM
#else
#define IO_SPACE_MAPPING I386_BUS_SPACE_IO
#define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM
#endif
struct isp_pcisoftc {
struct ispsoftc pci_isp;
device_t pci_dev;

View file

@ -56,6 +56,8 @@
#include <pci/pcireg.h>
#include <pci/pcivar.h>
#include "pcib_if.h"
#ifdef __alpha__
#include <machine/rpb.h>
#endif
@ -64,6 +66,8 @@
#include <machine/smp.h>
#endif /* APIC_IO */
static devclass_t pci_devclass;
struct pci_quirk {
u_int32_t devid; /* Vendor/device of the card */
int type;
@ -177,7 +181,7 @@ pci_fixancient(pcicfgregs *cfg)
/* read config data specific to header type 1 device (PCI to PCI bridge) */
static void *
pci_readppb(pcicfgregs *cfg)
pci_readppb(device_t pcib, int b, int s, int f)
{
pcih1cfgregs *p;
@ -187,35 +191,43 @@ pci_readppb(pcicfgregs *cfg)
bzero(p, sizeof *p);
p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_1, 2);
p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_1, 2);
p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_1, 2);
p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_1, 2);
p->seclat = pci_cfgread(cfg, PCIR_SECLAT_1, 1);
p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_1, 1);
p->iobase = PCI_PPBIOBASE (pci_cfgread(cfg, PCIR_IOBASEH_1, 2),
pci_cfgread(cfg, PCIR_IOBASEL_1, 1));
p->iolimit = PCI_PPBIOLIMIT (pci_cfgread(cfg, PCIR_IOLIMITH_1, 2),
pci_cfgread(cfg, PCIR_IOLIMITL_1, 1));
p->iobase = PCI_PPBIOBASE (PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_IOBASEH_1, 2),
PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_IOBASEL_1, 1));
p->iolimit = PCI_PPBIOLIMIT (PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_IOLIMITH_1, 2),
PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_IOLIMITL_1, 1));
p->membase = PCI_PPBMEMBASE (0,
pci_cfgread(cfg, PCIR_MEMBASE_1, 2));
PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_MEMBASE_1, 2));
p->memlimit = PCI_PPBMEMLIMIT (0,
pci_cfgread(cfg, PCIR_MEMLIMIT_1, 2));
PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_MEMLIMIT_1, 2));
p->pmembase = PCI_PPBMEMBASE (
(pci_addr_t)pci_cfgread(cfg, PCIR_PMBASEH_1, 4),
pci_cfgread(cfg, PCIR_PMBASEL_1, 2));
(pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEH_1, 4),
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEL_1, 2));
p->pmemlimit = PCI_PPBMEMLIMIT (
(pci_addr_t)pci_cfgread(cfg, PCIR_PMLIMITH_1, 4),
pci_cfgread(cfg, PCIR_PMLIMITL_1, 2));
(pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f,
PCIR_PMLIMITH_1, 4),
PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMLIMITL_1, 2));
return (p);
}
/* read config data specific to header type 2 device (PCI to CardBus bridge) */
static void *
pci_readpcb(pcicfgregs *cfg)
pci_readpcb(device_t pcib, int b, int s, int f)
{
pcih2cfgregs *p;
@ -225,60 +237,63 @@ pci_readpcb(pcicfgregs *cfg)
bzero(p, sizeof *p);
p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_2, 2);
p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_2, 2);
p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_2, 2);
p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_2, 2);
p->seclat = pci_cfgread(cfg, PCIR_SECLAT_2, 1);
p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_2, 1);
p->membase0 = pci_cfgread(cfg, PCIR_MEMBASE0_2, 4);
p->memlimit0 = pci_cfgread(cfg, PCIR_MEMLIMIT0_2, 4);
p->membase1 = pci_cfgread(cfg, PCIR_MEMBASE1_2, 4);
p->memlimit1 = pci_cfgread(cfg, PCIR_MEMLIMIT1_2, 4);
p->membase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE0_2, 4);
p->memlimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT0_2, 4);
p->membase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE1_2, 4);
p->memlimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT1_2, 4);
p->iobase0 = pci_cfgread(cfg, PCIR_IOBASE0_2, 4);
p->iolimit0 = pci_cfgread(cfg, PCIR_IOLIMIT0_2, 4);
p->iobase1 = pci_cfgread(cfg, PCIR_IOBASE1_2, 4);
p->iolimit1 = pci_cfgread(cfg, PCIR_IOLIMIT1_2, 4);
p->iobase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE0_2, 4);
p->iolimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT0_2, 4);
p->iobase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE1_2, 4);
p->iolimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT1_2, 4);
p->pccardif = pci_cfgread(cfg, PCIR_PCCARDIF_2, 4);
p->pccardif = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PCCARDIF_2, 4);
return p;
}
/* extract header type specific config data */
static void
pci_hdrtypedata(pcicfgregs *cfg)
pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg)
{
#define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w)
switch (cfg->hdrtype) {
case 0:
cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_0, 2);
cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_0, 2);
cfg->subvendor = REG(PCIR_SUBVEND_0, 2);
cfg->subdevice = REG(PCIR_SUBDEV_0, 2);
cfg->nummaps = PCI_MAXMAPS_0;
break;
case 1:
cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_1, 2);
cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_1, 2);
cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_1, 1);
cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_1, 1);
cfg->subvendor = REG(PCIR_SUBVEND_1, 2);
cfg->subdevice = REG(PCIR_SUBDEV_1, 2);
cfg->secondarybus = REG(PCIR_SECBUS_1, 1);
cfg->subordinatebus = REG(PCIR_SUBBUS_1, 1);
cfg->nummaps = PCI_MAXMAPS_1;
cfg->hdrspec = pci_readppb(cfg);
cfg->hdrspec = pci_readppb(pcib, b, s, f);
break;
case 2:
cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_2, 2);
cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_2, 2);
cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_2, 1);
cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_2, 1);
cfg->subvendor = REG(PCIR_SUBVEND_2, 2);
cfg->subdevice = REG(PCIR_SUBDEV_2, 2);
cfg->secondarybus = REG(PCIR_SECBUS_2, 1);
cfg->subordinatebus = REG(PCIR_SUBBUS_2, 1);
cfg->nummaps = PCI_MAXMAPS_2;
cfg->hdrspec = pci_readpcb(cfg);
cfg->hdrspec = pci_readpcb(pcib, b, s, f);
break;
}
#undef REG
}
/* read configuration header into pcicfgrect structure */
static struct pci_devinfo *
pci_readcfg(pcicfgregs *probe)
pci_read_device(device_t pcib, int b, int s, int f)
{
#define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w)
pcicfgregs *cfg = NULL;
struct pci_devinfo *devlist_entry;
struct devlist *devlist_head;
@ -287,8 +302,7 @@ pci_readcfg(pcicfgregs *probe)
devlist_entry = NULL;
if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) {
if (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVVENDOR, 4) != -1) {
devlist_entry = malloc(sizeof(struct pci_devinfo),
M_DEVBUF, M_WAITOK);
if (devlist_entry == NULL)
@ -297,23 +311,22 @@ pci_readcfg(pcicfgregs *probe)
cfg = &devlist_entry->cfg;
cfg->hose = probe->hose;
cfg->bus = probe->bus;
cfg->slot = probe->slot;
cfg->func = probe->func;
cfg->vendor = pci_cfgread(cfg, PCIR_VENDOR, 2);
cfg->device = pci_cfgread(cfg, PCIR_DEVICE, 2);
cfg->cmdreg = pci_cfgread(cfg, PCIR_COMMAND, 2);
cfg->statreg = pci_cfgread(cfg, PCIR_STATUS, 2);
cfg->baseclass = pci_cfgread(cfg, PCIR_CLASS, 1);
cfg->subclass = pci_cfgread(cfg, PCIR_SUBCLASS, 1);
cfg->progif = pci_cfgread(cfg, PCIR_PROGIF, 1);
cfg->revid = pci_cfgread(cfg, PCIR_REVID, 1);
cfg->hdrtype = pci_cfgread(cfg, PCIR_HEADERTYPE, 1);
cfg->cachelnsz = pci_cfgread(cfg, PCIR_CACHELNSZ, 1);
cfg->lattimer = pci_cfgread(cfg, PCIR_LATTIMER, 1);
cfg->intpin = pci_cfgread(cfg, PCIR_INTPIN, 1);
cfg->intline = pci_cfgread(cfg, PCIR_INTLINE, 1);
cfg->bus = b;
cfg->slot = s;
cfg->func = f;
cfg->vendor = REG(PCIR_VENDOR, 2);
cfg->device = REG(PCIR_DEVICE, 2);
cfg->cmdreg = REG(PCIR_COMMAND, 2);
cfg->statreg = REG(PCIR_STATUS, 2);
cfg->baseclass = REG(PCIR_CLASS, 1);
cfg->subclass = REG(PCIR_SUBCLASS, 1);
cfg->progif = REG(PCIR_PROGIF, 1);
cfg->revid = REG(PCIR_REVID, 1);
cfg->hdrtype = REG(PCIR_HEADERTYPE, 1);
cfg->cachelnsz = REG(PCIR_CACHELNSZ, 1);
cfg->lattimer = REG(PCIR_LATTIMER, 1);
cfg->intpin = REG(PCIR_INTPIN, 1);
cfg->intline = REG(PCIR_INTLINE, 1);
#ifdef __alpha__
alpha_platform_assign_pciintr(cfg);
#endif
@ -346,14 +359,14 @@ pci_readcfg(pcicfgregs *probe)
}
#endif /* APIC_IO */
cfg->mingnt = pci_cfgread(cfg, PCIR_MINGNT, 1);
cfg->maxlat = pci_cfgread(cfg, PCIR_MAXLAT, 1);
cfg->mingnt = REG(PCIR_MINGNT, 1);
cfg->maxlat = REG(PCIR_MAXLAT, 1);
cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0;
cfg->hdrtype &= ~PCIM_MFDEV;
pci_fixancient(cfg);
pci_hdrtypedata(cfg);
pci_hdrtypedata(pcib, b, s, f, cfg);
STAILQ_INSERT_TAIL(devlist_head, devlist_entry, pci_links);
@ -376,6 +389,7 @@ pci_readcfg(pcicfgregs *probe)
pci_generation++;
}
return (devlist_entry);
#undef REG
}
#if 0
@ -541,6 +555,7 @@ pci_devlist_get_parent(pcicfgregs *cfg)
static int
pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
{
device_t pci, pcib;
struct pci_io *io;
const char *name;
int error;
@ -782,17 +797,30 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case PCIOCREAD:
io = (struct pci_io *)data;
switch(io->pi_width) {
pcicfgregs probe;
case 4:
case 2:
case 1:
probe.hose = -1;
probe.bus = io->pi_sel.pc_bus;
probe.slot = io->pi_sel.pc_dev;
probe.func = io->pi_sel.pc_func;
io->pi_data = pci_cfgread(&probe,
io->pi_reg, io->pi_width);
error = 0;
/*
* Assume that the user-level bus number is
* actually the pciN instance number. We map
* from that to the real pcib+bus combination.
*/
pci = devclass_get_device(pci_devclass,
io->pi_sel.pc_bus);
if (pci) {
int b = pcib_get_bus(pci);
pcib = device_get_parent(pci);
io->pi_data =
PCIB_READ_CONFIG(pcib,
b,
io->pi_sel.pc_dev,
io->pi_sel.pc_func,
io->pi_reg,
io->pi_width);
error = 0;
} else {
error = ENODEV;
}
break;
default:
error = ENODEV;
@ -803,17 +831,30 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
case PCIOCWRITE:
io = (struct pci_io *)data;
switch(io->pi_width) {
pcicfgregs probe;
case 4:
case 2:
case 1:
probe.hose = -1;
probe.bus = io->pi_sel.pc_bus;
probe.slot = io->pi_sel.pc_dev;
probe.func = io->pi_sel.pc_func;
pci_cfgwrite(&probe,
io->pi_reg, io->pi_data, io->pi_width);
error = 0;
/*
* Assume that the user-level bus number is
* actually the pciN instance number. We map
* from that to the real pcib+bus combination.
*/
pci = devclass_get_device(pci_devclass,
io->pi_sel.pc_bus);
if (pci) {
int b = pcib_get_bus(pci);
pcib = device_get_parent(pci);
PCIB_WRITE_CONFIG(pcib,
b,
io->pi_sel.pc_dev,
io->pi_sel.pc_func,
io->pi_reg,
io->pi_data,
io->pi_width);
error = 0;
} else {
error = ENODEV;
}
break;
default:
error = ENODEV;
@ -850,7 +891,6 @@ static struct cdevsw pcicdev = {
#include "pci_if.h"
/*
* New style pci driver. Parent device is either a pci-host-bridge or a
* pci-pci-bridge. Both kinds are represented by instances of pcib.
@ -882,15 +922,17 @@ pci_print_verbose(struct pci_devinfo *dinfo)
}
static int
pci_porten(pcicfgregs *cfg)
pci_porten(device_t pcib, int b, int s, int f)
{
return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0);
return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2)
& PCIM_CMD_PORTEN) != 0;
}
static int
pci_memen(pcicfgregs *cfg)
pci_memen(device_t pcib, int b, int s, int f)
{
return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0);
return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2)
& PCIM_CMD_MEMEN) != 0;
}
/*
@ -898,10 +940,9 @@ pci_memen(pcicfgregs *cfg)
* register is a 32bit map register or 2 if it is a 64bit register.
*/
static int
pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
pci_add_map(device_t pcib, int b, int s, int f, int reg,
struct resource_list *rl)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
struct resource_list *rl = &dinfo->resources;
u_int32_t map;
u_int64_t base;
u_int8_t ln2size;
@ -910,14 +951,14 @@ pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
int type;
map = pci_cfgread(cfg, reg, 4);
map = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4);
if (map == 0 || map == 0xffffffff)
return 1; /* skip invalid entry */
pci_cfgwrite(cfg, reg, 0xffffffff, 4);
testval = pci_cfgread(cfg, reg, 4);
pci_cfgwrite(cfg, reg, map, 4);
PCIB_WRITE_CONFIG(pcib, b, s, f, reg, 0xffffffff, 4);
testval = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4);
PCIB_WRITE_CONFIG(pcib, b, s, f, reg, map, 4);
base = pci_mapbase(map);
if (pci_maptype(map) & PCI_MAPMEM)
@ -928,72 +969,24 @@ pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
ln2range = pci_maprange(testval);
if (ln2range == 64) {
/* Read the other half of a 64bit map register */
base |= (u_int64_t) pci_cfgread(cfg, reg + 4, 4) << 32;
base |= (u_int64_t) PCIB_READ_CONFIG(pcib, b, s, f, reg + 4, 4) << 32;
}
#ifdef __alpha__
/*
* XXX: encode hose number in the base addr,
* This will go away once the bus_space functions
* can deal with multiple hoses
*/
if (cfg->hose) {
u_int32_t mask, shift, maxh;
switch (hwrpb->rpb_type) {
case ST_DEC_4100:
mask = 0xc0000000;
shift = 30;
maxh = 4; /* not a hose. MCPCIA instance # */
break;
case ST_DEC_21000:
mask = 0xf8000000;
shift = 27;
maxh = 32;
break;
case ST_DEC_6600:
mask = 0x80000000;
shift = 31;
maxh = 2;
break;
default:
mask = 0;
shift = 0;
maxh = 0;
break;
}
if (base & mask) {
printf("base addr = 0x%llx\n", (long long) base);
printf("mask addr = 0x%lx\n", (long) mask);
printf("hacked addr = 0x%llx\n", (long long)
(base | ((u_int64_t)cfg->hose << shift)));
panic("hose encoding hack would clobber base addr");
/* NOTREACHED */
}
if (cfg->hose >= maxh) {
panic("Hose %d - can only encode %d hose(s)",
cfg->hose, maxh);
/* NOTREACHED */
}
base |= ((u_int64_t)cfg->hose << shift);
}
#endif
if (bootverbose) {
printf("\tmap[%02x]: type %x, range %2d, base %08x, size %2d",
reg, pci_maptype(map), ln2range,
(unsigned int) base, ln2size);
if (type == SYS_RES_IOPORT && !pci_porten(cfg))
if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f))
printf(", port disabled\n");
else if (type == SYS_RES_MEMORY && !pci_memen(cfg))
else if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f))
printf(", memory disabled\n");
else
printf(", enabled\n");
}
if (type == SYS_RES_IOPORT && !pci_porten(cfg))
if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f))
return 1;
if (type == SYS_RES_MEMORY && !pci_memen(cfg))
if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f))
return 1;
resource_list_add(rl, type, reg,
@ -1004,21 +997,22 @@ pci_add_map(device_t dev, pcicfgregs* cfg, int reg)
}
static void
pci_add_resources(device_t dev, pcicfgregs* cfg)
pci_add_resources(device_t pcib, int b, int s, int f, device_t dev)
{
struct pci_devinfo *dinfo = device_get_ivars(dev);
pcicfgregs *cfg = &dinfo->cfg;
struct resource_list *rl = &dinfo->resources;
struct pci_quirk *q;
int i;
for (i = 0; i < cfg->nummaps;) {
i += pci_add_map(dev, cfg, PCIR_MAPS + i*4);
i += pci_add_map(pcib, b, s, f, PCIR_MAPS + i*4, rl);
}
for (q = &pci_quirks[0]; q->devid; q++) {
if (q->devid == ((cfg->device << 16) | cfg->vendor)
&& q->type == PCI_QUIRK_MAP_REG)
pci_add_map(dev, cfg, q->arg1);
pci_add_map(pcib, b, s, f, q->arg1, rl);
}
if (cfg->intpin > 0 && cfg->intline != 255)
@ -1029,26 +1023,17 @@ pci_add_resources(device_t dev, pcicfgregs* cfg)
static void
pci_add_children(device_t dev, int busno)
{
pcicfgregs probe;
device_t pcib = device_get_parent(dev);
int maxslots;
int s, f;
#ifdef SIMOS
#undef PCI_SLOTMAX
#define PCI_SLOTMAX 0
#endif
bzero(&probe, sizeof probe);
#ifdef __alpha__
probe.hose = pcib_get_hose(dev);
#endif
#ifdef __i386__
probe.hose = 0;
#endif
probe.bus = busno;
for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) {
maxslots = PCIB_MAXSLOTS(pcib);
for (s = 0; s <= maxslots; s++) {
int pcifunchigh = 0;
for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) {
struct pci_devinfo *dinfo = pci_readcfg(&probe);
for (f = 0; f <= pcifunchigh; f++) {
struct pci_devinfo *dinfo =
pci_read_device(pcib, busno, s, f);
if (dinfo != NULL) {
if (dinfo->cfg.mfdev)
pcifunchigh = 7;
@ -1056,19 +1041,31 @@ pci_add_children(device_t dev, int busno)
pci_print_verbose(dinfo);
dinfo->cfg.dev = device_add_child(dev, NULL, -1);
device_set_ivars(dinfo->cfg.dev, dinfo);
pci_add_resources(dinfo->cfg.dev, &dinfo->cfg);
pci_add_resources(pcib, busno, s, f,
dinfo->cfg.dev);
}
}
}
}
static int
pci_new_probe(device_t dev)
pci_probe(device_t dev)
{
static int once;
device_set_desc(dev, "PCI bus");
pci_add_children(dev, device_get_unit(dev));
if (bootverbose)
device_printf(dev, "physical bus=%d\n", pcib_get_bus(dev));
/*
* Since there can be multiple independantly numbered PCI
* busses on some large alpha systems, we can't use the unit
* number to decide what bus we are probing. We ask the parent
* pcib what our bus number is.
*/
pci_add_children(dev, pcib_get_bus(dev));
if (!once) {
make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644, "pci");
once++;
@ -1227,12 +1224,6 @@ pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
case PCI_IVAR_SUBORDINATEBUS:
*result = cfg->subordinatebus;
break;
case PCI_IVAR_HOSE:
/*
* Pass up to parent bridge.
*/
*result = pcib_get_hose(dev);
break;
default:
return ENOENT;
}
@ -1340,7 +1331,10 @@ pci_read_config_method(device_t dev, device_t child, int reg, int width)
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
return pci_cfgread(cfg, reg, width);
return PCIB_READ_CONFIG(device_get_parent(dev),
cfg->bus, cfg->slot, cfg->func,
reg, width);
}
static void
@ -1349,7 +1343,10 @@ pci_write_config_method(device_t dev, device_t child, int reg,
{
struct pci_devinfo *dinfo = device_get_ivars(child);
pcicfgregs *cfg = &dinfo->cfg;
pci_cfgwrite(cfg, reg, val, width);
PCIB_WRITE_CONFIG(device_get_parent(dev),
cfg->bus, cfg->slot, cfg->func,
reg, val, width);
}
static int
@ -1369,7 +1366,7 @@ pci_modevent(module_t mod, int what, void *arg)
static device_method_t pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pci_new_probe),
DEVMETHOD(device_probe, pci_probe),
DEVMETHOD(device_attach, bus_generic_attach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),

View file

@ -72,6 +72,18 @@ pci_conf_write(pcici_t cfg, u_long reg, u_long data)
pci_write_config(cfg->dev, reg, data, 4);
}
int
pci_cfgread (pcicfgregs *cfg, int reg, int bytes)
{
return (pci_read_config(cfg->dev, reg, bytes));
}
void
pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes)
{
pci_write_config(cfg->dev, reg, data, bytes);
}
int
pci_map_port(pcici_t cfg, u_long reg, pci_port_t* pa)
{

71
sys/pci/pcib_if.m Normal file
View file

@ -0,0 +1,71 @@
#
# Copyright (c) 2000 Doug Rabson
# 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$
#
#include <sys/bus.h>
INTERFACE pcib;
#
# Return the number of slots on the attached PCI bus.
#
METHOD int maxslots {
device_t dev;
};
#
# Read configuration space on the PCI bus. The bus, slot and func
# arguments determine the device which is being read and the reg
# argument is a byte offset into configuration space for that
# device. The width argument (which should be 1, 2 or 4) specifies how
# many byte of configuration space to read from that offset.
#
METHOD u_int32_t read_config {
device_t dev;
int bus;
int slot;
int func;
int reg;
int width;
};
#
# Write configuration space on the PCI bus. The bus, slot and func
# arguments determine the device which is being written and the reg
# argument is a byte offset into configuration space for that
# device. The value field is written to the configuration space, with
# the number of bytes written depending on the width argument.
#
METHOD void write_config {
device_t dev;
int bus;
int slot;
int func;
int reg;
u_int32_t value;
int width;
};

View file

@ -58,6 +58,8 @@
#include <vm/vm_object.h>
#include <vm/pmap.h>
#include "pcib_if.h"
/*---------------------------------------------------------
**
** Intel chipsets for 486 / Pentium processor
@ -762,7 +764,9 @@ static int pcib_attach(device_t dev)
secondary = pci_get_secondarybus(dev);
if (secondary) {
device_add_child(dev, "pci", secondary);
device_t child;
child = device_add_child(dev, "pci", -1);
pcib_set_bus(child, secondary);
return bus_generic_attach(dev);
} else
return 0;
@ -771,16 +775,55 @@ static int pcib_attach(device_t dev)
static int
pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
if (which == PCIB_IVAR_HOSE) {
/*
* Pass up to parent bus.
*/
*result = pci_get_hose(dev);
return(0);
switch (which) {
case PCIB_IVAR_BUS:
*result = *(int*) device_get_softc(dev);
return 0;
}
return ENOENT;
}
static int
pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
{
switch (which) {
case PCIB_IVAR_BUS:
*(int*) device_get_softc(dev) = value;
return 0;
}
return ENOENT;
}
static int
pcib_maxslots(device_t dev)
{
return 31;
}
static u_int32_t
pcib_read_config(device_t dev, int b, int s, int f,
int reg, int width)
{
/*
* Pass through to the next ppb up the chain (i.e. our
* grandparent).
*/
return PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)),
b, s, f, reg, width);
}
static void
pcib_write_config(device_t dev, int b, int s, int f,
int reg, u_int32_t val, int width)
{
/*
* Pass through to the next ppb up the chain (i.e. our
* grandparent).
*/
PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)),
b, s, f, reg, val, width);
}
static device_method_t pcib_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pcib_probe),
@ -792,6 +835,7 @@ static device_method_t pcib_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@ -799,13 +843,18 @@ static device_method_t pcib_methods[] = {
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
DEVMETHOD(pcib_maxslots, pcib_maxslots),
DEVMETHOD(pcib_read_config, pcib_read_config),
DEVMETHOD(pcib_write_config, pcib_write_config),
{ 0, 0 }
};
static driver_t pcib_driver = {
"pcib",
pcib_methods,
1,
sizeof(int),
};
static devclass_t pcib_devclass;

View file

@ -82,7 +82,6 @@ typedef struct pcicfg {
u_int8_t mfdev; /* multi-function device (from hdrtype reg) */
u_int8_t nummaps; /* actual number of PCI maps used */
u_int8_t hose; /* hose which bus is attached to */
u_int8_t bus; /* config space bus address */
u_int8_t slot; /* config space slot address */
u_int8_t func; /* config space function number */
@ -156,6 +155,7 @@ const char *pci_chip_match(struct device *dev);
int pci_cfgread (pcicfgregs *cfg, int reg, int bytes);
void pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes);
#ifdef __alpha__
vm_offset_t pci_cvt_to_dense (vm_offset_t);
vm_offset_t pci_cvt_to_bwx (vm_offset_t);
@ -192,7 +192,6 @@ enum pci_device_ivars {
PCI_IVAR_FUNCTION,
PCI_IVAR_SECONDARYBUS,
PCI_IVAR_SUBORDINATEBUS,
PCI_IVAR_HOSE,
};
/*
@ -229,7 +228,6 @@ PCI_ACCESSOR(slot, SLOT, u_int8_t)
PCI_ACCESSOR(function, FUNCTION, u_int8_t)
PCI_ACCESSOR(secondarybus, SECONDARYBUS, u_int8_t)
PCI_ACCESSOR(subordinatebus, SUBORDINATEBUS, u_int8_t)
PCI_ACCESSOR(hose, HOSE, u_int32_t)
static __inline u_int32_t
pci_read_config(device_t dev, int reg, int width)
@ -249,7 +247,7 @@ pci_write_config(device_t dev, int reg, u_int32_t val, int width)
/*typedef enum pci_device_ivars pcib_device_ivars;*/
enum pcib_device_ivars {
PCIB_IVAR_HOSE,
PCIB_IVAR_BUS
};
#define PCIB_ACCESSOR(A, B, T) \
@ -267,7 +265,7 @@ static __inline void pcib_set_ ## A(device_t dev, T t) \
BUS_WRITE_IVAR(device_get_parent(dev), dev, PCIB_IVAR_ ## B, v); \
}
PCIB_ACCESSOR(hose, HOSE, u_int32_t)
PCIB_ACCESSOR(bus, BUS, u_int32_t)
#endif