- Add the PCI side of the HOST-PCI bridge itself to the bus. This
is required by the X.Org PCI domains code and additionally needs a workaround for Hummingbird and Sabre bridges as these don't allow their config headers to be read at any width, which is an unusual behavior. - In psycho(4) take advantage of DEFINE_CLASS_0 and use more appropriate types for some softc members. MFC after: 3 days
This commit is contained in:
parent
b629181a3d
commit
edd33ddaa9
@ -189,6 +189,19 @@ ofw_pcibus_attach(device_t dev)
|
||||
domain, busno);
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
|
||||
#ifndef SUN4V
|
||||
/* Add the PCI side of the HOST-PCI bridge itself to the bus. */
|
||||
if (strcmp(device_get_name(device_get_parent(pcib)), "nexus") == 0 &&
|
||||
(dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
|
||||
domain, busno, 0, 0, sizeof(*dinfo))) != NULL) {
|
||||
if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, node) != 0)
|
||||
pci_freecfg((struct pci_devinfo *)dinfo);
|
||||
else
|
||||
pci_add_child(dev, (struct pci_devinfo *)dinfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (child = OF_child(node); child != 0; child = OF_peer(child)) {
|
||||
if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1)
|
||||
continue;
|
||||
|
@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kdb.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
@ -160,14 +161,10 @@ static device_method_t psycho_methods[] = {
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t psycho_driver = {
|
||||
"pcib",
|
||||
psycho_methods,
|
||||
sizeof(struct psycho_softc),
|
||||
};
|
||||
|
||||
static devclass_t psycho_devclass;
|
||||
|
||||
DEFINE_CLASS_0(pcib, psycho_driver, psycho_methods,
|
||||
sizeof(struct psycho_softc));
|
||||
DRIVER_MODULE(psycho, nexus, psycho_driver, psycho_devclass, 0, 0);
|
||||
|
||||
static SLIST_HEAD(, psycho_softc) psycho_softcs =
|
||||
@ -304,9 +301,9 @@ psycho_attach(device_t dev)
|
||||
struct psycho_softc *asc, *sc, *osc;
|
||||
struct ofw_pci_ranges *range;
|
||||
const struct psycho_desc *desc;
|
||||
phandle_t child, node;
|
||||
bus_addr_t intrclr, intrmap;
|
||||
uint64_t csr, dr;
|
||||
phandle_t child, node;
|
||||
uint32_t dvmabase, psycho_br[2];
|
||||
int32_t rev;
|
||||
u_int ver;
|
||||
@ -676,6 +673,16 @@ psycho_attach(device_t dev)
|
||||
PCIB_WRITE_CONFIG(dev, psycho_br[0], PCS_DEVICE, PCS_FUNC, PCSR_SECBUS,
|
||||
sc->sc_pci_secbus, 1);
|
||||
|
||||
for (n = PCIR_VENDOR; n < PCIR_STATUS; n += sizeof(uint16_t))
|
||||
le16enc(&sc->sc_pci_hpbcfg[n], bus_space_read_2(
|
||||
sc->sc_pci_cfgt, sc->sc_pci_bh[OFW_PCI_CS_CONFIG],
|
||||
PSYCHO_CONF_OFF(sc->sc_pci_secbus, PCS_DEVICE,
|
||||
PCS_FUNC, n)));
|
||||
for (n = PCIR_REVID; n <= PCIR_BIST; n += sizeof(uint8_t))
|
||||
sc->sc_pci_hpbcfg[n] = bus_space_read_1(sc->sc_pci_cfgt,
|
||||
sc->sc_pci_bh[OFW_PCI_CS_CONFIG], PSYCHO_CONF_OFF(
|
||||
sc->sc_pci_secbus, PCS_DEVICE, PCS_FUNC, n));
|
||||
|
||||
ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(ofw_pci_intr_t));
|
||||
/*
|
||||
* On E250 the interrupt map entry for the EBus bridge is wrong,
|
||||
@ -924,13 +931,53 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
|
||||
u_long offset = 0;
|
||||
uint8_t byte;
|
||||
uint16_t shrt;
|
||||
uint32_t wrd;
|
||||
uint32_t r;
|
||||
uint32_t r, wrd;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
offset = PSYCHO_CONF_OFF(bus, slot, func, reg);
|
||||
bh = sc->sc_pci_bh[OFW_PCI_CS_CONFIG];
|
||||
|
||||
/*
|
||||
* The Hummingbird and Sabre bridges are picky in that they
|
||||
* only allow their config space to be accessed using the
|
||||
* "native" width of the respective register being accessed
|
||||
* and return semi-random other content of their config space
|
||||
* otherwise. Given that the PCI specs don't say anything
|
||||
* about such a (unusual) limitation and lots of stuff expects
|
||||
* to be able to access the contents of the config space at
|
||||
* any width we allow just that. We do this by using a copy
|
||||
* of the header of the bridge (the rest is all zero anyway)
|
||||
* read during attach (expect for PCIR_STATUS) in order to
|
||||
* simplify things.
|
||||
* The Psycho bridges contain a dupe of their header at 0x80
|
||||
* which we nullify that way also.
|
||||
*/
|
||||
if (bus == sc->sc_pci_secbus && slot == PCS_DEVICE &&
|
||||
func == PCS_FUNC) {
|
||||
if (offset % width != 0)
|
||||
return (-1);
|
||||
|
||||
if (reg > sizeof(sc->sc_pci_hpbcfg))
|
||||
return (0);
|
||||
|
||||
if ((reg < PCIR_STATUS && reg + width > PCIR_STATUS) ||
|
||||
reg == PCIR_STATUS || reg == PCIR_STATUS + 1)
|
||||
le16enc(&sc->sc_pci_hpbcfg[PCIR_STATUS],
|
||||
bus_space_read_2(sc->sc_pci_cfgt, bh,
|
||||
PSYCHO_CONF_OFF(sc->sc_pci_secbus,
|
||||
PCS_DEVICE, PCS_FUNC, PCIR_STATUS)));
|
||||
|
||||
switch (width) {
|
||||
case 1:
|
||||
return (sc->sc_pci_hpbcfg[reg]);
|
||||
case 2:
|
||||
return (le16dec(&sc->sc_pci_hpbcfg[reg]));
|
||||
case 4:
|
||||
return (le32dec(&sc->sc_pci_hpbcfg[reg]));
|
||||
}
|
||||
}
|
||||
|
||||
offset = PSYCHO_CONF_OFF(bus, slot, func, reg);
|
||||
switch (width) {
|
||||
case 1:
|
||||
i = bus_space_peek_1(sc->sc_pci_cfgt, bh, offset, &byte);
|
||||
@ -1001,7 +1048,7 @@ psycho_route_interrupt(device_t bridge, device_t dev, int pin)
|
||||
/*
|
||||
* If this is outside of the range for an intpin, it's likely a full
|
||||
* INO, and no mapping is required at all; this happens on the U30,
|
||||
* where there's no interrupt map at the Psycho node. Fortunately,
|
||||
* where there's no interrupt map at the Psycho node. Fortunately,
|
||||
* there seem to be no INOs in the intpin range on this boxen, so
|
||||
* this easy heuristics will do.
|
||||
*/
|
||||
|
@ -43,17 +43,17 @@ struct psycho_softc {
|
||||
struct mtx *sc_mtx;
|
||||
|
||||
/* Interrupt Group Number for this device */
|
||||
int sc_ign;
|
||||
uint32_t sc_ign;
|
||||
|
||||
bus_addr_t sc_pcictl;
|
||||
|
||||
phandle_t sc_node; /* Firmware node */
|
||||
int sc_mode;
|
||||
u_int sc_mode;
|
||||
#define PSYCHO_MODE_SABRE 1
|
||||
#define PSYCHO_MODE_PSYCHO 2
|
||||
|
||||
/* Bus A or B of a psycho pair? */
|
||||
int sc_half;
|
||||
u_int sc_half;
|
||||
|
||||
struct iommu_state *sc_is;
|
||||
|
||||
@ -77,6 +77,8 @@ struct psycho_softc {
|
||||
struct rman sc_pci_mem_rman;
|
||||
struct rman sc_pci_io_rman;
|
||||
|
||||
uint8_t sc_pci_hpbcfg[16];
|
||||
|
||||
SLIST_ENTRY(psycho_softc) sc_link;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user