Physical memory access from kld

Dmitry Pryanishnikov dmitry at atlantis.dp.ua
Fri Nov 18 11:51:39 GMT 2005


Hello!

  I'm trying to add Intel 875P chipset support for ecc.ko module. Basically
this module outputs whether chipset supports and utilizes ECC, how much
memory does it have, and whether there were memory errors. Well, this
chipset has a very confusing architecture. Instead of having all relevant
bits in PCI device configuration space, Intel has moved part of important
DRAM controller registers into memory-mapped region, which is in turn 
controlled by the Overflow device 6, which isn't (in turn) even available
by default. Many thanks to the author of

http://www.x86-secret.com/articles/tweak/pat/patsecrets-2.htm

for making it possible to access it at all - Intel's pdf doesn't even
mention special register 0xF4 of Device 0! Very confusing desing, much
worse than previous Intel chips ;(

  So, what tricks should I do in order to access memory-mapped registers
of this "hidden" device 6? I wrote the code (currently under FreeBSD-4,
but I want to port it then to RELENG_6) that enables device 6. Luckily
BAR6 (starting address of memory-mapped registers) has been set up correctly
by the mobo's (D875PBZ) BIOS. I can even "dd if=/dev/mem skip=xxx" and read
those registers. But obviously I can't just dereference the pointer
read from BAR6 since this physical address isn't mapped in kernel's
virtual address space. What API should I use in order to map it
in RELENG_4? In RELENG_6?

  And how to construct 'pcicfgregs' object for this "shadow" Overflow device 
under RELENG_6? During boot this device is invisible, so OS doesn't create 
'pcicfgregs' for it. Under RELENG_4 all is simple:

static pcicfgregs               pci_cfg,pci_cfg2;
...
         bzero(cfgp, sizeof pci_cfg);
 	pci_cfg.slot = 0;
 	pci_cfg.func = 0;
...
         pci_cfg2 = pci_cfg;
         pci_cfg2.slot = 6 ; pci_cfg2.func = 0;

and voila - pci_cfgread() / pci_cfgwrite() are happy. But under RELENG_6 there
is no such API, and pci_read_config() / pci_write_config() do require valid
(pcicfgregs *)->dev. So for Device 0 I'm just using OS-created objects:

         STAILQ_FOREACH(dinfo,&pci_devq,pci_links) {
             cfgp = &dinfo->cfg;
             if (cfgp->baseclass != PCIC_BRIDGE) continue;
             if (cfgp->subclass != PCIS_BRIDGE_HOST) continue;
 		/* Here I have valid "pcicfgregs *cfgp" */

How to create valid *cfgp for Device 6?


Sincerely, Dmitry
-- 
Atlantis ISP, System Administrator
e-mail:  dmitry at atlantis.dp.ua
nic-hdl: LYNX-RIPE


More information about the freebsd-hackers mailing list