mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
* 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:
parent
5809aaba67
commit
21c3015a24
72 changed files with 3686 additions and 4792 deletions
|
|
@ -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
289
sys/alpha/alpha/busspace.c
Normal 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();
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
59
sys/alpha/pci/alphapci_if.m
Normal file
59
sys/alpha/pci/alphapci_if.m
Normal 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;
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
131
sys/alpha/pci/bwx.c
Normal 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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
154
sys/alpha/pci/swiz.c
Normal 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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -26,4 +26,6 @@
|
|||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
extern vm_offset_t t2_csr_base;
|
||||
|
||||
extern void t2_init(void);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#endif
|
||||
#include <dev/ata/ata-all.h>
|
||||
#include <dev/ata/ata-disk.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#if NPCI > 0
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
71
sys/dev/pci/pcib_if.m
Normal 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;
|
||||
};
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
351
sys/pci/pci.c
351
sys/pci/pci.c
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
71
sys/pci/pcib_if.m
Normal 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;
|
||||
};
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue