mirror of
https://github.com/openbsd/src.git
synced 2024-12-22 16:42:56 -08:00
Add an ioctl to figure out the non-sticky bits in PCI BARs used for determining
the size of those BARs. Make pcidump use this new ioctl to print the size of PCI BARs. ok deraadt@, miod@
This commit is contained in:
parent
311a1debed
commit
d01993f357
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pci.c,v 1.83 2010/08/31 17:13:44 deraadt Exp $ */
|
||||
/* $OpenBSD: pci.c,v 1.84 2010/09/05 18:14:33 kettenis Exp $ */
|
||||
/* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
@ -63,6 +63,7 @@ struct pci_dev {
|
||||
pcireg_t pd_bhlc;
|
||||
pcireg_t pd_int;
|
||||
pcireg_t pd_map[NMAPREG];
|
||||
pcireg_t pd_mask[NMAPREG];
|
||||
int pd_pmcsr_state;
|
||||
};
|
||||
|
||||
@ -358,7 +359,7 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
|
||||
struct pci_attach_args pa;
|
||||
struct pci_dev *pd;
|
||||
struct device *dev;
|
||||
pcireg_t id, csr, class, intr, bhlcr;
|
||||
pcireg_t id, class, intr, bhlcr;
|
||||
int ret = 0, pin, bus, device, function;
|
||||
|
||||
pci_decompose_tag(pc, tag, &bus, &device, &function);
|
||||
@ -368,7 +369,6 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
|
||||
return (0);
|
||||
|
||||
id = pci_conf_read(pc, tag, PCI_ID_REG);
|
||||
csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
|
||||
class = pci_conf_read(pc, tag, PCI_CLASS_REG);
|
||||
|
||||
/* Invalid vendor ID value? */
|
||||
@ -430,10 +430,48 @@ pci_probe_device(struct pci_softc *sc, pcitag_t tag,
|
||||
if (ret != 0 && pap != NULL)
|
||||
*pap = pa;
|
||||
} else {
|
||||
pcireg_t address, csr;
|
||||
int i, reg, reg_start, reg_end;
|
||||
int s;
|
||||
|
||||
pd = malloc(sizeof *pd, M_DEVBUF, M_ZERO | M_WAITOK);
|
||||
pd->pd_tag = tag;
|
||||
LIST_INSERT_HEAD(&sc->sc_devs, pd, pd_next);
|
||||
|
||||
switch (PCI_HDRTYPE_TYPE(bhlcr)) {
|
||||
case 0:
|
||||
reg_start = PCI_MAPREG_START;
|
||||
reg_end = PCI_MAPREG_END;
|
||||
break;
|
||||
case 1: /* PCI-PCI bridge */
|
||||
reg_start = PCI_MAPREG_START;
|
||||
reg_end = PCI_MAPREG_PPB_END;
|
||||
break;
|
||||
case 2: /* PCI-CardBus bridge */
|
||||
reg_start = PCI_MAPREG_START;
|
||||
reg_end = PCI_MAPREG_PCB_END;
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
|
||||
s = splhigh();
|
||||
csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
|
||||
if (csr & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
|
||||
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr &
|
||||
~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE));
|
||||
|
||||
for (reg = reg_start, i = 0; reg < reg_end; reg += 4, i++) {
|
||||
address = pci_conf_read(pc, tag, reg);
|
||||
pci_conf_write(pc, tag, reg, 0xffffffff);
|
||||
pd->pd_mask[i] = pci_conf_read(pc, tag, reg);
|
||||
pci_conf_write(pc, tag, reg, address);
|
||||
}
|
||||
|
||||
if (csr & (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE))
|
||||
pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
|
||||
splx(s);
|
||||
|
||||
if ((dev = config_found_sm(&sc->sc_dev, &pa, pciprint,
|
||||
pcisubmatch)))
|
||||
pci_dev_postattach(dev, &pa);
|
||||
@ -509,7 +547,7 @@ pci_get_capability(pci_chipset_tag_t pc, pcitag_t tag, int capid,
|
||||
|
||||
int
|
||||
pci_find_device(struct pci_attach_args *pa,
|
||||
int (*match)(struct pci_attach_args *))
|
||||
int (*match)(struct pci_attach_args *))
|
||||
{
|
||||
extern struct cfdriver pci_cd;
|
||||
struct device *pcidev;
|
||||
@ -903,6 +941,7 @@ pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
|
||||
|
||||
switch (cmd) {
|
||||
case PCIOCREAD:
|
||||
case PCIOCREADMASK:
|
||||
break;
|
||||
case PCIOCWRITE:
|
||||
if (!(flag & FWRITE))
|
||||
@ -971,6 +1010,30 @@ pciioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
|
||||
}
|
||||
break;
|
||||
|
||||
case PCIOCREADMASK:
|
||||
{
|
||||
io = (struct pci_io *)data;
|
||||
struct pci_dev *pd;
|
||||
int dev, func, i;
|
||||
|
||||
if (io->pi_width != 4 || io->pi_reg & 0x3 ||
|
||||
io->pi_reg < PCI_MAPREG_START ||
|
||||
io->pi_reg >= PCI_MAPREG_END)
|
||||
return (EINVAL);
|
||||
|
||||
error = ENODEV;
|
||||
LIST_FOREACH(pd, &pci->sc_devs, pd_next) {
|
||||
pci_decompose_tag(pc, pd->pd_tag, NULL, &dev, &func);
|
||||
if (dev == sel->pc_dev && func == sel->pc_func) {
|
||||
i = (io->pi_reg - PCI_MAPREG_START) / 4;
|
||||
io->pi_data = pd->pd_mask[i];
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PCIOCGETROMLEN:
|
||||
case PCIOCGETROM:
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pcivar.h,v 1.61 2010/08/27 20:31:55 kettenis Exp $ */
|
||||
/* $OpenBSD: pcivar.h,v 1.62 2010/09/05 18:14:33 kettenis Exp $ */
|
||||
/* $NetBSD: pcivar.h,v 1.23 1997/06/06 23:48:05 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
@ -252,7 +252,7 @@ int pci_vpd_write(pci_chipset_tag_t, pcitag_t, int, int, pcireg_t *);
|
||||
const char *pci_findvendor(pcireg_t);
|
||||
const char *pci_findproduct(pcireg_t);
|
||||
int pci_find_device(struct pci_attach_args *pa,
|
||||
int (*match)(struct pci_attach_args *));
|
||||
int (*match)(struct pci_attach_args *));
|
||||
int pci_probe_device(struct pci_softc *, pcitag_t tag,
|
||||
int (*)(struct pci_attach_args *), struct pci_attach_args *);
|
||||
int pci_detach_devices(struct pci_softc *, int);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pciio.h,v 1.6 2010/04/21 18:55:40 kettenis Exp $ */
|
||||
/* $OpenBSD: pciio.h,v 1.7 2010/09/05 18:14:33 kettenis Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, Stefan Esser <se@FreeBSD.ORG>
|
||||
@ -73,5 +73,6 @@ struct pci_vga {
|
||||
#define PCIOCGETROM _IOWR('p', 5, struct pci_rom)
|
||||
#define PCIOCGETVGA _IOWR('p', 6, struct pci_vga)
|
||||
#define PCIOCSETVGA _IOWR('p', 7, struct pci_vga)
|
||||
#define PCIOCREADMASK _IOWR('p', 8, struct pci_io)
|
||||
|
||||
#endif /* !_SYS_PCIIO_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: pcidump.c,v 1.23 2010/08/02 10:17:10 jsg Exp $ */
|
||||
/* $OpenBSD: pcidump.c,v 1.24 2010/09/05 18:14:33 kettenis Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006, 2007 David Gwynne <loki@animata.net>
|
||||
@ -43,6 +43,7 @@ void hexdump(int, int, int, int);
|
||||
const char *str2busdevfunc(const char *, int *, int *, int *);
|
||||
int pci_nfuncs(int, int);
|
||||
int pci_read(int, int, int, u_int32_t, u_int32_t *);
|
||||
int pci_readmask(int, int, int, u_int32_t, u_int32_t *);
|
||||
void dump_caplist(int, int, int, u_int8_t);
|
||||
void dump_pcie_linkspeed(int, int, int, uint8_t);
|
||||
void print_pcie_ls(uint8_t);
|
||||
@ -344,16 +345,18 @@ dump_type0(int bus, int dev, int func)
|
||||
{
|
||||
const char *memtype;
|
||||
u_int64_t mem;
|
||||
u_int32_t reg;
|
||||
u_int64_t mask;
|
||||
u_int32_t reg, reg1;
|
||||
int bar;
|
||||
|
||||
for (bar = PCI_MAPREG_START; bar < PCI_MAPREG_END; bar += 0x4) {
|
||||
if (pci_read(bus, dev, func, bar, ®) != 0)
|
||||
if (pci_read(bus, dev, func, bar, ®) != 0 ||
|
||||
pci_readmask(bus, dev, func, bar, ®1) != 0)
|
||||
warn("unable to read PCI_MAPREG 0x%02x", bar);
|
||||
|
||||
printf("\t0x%04x: BAR ", bar);
|
||||
|
||||
if (reg == 0x0) {
|
||||
if (reg == 0 && reg1 == 0) {
|
||||
printf("empty (%08x)\n", reg);
|
||||
continue;
|
||||
}
|
||||
@ -371,28 +374,34 @@ dump_type0(int bus, int dev, int func)
|
||||
case PCI_MAPREG_MEM_TYPE_32BIT_1M:
|
||||
printf("%s ", memtype);
|
||||
|
||||
printf("addr: 0x%08x\n",
|
||||
PCI_MAPREG_MEM_ADDR(reg));
|
||||
printf("addr: 0x%08x/0x%08x\n",
|
||||
PCI_MAPREG_MEM_ADDR(reg),
|
||||
PCI_MAPREG_MEM_SIZE(reg1));
|
||||
|
||||
break;
|
||||
case PCI_MAPREG_MEM_TYPE_64BIT:
|
||||
mem = reg;
|
||||
mask = reg1;
|
||||
bar += 0x04;
|
||||
if (pci_read(bus, dev, func, bar, ®) != 0)
|
||||
if (pci_read(bus, dev, func, bar, ®) != 0 ||
|
||||
pci_readmask(bus, dev, func, bar, ®1) != 0)
|
||||
warn("unable to read 0x%02x", bar);
|
||||
|
||||
mem |= (u_int64_t)reg << 32;
|
||||
mask |= (u_int64_t)reg1 << 32;
|
||||
|
||||
printf("64bit addr: 0x%016llx\n",
|
||||
PCI_MAPREG_MEM64_ADDR(mem));
|
||||
printf("64bit addr: 0x%016llx/0x%08llx\n",
|
||||
PCI_MAPREG_MEM64_ADDR(mem),
|
||||
PCI_MAPREG_MEM64_SIZE(mask));
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case PCI_MAPREG_TYPE_IO:
|
||||
printf("io addr: 0x%08x\n",
|
||||
PCI_MAPREG_IO_ADDR(reg));
|
||||
printf("io addr: 0x%08x/0x%04x\n",
|
||||
PCI_MAPREG_IO_ADDR(reg),
|
||||
PCI_MAPREG_IO_SIZE(reg1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -658,6 +667,28 @@ pci_read(int bus, int dev, int func, u_int32_t reg, u_int32_t *val)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
pci_readmask(int bus, int dev, int func, u_int32_t reg, u_int32_t *val)
|
||||
{
|
||||
struct pci_io io;
|
||||
int rv;
|
||||
|
||||
bzero(&io, sizeof(io));
|
||||
io.pi_sel.pc_bus = bus;
|
||||
io.pi_sel.pc_dev = dev;
|
||||
io.pi_sel.pc_func = func;
|
||||
io.pi_reg = reg;
|
||||
io.pi_width = 4;
|
||||
|
||||
rv = ioctl(pcifd, PCIOCREADMASK, &io);
|
||||
if (rv != 0)
|
||||
return (rv);
|
||||
|
||||
*val = io.pi_data;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
dump_rom(int bus, int dev, int func)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user