SVN: rc-scripts/trunk: AUTHORS rc-scripts.spec.in rc.d/init.d/functions rc.d/rc.shutdown src/Makefil...
siefca
siefca at pld-linux.org
Sat Nov 25 13:09:53 CET 2006
Author: siefca
Date: Sat Nov 25 13:09:52 2006
New Revision: 7989
Added:
rc-scripts/trunk/src/pci-config.c
Modified:
rc-scripts/trunk/AUTHORS
rc-scripts/trunk/rc-scripts.spec.in
rc-scripts/trunk/rc.d/init.d/functions
rc-scripts/trunk/rc.d/rc.shutdown
rc-scripts/trunk/src/Makefile.am
Log:
- added Wake-On-Lan work-around for nForce ethernet drivers
- added pci-config utility which allows power state manipulation and devices listing
Modified: rc-scripts/trunk/AUTHORS
==============================================================================
--- rc-scripts/trunk/AUTHORS (original)
+++ rc-scripts/trunk/AUTHORS Sat Nov 25 13:09:52 2006
@@ -29,8 +29,10 @@
Michał Kochanowicz <mkochano at pld-linux.org>
fixes, progress()
-Paweł Wilk <siefca at pl.qmail.org>
+Paweł Wilk <siefca at gnu.org>
executing scripts on iface up/down
+ timezone setup & resolvesymlink
+ nVidia ethernet Wake-On-Lan work-around
Robert Ślaski <robin at atm.com.pl>
ATM support
Modified: rc-scripts/trunk/rc-scripts.spec.in
==============================================================================
--- rc-scripts/trunk/rc-scripts.spec.in (original)
+++ rc-scripts/trunk/rc-scripts.spec.in Sat Nov 25 13:09:52 2006
@@ -218,6 +218,7 @@
%attr(755,root,root) %{_sbindir}/ppp-watch
%attr(755,root,root) %{_sbindir}/netreport
%attr(755,root,root) %{_sbindir}/setsysfont
+%attr(755,root,root) %{_sbindir}/pci-config
%attr(4755,root,root) %{_sbindir}/usernetctl
%attr(755,root,root) %{_sbindir}/if*
Modified: rc-scripts/trunk/rc.d/init.d/functions
==============================================================================
--- rc-scripts/trunk/rc.d/init.d/functions (original)
+++ rc-scripts/trunk/rc.d/init.d/functions Sat Nov 25 13:09:52 2006
@@ -884,6 +884,58 @@
echo $SELINUX > $selinuxfs/enforce
}
+# Wake-On-Lan workaround for nForce ethernet drivers.
+# To realy help it also requires patched kernel module.
+# Written by Pawel Wilk using idea from Arjen Verweij,
+# see http://atlas.et.tudelft.nl/verwei90/nforce2/wol.html
+#
+# Call it only when system halts/suspends, there is
+# no return to the D0 power state after execution!
+#
+forcedeth_workaround()
+{
+ [ -x /sbin/ethtool ] || return 2
+ [ -x /sbin/pci-config || return 2
+ grep -qi forcedeth /proc/modules || return 0
+
+ # FIXME: put here condition - kernel/module version checking
+ # when the problem will be fixed in the driver
+
+ typeset iface bus_dev_fn bus lookfor dev_index cur_state
+
+ for iface in $(ip link show | awk -F'[ :]+' '/eth[0-9]+/ {print $2}')
+ do
+ if LC_ALL=C ethtool -i "${iface}" 2>&1 | egrep -qi 'driver:[[:blank:]]forcedeth'; then
+ case $(LC_ALL=C ethtool "${iface}" 2>&1 | awk 'tolower($1) ~ "wake-on:" {print $2}') in
+ *d*) continue ;; # 'd' letter means that the WON was DISABLED for interface
+ "") continue ;; # empty string means that the WON is not supported here
+ esac
+ bus_dev_fn=$(LC_ALL=C ethtool -i ${iface} 2>&1 | awk -F'[ :.]+' '/^bus-info:/ {printf ("%d %d %d",$3,$4,$5) }')
+ if [ -n "${bus_dev_fn}" -a "${bus_dev_fn}" != "0 0 0" ]; then
+ bus=$(echo "${bus_dev_fn}" | awk '{print $1}')
+ lookfor=$(echo "${bus_dev_fn}" | awk '{print "at bus "$1" device/function "$2"/"$3}')
+ dev_index=$(LC_ALL=C pci-config -B${bus} 2>&1 | grep -i "${lookfor}" | awk '/Device \#[0-9]+/ {print $2}')
+ if [ -n "${dev_index}" ]; then
+ show "Forcing sleep state for the nForce interface %s" ${iface} ; busy
+ ip link set ${iface} up 2>&1 >/dev/null # need it to be up
+ sleep 1
+ pci-config -S -$dev_index 2>&1 >/dev/null
+ RESULT=$?
+ cur_state=$(pci-config -a -$dev_index 2>&1 | awk -F'[ \t:.]+' ' tolower($2$3) ~ "powerstate" {print tolower($4)}')
+ if [ "${cur_state}" != "d3" ]; then
+ RESULT=1
+ fi
+ if [ $RESULT -gt 0 ]; then
+ fail
+ else
+ ok
+ fi
+ fi
+ fi
+ fi
+ done
+}
+
# Remove duplicate entries from mtab (for vserver guest use only)
clean_vserver_mtab() {
:>/etc/mtab.clean
Modified: rc-scripts/trunk/rc.d/rc.shutdown
==============================================================================
--- rc-scripts/trunk/rc.d/rc.shutdown (original)
+++ rc-scripts/trunk/rc.d/rc.shutdown Sat Nov 25 13:09:52 2006
@@ -48,6 +48,9 @@
halt -w
if ! is_yes "$VSERVER"; then
+ # Work-around for the nVidia drivers Wake-On-Lan functionality.
+ forcedeth_workaround
+
# Turn off swap, then unmount file systems.
run_cmd "Turning off swap" swapoff -a
Modified: rc-scripts/trunk/src/Makefile.am
==============================================================================
--- rc-scripts/trunk/src/Makefile.am (original)
+++ rc-scripts/trunk/src/Makefile.am Sat Nov 25 13:09:52 2006
@@ -25,7 +25,8 @@
netreport \
ppp-watch \
start-stop-daemon \
- usernetctl
+ usernetctl \
+ pci-config
EXTRA_PROGRAMS = \
testd
@@ -34,7 +35,7 @@
doexec_SOURCES = doexec.c
-resolvesymlink_SOURCE = resolvesymlink.c
+resolvesymlink_SOURCES = resolvesymlink.c
ipcalc_SOURCES = ipcalc.c
ipcalc_LDADD = -lpopt
@@ -66,3 +67,5 @@
start_stop_daemon_SOURCES = start-stop-daemon.c
+pci-config_SOURCES = pci-config.c
+
Added: rc-scripts/trunk/src/pci-config.c
==============================================================================
--- (empty file)
+++ rc-scripts/trunk/src/pci-config.c Sat Nov 25 13:09:52 2006
@@ -0,0 +1,446 @@
+/* pci-config-space.c: Read the PCI configuration space.
+
+ Read the PCI configuration space using the Intel bus-bridge interface
+ registers. This bypasses the BIOS32 entry, and thus we are not assured
+ of working on all systems.
+
+ Copyright 1998-2002 by Donald Becker.
+ This software may be used and distributed according to the terms of
+ the GNU General Public License (GPL), incorporated herein by reference.
+ Contact the author for use under other terms.
+
+ The author may be reached as becker at scyld.com, or C/O
+ Scyld Computing Corporation
+ 410 Severn Ave., Suite 210
+ Annapolis MD 21403
+
+ Support and updates available at
+ http://www.scyld.com/diag/index.html
+
+ Common-sense licensing statement: Using any portion of this program in
+ your own program means that you must give credit to the original author
+ and release the resulting code under the GPL.
+ */
+
+static char *version_msg =
+"pci-config.c:v2.03 4/15/2002 Donald Becker (becker at scyld.com)\n"
+" http://www.scyld.com/diag/index.html\n";
+static char *usage_msg =
+"Usage: pci-config [-aDfSvVW] [-# <device_index>]\n";
+
+static char *long_usage_msg ="
+
+ This program shows the contents of PCI configuration space.
+ It reads the hardware registers, and thus must be run as 'root'.
+
+ Running this program with no options shows the installed PCI devices.
+ Each line is prefixed by its index which may be used with -#<index>
+ e.g. \"pci-config -#3\" to specify the device to operate on.
+
+ Commonly use options are
+ -# <device-index> Operate only on DEVICE-INDEX e.g -#3
+
+ The operations on the selected device are
+ -a --show-addresses Show PCI address registers.
+ -S --sleep Put device to sleep (ACPI D3 state)
+ -W --wake Wake a sleeping device (ACPI D0 state)
+
+ Less commonly used options are
+ -B <bus> --bus <bus> Show only devices on BUS.
+ -A <addr> --set-addresses Set PCI address register 1 to the ADDR.
+ -D --debug Show details of operations
+ -f --force Override checks and perform the operation
+ -u --usage Show this long usage message
+ -v --verbose Verbose mode
+ -V --version Display this program's version information
+
+";
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <getopt.h>
+#if defined(__linux__) && __GNU_LIBRARY__ == 1
+#include <asm/io.h> /* Newer libraries use <sys/io.h> instead. */
+#else
+#include <sys/io.h>
+#endif
+#if !defined(__OPTIMIZE__)
+#error You must compile this driver with "-O"!
+#endif
+
+struct option longopts[] = {
+ {"show-addresses", 0, 0, 'a'}, /* Show PCI address registers. */
+ {"set-addresses", 1, 0, 'A'}, /* Show PCI address registers. */
+ {"bus", 1, 0, 'B'}, /* Show only devices on BUS. */
+ {"debug", 0, 0, 'D'}, /* Increase debug level. */
+ {"force", 0, 0, 'f'}, /* Force operation. */
+ {"set-WOL", 0, 0, 'M'}, /* Set to Wake-On-LAN mode. */
+ {"sleep", 0, 0, 'S'}, /* Put device to sleep (ACPI D3 state). */
+ {"usage", 0, 0, 'u'}, /* Show the long usage message. */
+ {"verbose", 0, 0, 'v'}, /* Verbose mode */
+ {"version", 0, 0, 'V'}, /* Display version number */
+ {"wake-on-lan", 0, 0, 'W'}, /* Wake (set to D0 state) the device. */
+ {"device-index", 1, 0, '#'}, /* Operate only on device INDEX. */
+ { 0, 0, 0, 0 }
+};
+
+static int verbose=1, opt_a=0, opt_f=0, opt_wake=0, opt_set_WOL=0, debug=0;
+static int opt_sleep = 0;
+static long set_address = -1;
+
+static void show_addr_config(unsigned char pci_bus, unsigned char pci_dev_fn);
+static void show_ext_caps(unsigned int *cfg_space, unsigned char pci_bus,
+ unsigned char pci_dev_fn);
+static void show_one_device(unsigned char pci_bus, unsigned char pci_dev_fn,
+ int dev_num);
+
+static void cyclone_WOL(int pci_bus, int pci_dev_fn, void *pci_config_space);
+static void acpi_wake(unsigned char pci_bus, unsigned char pci_dev_fn,
+ void *config);
+static void acpi_sleep(unsigned char bus, unsigned char devfn, void *pci_cfg);
+static int dump_mem_region(long addr);
+
+extern int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned char *val);
+int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned short *val);
+extern int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned int *val);
+void pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned char val);
+void pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned short val);
+void pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned int val);
+
+
+int main(int argc, char **argv)
+{
+ int pci_bus = 0, pci_dev_fn;
+ int errflag = 0, show_version = 0;
+ int c, longind, card_num = 0;
+ int dev_num = 0;
+
+ while ((c = getopt_long(argc, argv, "#:aA:b:B:DfMSuvVW",
+ longopts, &longind))
+ != -1)
+ switch (c) {
+ case 'a': opt_a++; break;
+ case 'A': set_address = strtol(optarg, NULL, 16); break;
+ case 'b': printf("Setting bus to %s.\n", optarg);
+ case 'B': pci_bus = strtol(optarg, NULL, 0); break;
+ case 'D': debug++; break;
+ case 'f': opt_f++; break;
+ case 'M': opt_set_WOL++; break;
+ case 'S': opt_sleep++; break;
+ case 'u': printf("%s%s", usage_msg, long_usage_msg); return 0;
+ case 'v': verbose++; break;
+ case 'V': show_version++; break;
+ case 'W': opt_wake++; break;
+ case '#': card_num = atoi(optarg); break;
+ case '?':
+ errflag++;
+ }
+ if (errflag) {
+ fprintf(stderr, "%s%s", usage_msg, " Use -u for more information.\n");
+ return 3;
+ }
+
+ if (verbose)
+ printf(version_msg);
+
+ /* Get access to all of I/O space. */
+ if (iopl(3) < 0) {
+ perror("pci-config: iopl()");
+ fprintf(stderr, "This program must be run as root.\n");
+ return 2;
+ }
+ for (pci_dev_fn = 0; pci_dev_fn < 256; pci_dev_fn++) {
+ /*unsigned char cb;*/
+ unsigned int pci_id;
+
+ pcibios_read_config_dword(pci_bus, pci_dev_fn, 0, &pci_id);
+ if (pci_id == 0xffffffff)
+ continue;
+ dev_num++;
+ if (card_num == 0) {
+ printf("Device #%d at bus %d device/function %d/%d, %8.8x.\n",
+ dev_num, pci_bus, pci_dev_fn>>3, pci_dev_fn&7, pci_id);
+ } else if (card_num == dev_num) {
+ show_one_device(pci_bus, pci_dev_fn, dev_num);
+ }
+ if ((pci_dev_fn & 7) == 0) {
+ unsigned int cdw;
+ pcibios_read_config_dword(pci_bus, pci_dev_fn, 3*4, &cdw);
+ if ((cdw & 0x00800000) == 0)
+ pci_dev_fn += 7;
+ }
+ }
+
+ return 0;
+}
+
+static void show_one_device(unsigned char pci_bus, unsigned char pci_dev_fn,
+ int dev_num)
+{
+ unsigned int config[64];
+ int i;
+ int pci_id;
+
+ printf("Device #%d at bus %d device/function %d/%d.",
+ dev_num, pci_bus, pci_dev_fn>>3, pci_dev_fn&7);
+ for (i = 0; i < 64; i++) {
+ pcibios_read_config_dword(pci_bus, pci_dev_fn, i<<2, &config[i]);
+ printf("%s%8.8x", i % 8 == 0 ? "\n " : " ", config[i]);
+ }
+ printf("\n");
+ for (i = 0; i < 5; i++) {
+ unsigned int pciaddr = config[4 + i];
+ if (pciaddr)
+ printf(" Base Address %d: %s at %8.8x.\n",
+ i, pciaddr & 1 ? "I/O" : "Memory", pciaddr & ~1);
+ }
+ if (set_address >= 0) {
+ fprintf(stderr, "Setting PCI address register 1 to 0x%lx.\n",
+ set_address);
+ pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x14, set_address);
+ pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x04, config[1] | 3);
+ }
+ if (opt_a)
+ show_addr_config(pci_bus, pci_dev_fn);
+ pci_id = config[0];
+ if (config[1] & 0x00100000)
+ show_ext_caps(config, pci_bus, pci_dev_fn);
+ if (config[10]) {
+ char *cis_addr_space[] = {"PCI configuration space", "BAR 0", "BAR 1", "BAR 2", "BAR 3", };
+ int space = config[10] & 7;
+ printf(" CardBus CIS pointer 0x%4.4x (%s), address %x.\n", config[10],
+ cis_addr_space[space], config[4 + (space-1)]);
+ if (space > 0 && space < 4)
+ dump_mem_region(config[4 + ((space-1))]);
+ }
+ if (opt_sleep)
+ acpi_sleep(pci_bus, pci_dev_fn, config);
+ if (opt_wake)
+ acpi_wake(pci_bus, pci_dev_fn, config);
+ if (opt_set_WOL)
+ if (pci_id == 0x905510b7)
+ cyclone_WOL(pci_bus, pci_dev_fn, config);
+}
+
+static void show_addr_config(unsigned char pci_bus, unsigned char pci_dev_fn)
+{
+ int i;
+ unsigned int pciaddr, cdw;
+ for (i = 0; i < 5; i++) {
+ int cfg_i = 0x10 + (i<<2);
+ pcibios_read_config_dword(pci_bus, pci_dev_fn, cfg_i, &pciaddr);
+ pcibios_write_config_dword(pci_bus, pci_dev_fn, cfg_i, 0xffffffff);
+ pcibios_read_config_dword(pci_bus, pci_dev_fn, cfg_i, &cdw);
+ if (cdw == 0)
+ break;
+ printf(" Address %d %s at %8.8x, decoded bits are %8.8x.\n",
+ i, cdw & 1 ? "is I/O" : "memory", pciaddr & ~1, ~cdw);
+ pcibios_write_config_dword(pci_bus, pci_dev_fn, cfg_i, pciaddr);
+ }
+ pcibios_read_config_dword(pci_bus, pci_dev_fn, 0x30, &pciaddr);
+ pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x30, 0xfffffffe);
+ pcibios_read_config_dword(pci_bus, pci_dev_fn, 0x30, &cdw);
+ pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x30, pciaddr);
+ if (cdw)
+ printf(" BIOS ROM at %8.8x, decoded bits are %8.8x.\n", pciaddr, cdw);
+ else
+ printf(" No BIOS extension (boot ROM).\n");
+ return;
+}
+static void show_ext_caps(unsigned int *cfg_space, unsigned char pci_bus,
+ unsigned char pci_dev_fn)
+{
+ unsigned char *pcfg = (void *)cfg_space;
+ int cap_idx = cfg_space[13] & 0xff;
+
+ printf(" Extended capabilities, first structure at offset 0x%x.\n",
+ cap_idx);
+ for (; cap_idx; cap_idx = pcfg[cap_idx + 1]) {
+ printf(" Extended PCI capability type %d at 0x%2.2x, next %d.\n",
+ pcfg[cap_idx], cap_idx, pcfg[cap_idx + 1]);
+ if (pcfg[cap_idx] == 1) {
+ printf(" Power management entry ver. %d: Capabilities %2.2x%2.2x"
+ ", Ctrl %2.2x%2.2x, Event %2.2x%2.2x.\n",
+ pcfg[cap_idx + 2] & 7,
+ pcfg[cap_idx + 3], pcfg[cap_idx + 2],
+ pcfg[cap_idx + 5], pcfg[cap_idx + 4],
+ pcfg[cap_idx + 7], pcfg[cap_idx + 6]);
+ printf(" Power state D%d.\n", pcfg[cap_idx + 4] & 3);
+ }
+ }
+}
+
+
+static int acpi_find(unsigned char pci_bus, unsigned char pci_dev_fn,
+ void *config)
+{
+ unsigned char *pcfg = (void *)config;
+ if (pcfg[6] & 0x10) {
+ int cap_idx = pcfg[0x34];
+
+ printf(" Extended capabilities, first structure at offset 0x%x.\n",
+ cap_idx);
+ for (; cap_idx; cap_idx = pcfg[cap_idx + 1]) {
+ if (pcfg[cap_idx] == 1)
+ return cap_idx;
+ }
+ }
+ return 0;
+}
+
+static void acpi_wake(unsigned char pci_bus, unsigned char pci_dev_fn,
+ void *pci_config_space)
+{
+ unsigned char *config = pci_config_space;
+ unsigned short *configw = pci_config_space;
+ unsigned int *configdw = pci_config_space;
+ int pwr_idx = acpi_find(pci_bus, pci_dev_fn, config);
+ unsigned short pwr_command = configw[(pwr_idx + 4)>>1];
+ int i;
+
+ if (debug)
+ printf("Power index is %#x.\n", pwr_idx);
+
+ printf(" Waking up an ACPI device. Currently powered %s, "
+ "I/O %#x IRQ %d.\n"
+ " Updating the power state of %4.4x->%4.4x.\n",
+ pwr_command & 3 ? "down" : "up", configdw[0x10>>2], config[0x3c],
+ pwr_command, pwr_command & ~3);
+ pcibios_write_config_word(pci_bus, pci_dev_fn, pwr_idx + 4,
+ pwr_command & ~3);
+ /* Many devices must have their PCI register state restored when changing
+ from D3 state. */
+ for (i = 0x10; i <= 0x20; i+=4)
+ pcibios_write_config_dword(pci_bus, pci_dev_fn, i, configdw[i >> 2]);
+ /* PCI_ROM_ADDRESS, interrupt line, cache line size, latency timer */
+ pcibios_write_config_dword(pci_bus, pci_dev_fn, 0x30, configdw[0x30 >> 2]);
+ pcibios_write_config_byte(pci_bus, pci_dev_fn, 0x3c, config[0x3c]);
+ pcibios_write_config_byte(pci_bus, pci_dev_fn, 0x0c, config[0x0c]);
+ pcibios_write_config_byte(pci_bus, pci_dev_fn, 0x0d, config[0x0d]);
+ /* Finally, restore the command register. */
+ pcibios_write_config_word(pci_bus, pci_dev_fn, 0x04, configw[4>>1]);
+}
+
+static void acpi_sleep(unsigned char bus, unsigned char devfn,
+ void *pci_config_space)
+{
+ unsigned short *configw = pci_config_space;
+ int pwr_idx = acpi_find(bus, devfn, pci_config_space);
+ unsigned short pwr_command = configw[(pwr_idx + 4)>>1];
+ pcibios_write_config_word(bus, devfn, pwr_idx + 4, pwr_command | 0x0103);
+}
+
+/* Put the 3Com Cyclone e.g. 3c905B series into Wake On LAN mode. */
+static void cyclone_WOL(int pci_bus, int pci_dev_fn, void *config)
+{
+ int pwr_idx = acpi_find(pci_bus, pci_dev_fn, config);
+ unsigned short pwr_command = ((unsigned short *)config)[(pwr_idx + 4)>>1];
+ long ioaddr = ((int *)config)[0x10];
+
+ acpi_wake(pci_bus, pci_dev_fn, config);
+
+ outw(0x801f, ioaddr + 0x0e); /* Set RxFilter to accept frames. */
+ outw((1<<11) + 7, ioaddr + 0x0e);
+ outw(7, ioaddr + 0x0c);
+ printf(" Window 7 Power Management Event is %4.4x.\n",
+ inw(ioaddr + 0x0c));
+ printf(" Changing the power state from %4.4x to 0103.\n", pwr_command);
+ outw(0x2000, ioaddr + 0x0e); /* RxEnable. */
+ pcibios_write_config_word(pci_bus, pci_dev_fn, 0xe0, pwr_command | 0x8103);
+}
+
+
+#define PCI_CONFIG_ADDR 0x0cf8
+#define PCI_CONFIG_DATA 0x0cfc
+
+int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned char *val)
+{
+ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc),
+ PCI_CONFIG_ADDR);
+ *val = inb(PCI_CONFIG_DATA + (regnum & 3));
+ return 0;
+}
+int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned short *val)
+{
+ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc),
+ PCI_CONFIG_ADDR);
+ *val = inw(PCI_CONFIG_DATA + (regnum & 2));
+ return 0;
+}
+int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned int *val)
+{
+ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc),
+ PCI_CONFIG_ADDR);
+ *val = inl(PCI_CONFIG_DATA);
+ return 0;
+}
+void pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned char val)
+{
+ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc),
+ PCI_CONFIG_ADDR);
+ outb(val, PCI_CONFIG_DATA + (regnum & 3));
+ return;
+}
+void pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned short val)
+{
+ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc),
+ PCI_CONFIG_ADDR);
+ outw(val, PCI_CONFIG_DATA + (regnum & 2));
+ return;
+}
+void pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
+ unsigned char regnum, unsigned int val)
+{
+ outl(0x80000000 | (bus<<16) | (dev_fn << 8) | (regnum & 0xfc),
+ PCI_CONFIG_ADDR);
+ outl(val, PCI_CONFIG_DATA);
+ return;
+}
+
+
+/* Map the board shared memory into our address space -- this code is
+ a good example of non-kernel access to devices on the PCI bus. */
+static int dump_mem_region(long addr)
+{
+ unsigned short *shared_mem;
+ int i;
+ int memfd = open("/dev/kmem", O_RDWR);
+
+ if (memfd < 0) {
+ perror("/dev/kmem (shared memory)");
+ return 2;
+ } else
+ printf("Opened /dev/kmem for PCI memory.\n");
+ shared_mem = mmap(0, 0x8000, PROT_READ|PROT_WRITE,
+ MAP_SHARED, memfd, addr);
+ printf("Shared memory at %#x (%#x).\n", (int)addr, (int)shared_mem);
+ for (i = 0; i < 100; i++)
+ printf(" %4.4x", shared_mem[i]);
+ close(memfd);
+ printf(" ...\n");
+ return 0;
+}
+
+/*
+ * Local variables:
+ * compile-command: "cc -O -Wall -o pci-config pci-config.c"
+ * tab-width: 4
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ */
More information about the pld-cvs-commit
mailing list