lkml.org 
[lkml]   [1999]   [Jul]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patches in this message
/
Date
From
SubjectHow Swap PCI changes.
Hi Everybody,

I am sorry to say I forgot to attach the diff files for the PCI changes
from
Motorola. I apologize but this is a mistake I make time after time.
Here they
are.

Johnnie Peters
Motorola Computer Group
Tempe, Az.diff -u -r --new-file linux/CREDITS linux_mot/CREDITS
--- linux/CREDITS Wed Jun 9 22:23:01 1999
+++ linux_mot/CREDITS Fri Jul 9 14:40:03 1999
@@ -1659,6 +1659,13 @@
W: http://www.nyx.net/~arobinso
D: Hayes ESP serial port driver

+N: Robert Robinson
+E: robr@phx.mcd.mot.com
+D: Added PCI services to support hotswapping
+S: 2900 South Diablo Way, DW278
+S: Tempe, Arizona 85282
+S: USA
+
N: Florian La Roche
E: rzsfl@rz.uni-sb.de
E: flla@stud.uni-sb.de
diff -u -r --new-file linux/Documentation/Configure.help linux_mot/Documentation/Configure.help
--- linux/Documentation/Configure.help Sun Jun 13 19:54:06 1999
+++ linux_mot/Documentation/Configure.help Fri Jul 9 12:57:19 1999
@@ -1394,6 +1394,289 @@
kernel will try the direct access method and falls back to the BIOS
if that doesn't work. If unsure, go with the default.

+PCI services
+CONFIG_PCI_SERVICES
+ If your platform supports PCI hot swap capability, you can add
+ dynamic PCI device/resource management services here, e.g. dynamic
+ PCI bus node management, as well as PCI memory and I/O space
+ management. If unsure, say N.
+
+PCI Bus Level 0 nodes
+CONFIG_PCI_BUSLVL0_NODES
+ This PCI Services option sets the number of Bus Level 0 nodes for
+ your platform. The number of Bus Level 0 nodes is the same as
+ the number of PCI Host Bridges connected to the Host Bus. Normally,
+ each system has only one Host Bridge.
+
+PCI Bus Level 1 nodes
+CONFIG_PCI_BUSLVL1_NODES
+ This PCI Services option sets the number of Bus Level 1 nodes for
+ your platform. The number of Bus Level 1 nodes is the number of
+ PCI-to-PCI bridges (excluding any AGP bridges) whose primary bus
+ is the Host Bridges' secondary bus, e.g. PCI bus 0. Normally,
+ each system has only one such bridge.
+
+PCI Bus Level 2 nodes
+CONFIG_PCI_BUSLVL2_NODES
+ This PCI Services option sets the number of Bus Level 2 nodes for
+ your platform. Typically, each PCI slot or card in a system is
+ a Bus Level 2 node. Each card usually has one PCI-to-PCI bridge
+ which is connected to a Bus Level 1 node. The maximum number of
+ PCI cards (hence, Bus Level 2 nodes) is normally eight for a system.
+
+PCI Bus Level 3 nodes
+CONFIG_PCI_BUSLVL3_NODES
+ This PCI Services option sets the number of Bus Level 3 nodes for
+ your platform. A Bus Level 3 node is an additional PCI-to-PCI
+ bridge located on the PCI card. Normally, there is no more than
+ one additional bridge (connected to a Bus Level 2 node) per card.
+
+PCI I/O space starting address
+CONFIG_PCI_IO_START
+ This PCI Services option sets the starting address of configurable
+ PCI I/O space for your platform. If no configurable PCI I/O space
+ is needed or available, then set this value to 00000000 and
+ the CONFIG_PCI_IO_END PCI Services option to ffffffff.
+
+PCI I/O space ending address
+CONFIG_PCI_IO_END
+ This PCI Services option sets the ending address of configurable
+ PCI I/O space for your platform. If no configurable PCI I/O space
+ is needed or available, then set this value to ffffffff and the
+ CONFIG_PCI_IO_START PCI Services option to 00000000.
+
+PCI 20-bit memory space starting address
+CONFIG_PCI_MEM20_START
+ This PCI Services option sets the starting address of configurable
+ PCI 20-bit memory space (i.e. memory below 1M byte) for your platform.
+ Note that only Bus 0 devices can be configured to use 20-bit memory.
+
+PCI 20-bit memory space ending address
+CONFIG_PCI_MEM20_END
+ This PCI Services option sets the ending address of configurable
+ PCI 20-bit memory space (i.e. memory below 1M byte) for your platform.
+ Note that only Bus 0 devices can be configured to use 20-bit memory.
+
+PCI memory space starting address
+CONFIG_PCI_MEM_START
+ This PCI Services option sets the starting address of normal
+ configurable PCI memory space (i.e. either 32-bit memory or
+ 64-bit memory).
+
+PCI memory space ending address
+CONFIG_PCI_MEM_END
+ This PCI Services option sets the ending address of normal
+ configurable PCI memory space (i.e. either 32-bit memory or
+ 64-bit memory).
+
+PCI prefetch memory space starting address
+CONFIG_PCI_MEMPF_START
+ This PCI Services option sets the starting address of configurable
+ PCI prefetchable memory space, (i.e. either 32-bit prefetchable
+ memory or 64-bit prefetchable memory). If no configurable PCI
+ prefetchable memory space is needed or available, then set this
+ value to 00000000 and the CONFIG_PCI_MEMPF_END PCI Services option
+ to ffffffff.
+
+PCI prefetch memory space ending address
+CONFIG_PCI_MEMPF_END
+ This PCI Services option sets the ending address of configurable
+ PCI prefetchable memory space, (i.e. either 32-bit prefetchable
+ memory or 64-bit prefetchable memory). If no configurable PCI
+ prefetchable memory space is needed or available, then set this
+ value to ffffffff and the CONFIG_PCI_MEMPF_START PCI Services
+ option to 00000000.
+
+PCI AGP bridge
+CONFIG_PCI_AGP_BRIDGE
+ This PCI Services option enables support for an AGP PCI-2-PCI bridge
+ device. If your platform doesn't have an AGP PCI-2-PCI bridge device,
+ then you should say N here. If unsure, say N.
+
+PCI AGP bridge I/O space size
+CONFIG_PCI_AGP_IO_SIZE
+ If the AGP PCI-2-PCI bridge option is enabled, this PCI Services option
+ sets the size of I/O space that will be allocated for the AGP PCI-2-PCI
+ bridge device.
+
+PCI AGP bridge memory space size
+CONFIG_PCI_AGP_MEM_SIZE
+ If the AGP PCI-2-PCI bridge option is enabled, this PCI Services option
+ sets the size of memory space that will be allocated for the AGP PCI-2-PCI
+ bridge device.
+
+PCI AGP prefetch memory space size
+CONFIG_PCI_AGP_MEMPF_SIZE
+ If the AGP PCI-2-PCI bridge option is enabled, this PCI Services option
+ sets the size of prefetchable memory space that will be allocated for the
+ AGP PCI-2-PCI bridge device.
+
+PCI local IRQ A
+CONFIG_PCI_LOCAL_PIRQA
+ This PCI Services option sets the PCI Interrupt A (PIRQA)
+ value for PCI for the local domain.
+
+PCI local IRQ B
+CONFIG_PCI_LOCAL_PIRQB
+ This PCI Services option sets the PCI Interrupt B (PIRQB)
+ value for PCI for the local domain.
+
+PCI local IRQ C
+CONFIG_PCI_LOCAL_PIRQC
+ This PCI Services option sets the PCI Interrupt C (PIRQC)
+ value for PCI for the local domain.
+
+PCI local IRQ D
+CONFIG_PCI_LOCAL_PIRQD
+ This PCI Services option sets the PCI Interrupt D (PIRQD)
+ value for PCI for the local domain.
+
+PCI multi-domain system
+CONFIG_PCI_MULTI_DOMAIN
+ This PCI Services option enables support for systems with more
+ than one PCI domain, i.e. a local domain and a remote domain. If
+ you have a system with only one domain, like most personal
+ computers, say N.
+
+PCI remote IRQ A
+CONFIG_PCI_REMOTE_PIRQA
+ If the multi-domain option is enabled, this PCI
+ PCI Services option sets the PIRQA value for PCI
+ Interrupt A in the remote domain.
+
+PCI remote IRQ B
+CONFIG_PCI_REMOTE_PIRQB
+ If the multi-domain option is enabled, this PCI
+ PCI Services option sets the PIRQB value for PCI
+ Interrupt A in the remote domain.
+
+PCI remote IRQ C
+CONFIG_PCI_REMOTE_PIRQC
+ If the multi-domain option is enabled, this PCI
+ PCI Services option sets the PIRQC value for PCI
+ Interrupt A in the remote domain.
+
+PCI remote IRQ D
+CONFIG_PCI_REMOTE_PIRQD
+ If the multi-domain option is enabled, this PCI
+ PCI Services option sets the PIRQD value for PCI
+ Interrupt A in the remote domain.
+
+PCI remote domain bridge device/function
+CONFIG_PCI_REMOTE_DEV
+ This PCI Services option sets the device/function value
+ for the remote domain PCI-2-PCI bridge. This is used
+ by the PCI Services to differentiate between local and
+ remote devices in a multi-domain system.
+
+PCI local domain bridge device/function
+CONFIG_PCI_LOCAL_DEV
+ This PCI Services option sets the device/function value
+ for the local domain PCI-2-PCI bridge. This is used
+ by the PCI Services to differentiate between local and
+ remote devices in a multi-domain system.
+
+PCI PIRQ registers update
+CONFIG_PCI_PIRQ_UPDATE
+ This PCI Services option will update the interrupt
+ control device's PIRQ registers with the local PCI
+ IRQ values if selected. If unsure, say Y.
+
+PCI Bus 0 device configuration
+CONFIG_PCI_BUS_0_DEVICES
+ This PCI Services option enables the dynamic configuration of Bus 0
+ PCI devices. If not enabled, then the PCIBIOS configuration of Bus 0
+ PCI devices, except for PCI-to-PCI bridges, will be retained and used.
+ If your platform is Intel based, then you should say N here. If unsure,
+ say N.
+
+PCI Command Reg. - Special Cycle Recognition
+CONFIG_PCI_COMMAND_SPECIAL
+ This PCI Services option will set the Special Cycle Recognition bit
+ in each device's command register. When set, the device will be
+ enabled to monitor PCI special cycles (if it's designed to monitor
+ special cycles). If not set, the device will ignore special cycles.
+ If unsure, say N.
+
+PCI Command Reg. - Memory Write/Invalidate
+CONFIG_PCI_COMMAND_INVALIDATE
+ This PCI Services option will set the Memory Write and Invalidate
+ Enable bit in each device's command register. When set, the device
+ will be enabled to generate the memory write and invalidate command.
+ If not set, the device will use memory write commands instead. If
+ unsure, say N.
+
+PCI Command Reg. - Parity Error Response
+CONFIG_PCI_COMMAND_PARITY
+ This PCI Services option will set the Parity Error Response bit
+ in each device's command register. When set, the device can report
+ parity errors. If not set, the device ignores parity errors. If
+ unsure, say N.
+
+PCI Command Reg. - Wait Cycle
+CONFIG_PCI_COMMAND_WAIT
+ This PCI Services option will set the Wait Cycle Enable bit
+ in each device's command register. This bit controls whether
+ the device does address/data stepping. If unsure, say N.
+
+PCI Command Reg. - System Error
+CONFIG_PCI_COMMAND_SERR
+ This PCI Services option will set the System Error Enable bit
+ in each device's command register. When set, the device can
+ drive the SERR# line. If unsure, say Y.
+
+PCI Cache Line Size
+CONFIG_PCI_CACHE_LINE_SIZE
+ This PCI Services option will set the Cache Line Size value for
+ each device. For Intel-based platforms, this is normally 4. For
+ PowerPC-based platforms, this is normally 8.
+
+PCI Latency Timer
+CONFIG_PCI_LATENCY_TIMER
+ This PCI Services option will set the Latency Timer value for
+ each device. For Intel-based platforms, this is normally 32. For
+ PowerPC-based platforms, this is normally 128.
+
+PCI Secondary Latency Timer
+CONFIG_PCI_SEC_LATENCY_TIMER
+ This PCI Services option will set the Secondary Latency Timer value
+ for each bridge device. For Intel-based platforms, this is normally
+ 64. For PowerPC-based platforms, this is normally 128.
+
+PCI Bridge Ctl. - Parity Error Response
+CONFIG_PCI_BRIDGE_CTL_PARITY
+ This PCI Services option will set the Parity Error Response bit
+ in each bridge device's bridge control register. When set, the
+ bridge takes the normal actions when a parity error is detected
+ on the secondary side. If not set, parity errors are ignored, but
+ the bridge must generate proper parity. If unsure, say N.
+
+PCI Bridge Ctl. - System Error
+CONFIG_PCI_BRIDGE_CTL_SERR
+ This PCI Services option will set the System Error Enable bit
+ in each bridge device's bridge control register. When set,
+ detection of SERR# asserted on the secondary side causes the
+ bridge to assert SERR# on the primary side (but only if the
+ SERR# enable bit in the command register is set). If not set,
+ detection of SERR# on the secondary side is ignored. If unsure,
+ say N.
+
+PCI Bridge Ctl. - ISA Mode
+CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+ This PCI Services option will set the ISA Mode bit in each bridge
+ device's bridge control register. When set, the bridge only
+ recognizes I/O addresses within the usable ranges that do not
+ alias to an ISA range. If unsure, say N.
+
+PCI Bridge Ctl. - Master Abort Mode
+CONFIG_PCI_BRIDGE_CTL_MASTER_ABORT
+ This PCI Services option will set the Master Abort Mode bit in
+ each bridge device's bridge control register. When set, if the
+ bridge experiences a master abort, it issues a target abort to
+ the initiating master. If not set, any reads that experiences
+ a master abort returns all ones; any writes complete normally
+ and the data is thrown away. If unsure, say N.
+
PCI quirks
CONFIG_PCI_QUIRKS
If you have a broken BIOS, it may fail to set up the PCI bus in a
diff -u -r --new-file linux/arch/i386/config.in linux_mot/arch/i386/config.in
--- linux/arch/i386/config.in Mon Apr 26 13:49:17 1999
+++ linux_mot/arch/i386/config.in Fri Jul 9 12:24:55 1999
@@ -63,6 +63,10 @@
if [ "$CONFIG_PCI_GODIRECT" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
define_bool CONFIG_PCI_DIRECT y
fi
+ bool ' PCI services' CONFIG_PCI_SERVICES
+ if [ "$CONFIG_PCI_SERVICES" = "y" ]; then
+ source drivers/pci/Config.in.5350
+ fi
bool ' PCI quirks' CONFIG_PCI_QUIRKS
if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool ' PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
diff -u -r --new-file linux/arch/ppc/config.in linux_mot/arch/ppc/config.in
--- linux/arch/ppc/config.in Fri Jun 4 13:30:47 1999
+++ linux_mot/arch/ppc/config.in Tue Jun 22 12:53:49 1999
@@ -92,7 +92,6 @@
bool 'Support for Open Firmware device tree in /proc' CONFIG_PROC_DEVICETREE
bool 'Support for TotalImpact TotalMP' CONFIG_TOTALMP
bool 'Support for early boot text console (BootX only)' CONFIG_BOOTX_TEXT
-bool 'Support for Motorola Hot Swap' CONFIG_MOTOROLA_HOTSWAP
if [ "$CONFIG_PREP" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
bool 'PReP bootloader kernel arguments' CONFIG_CMDLINE_BOOL y
if [ "$CONFIG_CMDLINE_BOOL" = "y" ] ; then
dep_tristate 'Amiga or PowerMac DMA sound support' CONFIG_DMASOUND $CONFIG_SOUND
source drivers/sound/Config.in
fi
+endmenu
+
+mainmenu_option next_comment
+comment 'Motorola Hot Swap Support'
+bool 'PCI services' CONFIG_PCI_SERVICES
+if [ "$CONFIG_PCI_SERVICES" = "y" ]; then
+ source drivers/pci/Config.in.cpx8216
+fi
endmenu

mainmenu_option next_comment
comment 'Kernel hacking'
diff -u -r --new-file linux/drivers/pci/Config.in.cpv5000 linux_mot/drivers/pci/Config.in.cpv5000
--- linux/drivers/pci/Config.in.cpv5000 Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/Config.in.cpv5000 Tue Jun 8 10:36:04 1999
@@ -0,0 +1,127 @@
+#
+# drivers/pci/Config.in.cpv5000
+#
+# See drivers/pci/README.CONFIG for more information.
+#
+
+
+#
+# Prompt user for number of nodes at each Bus Level.
+#
+
+int ' PCI Bus Level 0 nodes' CONFIG_PCI_BUSLVL0_NODES 1
+int ' PCI Bus Level 1 nodes' CONFIG_PCI_BUSLVL1_NODES 1
+int ' PCI Bus Level 2 nodes' CONFIG_PCI_BUSLVL2_NODES 7
+int ' PCI Bus Level 3 nodes' CONFIG_PCI_BUSLVL3_NODES 1
+
+#
+# Prompt user for starting/ending address for PCI I/O space,
+# PCI 20-bit memory space, PCI normal memory space, and PCI
+# prefetch memory space.
+#
+
+hex ' PCI I/O space starting address' CONFIG_PCI_IO_START 00007000
+hex ' PCI I/O space ending address' CONFIG_PCI_IO_END 0000dfff
+
+hex ' PCI 20-bit memory space starting address' CONFIG_PCI_MEM20_START 00000000
+hex ' PCI 20-bit memory space ending address' CONFIG_PCI_MEM20_END 000fffff
+
+hex ' PCI memory space starting address' CONFIG_PCI_MEM_START ff000000
+hex ' PCI memory space ending address' CONFIG_PCI_MEM_END ff8fffff
+
+hex ' PCI prefetch memory space starting address' CONFIG_PCI_MEMPF_START fe000000
+hex ' PCI prefetch memory space ending address' CONFIG_PCI_MEMPF_END feffffff
+
+#
+# Prompt the user as to whether the system has an AGP
+# PCI-2-PCI bridge or not. If it does have an AGP bridge,
+# then prompt the user for the size of it's I/O, memory,
+# and prefetchable memory space size.
+#
+
+bool ' PCI AGP bridge' CONFIG_PCI_AGP_BRIDGE
+
+if [ "$CONFIG_PCI_AGP_BRIDGE" = "y" ]; then
+ hex ' PCI AGP bridge I/O space size' CONFIG_PCI_AGP_IO_SIZE 00001000
+ hex ' PCI AGP bridge memory space size' CONFIG_PCI_AGP_MEM_SIZE 00100000
+ hex ' PCI AGP prefetch memory space size' CONFIG_PCI_AGP_MEMPF_SIZE 00100000
+fi
+
+#
+# Prompt user for local domain PCI IRQ values for PIRQA, PIRQB,
+# PIRQC, and PIRQD.
+#
+
+int ' PCI local IRQ A' CONFIG_PCI_LOCAL_PIRQA 5
+int ' PCI local IRQ B' CONFIG_PCI_LOCAL_PIRQB 9
+int ' PCI local IRQ C' CONFIG_PCI_LOCAL_PIRQC 5
+int ' PCI local IRQ D' CONFIG_PCI_LOCAL_PIRQD 10
+
+#
+# Prompt user as to whether the system is a multi-domain system
+# or not. If so, then prompt the user for remote domain PCI IRQ
+# values for PIRQA, PIRQB, PIRQC, and PIRQD.
+#
+
+bool ' PCI multi-domain system' CONFIG_PCI_MULTI_DOMAIN
+
+if [ "$CONFIG_PCI_MULTI_DOMAIN" = "y" ]; then
+ int ' PCI remote IRQ A' CONFIG_PCI_REMOTE_PIRQA 5
+ int ' PCI remote IRQ B' CONFIG_PCI_REMOTE_PIRQB 9
+ int ' PCI remote IRQ C' CONFIG_PCI_REMOTE_PIRQC 5
+ int ' PCI remote IRQ D' CONFIG_PCI_REMOTE_PIRQD 10
+ hex ' PCI remote domain bridge device/function' CONFIG_PCI_REMOTE_DEV 000000c0
+ hex ' PCI local domain bridge device/function' CONFIG_PCI_LOCAL_DEV 000000a0
+fi
+
+#
+# Prompt user as well as whether to configure hardware
+# interrupts or not.
+#
+
+bool ' PCI PIRQ registers update' CONFIG_PCI_PIRQ_UPDATE
+
+#
+# Prompt user as to whether to configure PCI bus 0
+# devices or not, excluding PCI-to-PCI bridges.
+#
+
+bool ' PCI Bus 0 device configuration' CONFIG_PCI_BUS_0_DEVICES
+
+#
+# Prompt user for devices' Command register bits.
+#
+
+bool ' PCI Command Reg. - Special Cycle Recognition' CONFIG_PCI_COMMAND_SPECIAL
+bool ' PCI Command Reg. - Memory Write/Invalidate' CONFIG_PCI_COMMAND_INVALIDATE
+bool ' PCI Command Reg. - Parity Error Response' CONFIG_PCI_COMMAND_PARITY
+bool ' PCI Command Reg. - Wait Cycle' CONFIG_PCI_COMMAND_WAIT
+bool ' PCI Command Reg. - System Error' CONFIG_PCI_COMMAND_SERR
+
+#
+# Prompt user for devices' Cache Line Size value.
+#
+
+int ' PCI Cache Line Size' CONFIG_PCI_CACHE_LINE_SIZE 4
+
+#
+# Prompt user for devices' Latency Timer value.
+#
+
+int ' PCI Latency Timer' CONFIG_PCI_LATENCY_TIMER 32
+
+#
+# Prompt user for bridges' Secondary Latency Timer value.
+#
+
+int ' PCI Secondary Latency Timer' CONFIG_PCI_SEC_LATENCY_TIMER 64
+
+#
+# Prompt user for bridges' Bridge Control register bits.
+#
+
+bool ' PCI Bridge Ctl. - Parity Error Response' CONFIG_PCI_BRIDGE_CTL_PARITY
+bool ' PCI Bridge Ctl. - System Error' CONFIG_PCI_BRIDGE_CTL_SERR
+bool ' PCI Bridge Ctl. - ISA Mode' CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+bool ' PCI Bridge Ctl. - Master Abort Mode' CONFIG_PCI_BRIDGE_CTL_MASTER_ABORT
+
diff -u -r --new-file linux/drivers/pci/Config.in.cpv5300 linux_mot/drivers/pci/Config.in.cpv5300
--- linux/drivers/pci/Config.in.cpv5300 Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/Config.in.cpv5300 Tue Jun 8 10:36:04 1999
@@ -0,0 +1,127 @@
+#
+# drivers/pci/Config.in.cpv5300
+#
+# See drivers/pci/README.CONFIG for more information.
+#
+
+
+#
+# Prompt user for number of nodes at each Bus Level.
+#
+
+int ' PCI Bus Level 0 nodes' CONFIG_PCI_BUSLVL0_NODES 1
+int ' PCI Bus Level 1 nodes' CONFIG_PCI_BUSLVL1_NODES 2
+int ' PCI Bus Level 2 nodes' CONFIG_PCI_BUSLVL2_NODES 7
+int ' PCI Bus Level 3 nodes' CONFIG_PCI_BUSLVL3_NODES 1
+
+#
+# Prompt user for starting/ending address for PCI I/O space,
+# PCI 20-bit memory space, PCI normal memory space, and PCI
+# prefetch memory space.
+#
+
+hex ' PCI I/O space starting address' CONFIG_PCI_IO_START 00001000
+hex ' PCI I/O space ending address' CONFIG_PCI_IO_END 00007fff
+
+hex ' PCI 20-bit memory space starting address' CONFIG_PCI_MEM20_START 00000000
+hex ' PCI 20-bit memory space ending address' CONFIG_PCI_MEM20_END 000fffff
+
+hex ' PCI memory space starting address' CONFIG_PCI_MEM_START fc000000
+hex ' PCI memory space ending address' CONFIG_PCI_MEM_END feafffff
+
+hex ' PCI prefetch memory space starting address' CONFIG_PCI_MEMPF_START f5000000
+hex ' PCI prefetch memory space ending address' CONFIG_PCI_MEMPF_END f7ffffff
+
+#
+# Prompt the user as to whether the system has an AGP
+# PCI-2-PCI bridge or not. If it does have an AGP bridge,
+# then prompt the user for the size of it's I/O, memory,
+# and prefetchable memory space size.
+#
+
+bool ' PCI AGP bridge' CONFIG_PCI_AGP_BRIDGE
+
+if [ "$CONFIG_PCI_AGP_BRIDGE" = "y" ]; then
+ hex ' PCI AGP bridge I/O space size' CONFIG_PCI_AGP_IO_SIZE 00000000
+ hex ' PCI AGP bridge memory space size' CONFIG_PCI_AGP_MEM_SIZE 00100000
+ hex ' PCI AGP prefetch memory space size' CONFIG_PCI_AGP_MEMPF_SIZE 01000000
+fi
+
+#
+# Prompt user for local domain PCI IRQ values for PIRQA, PIRQB,
+# PIRQC, and PIRQD.
+#
+
+int ' PCI local IRQ A' CONFIG_PCI_LOCAL_PIRQA 5
+int ' PCI local IRQ B' CONFIG_PCI_LOCAL_PIRQB 9
+int ' PCI local IRQ C' CONFIG_PCI_LOCAL_PIRQC 5
+int ' PCI local IRQ D' CONFIG_PCI_LOCAL_PIRQD 10
+
+#
+# Prompt user as to whether the system is a multi-domain system
+# or not. If so, then prompt the user for remote domain PCI IRQ
+# values for PIRQA, PIRQB, PIRQC, and PIRQD.
+#
+
+bool ' PCI multi-domain system' CONFIG_PCI_MULTI_DOMAIN
+
+if [ "$CONFIG_PCI_MULTI_DOMAIN" = "y" ]; then
+ int ' PCI remote IRQ A' CONFIG_PCI_REMOTE_PIRQA 5
+ int ' PCI remote IRQ B' CONFIG_PCI_REMOTE_PIRQB 9
+ int ' PCI remote IRQ C' CONFIG_PCI_REMOTE_PIRQC 5
+ int ' PCI remote IRQ D' CONFIG_PCI_REMOTE_PIRQD 10
+ hex ' PCI remote domain bridge device/function' CONFIG_PCI_REMOTE_DEV 000000c0
+ hex ' PCI local domain bridge device/function' CONFIG_PCI_LOCAL_DEV 000000a0
+fi
+
+#
+# Prompt user as well as whether to configure hardware
+# interrupts or not.
+#
+
+bool ' PCI PIRQ registers update' CONFIG_PCI_PIRQ_UPDATE
+
+#
+# Prompt user as to whether to configure PCI bus 0
+# devices or not, excluding PCI-to-PCI bridges.
+#
+
+bool ' PCI Bus 0 device configuration' CONFIG_PCI_BUS_0_DEVICES
+
+#
+# Prompt user for devices' Command register bits.
+#
+
+bool ' PCI Command Reg. - Special Cycle Recognition' CONFIG_PCI_COMMAND_SPECIAL
+bool ' PCI Command Reg. - Memory Write/Invalidate' CONFIG_PCI_COMMAND_INVALIDATE
+bool ' PCI Command Reg. - Parity Error Response' CONFIG_PCI_COMMAND_PARITY
+bool ' PCI Command Reg. - Wait Cycle' CONFIG_PCI_COMMAND_WAIT
+bool ' PCI Command Reg. - System Error' CONFIG_PCI_COMMAND_SERR
+
+#
+# Prompt user for devices' Cache Line Size value.
+#
+
+int ' PCI Cache Line Size' CONFIG_PCI_CACHE_LINE_SIZE 4
+
+#
+# Prompt user for devices' Latency Timer value.
+#
+
+int ' PCI Latency Timer' CONFIG_PCI_LATENCY_TIMER 128
+
+#
+# Prompt user for bridges' Secondary Latency Timer value.
+#
+
+int ' PCI Secondary Latency Timer' CONFIG_PCI_SEC_LATENCY_TIMER 64
+
+#
+# Prompt user for bridges' Bridge Control register bits.
+#
+
+bool ' PCI Bridge Ctl. - Parity Error Response' CONFIG_PCI_BRIDGE_CTL_PARITY
+bool ' PCI Bridge Ctl. - System Error' CONFIG_PCI_BRIDGE_CTL_SERR
+bool ' PCI Bridge Ctl. - ISA Mode' CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+bool ' PCI Bridge Ctl. - Master Abort Mode' CONFIG_PCI_BRIDGE_CTL_MASTER_ABORT
+
diff -u -r --new-file linux/drivers/pci/Config.in.cpv5350 linux_mot/drivers/pci/Config.in.cpv5350
--- linux/drivers/pci/Config.in.cpv5350 Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/Config.in.cpv5350 Tue Jun 8 10:36:04 1999
@@ -0,0 +1,127 @@
+#
+# drivers/pci/Config.in.cpv5350
+#
+# See drivers/pci/README.CONFIG for more information.
+#
+
+
+#
+# Prompt user for number of nodes at each Bus Level.
+#
+
+int ' PCI Bus Level 0 nodes' CONFIG_PCI_BUSLVL0_NODES 1
+int ' PCI Bus Level 1 nodes' CONFIG_PCI_BUSLVL1_NODES 2
+int ' PCI Bus Level 2 nodes' CONFIG_PCI_BUSLVL2_NODES 7
+int ' PCI Bus Level 3 nodes' CONFIG_PCI_BUSLVL3_NODES 1
+
+#
+# Prompt user for starting/ending address for PCI I/O space,
+# PCI 20-bit memory space, PCI normal memory space, and PCI
+# prefetch memory space.
+#
+
+hex ' PCI I/O space starting address' CONFIG_PCI_IO_START 00002000
+hex ' PCI I/O space ending address' CONFIG_PCI_IO_END 0000ffff
+
+hex ' PCI 20-bit memory space starting address' CONFIG_PCI_MEM20_START 00000000
+hex ' PCI 20-bit memory space ending address' CONFIG_PCI_MEM20_END 000fffff
+
+hex ' PCI memory space starting address' CONFIG_PCI_MEM_START f4300000
+hex ' PCI memory space ending address' CONFIG_PCI_MEM_END f4ffffff
+
+hex ' PCI prefetch memory space starting address' CONFIG_PCI_MEMPF_START f5000000
+hex ' PCI prefetch memory space ending address' CONFIG_PCI_MEMPF_END f7ffffff
+
+#
+# Prompt the user as to whether the system has an AGP
+# PCI-2-PCI bridge or not. If it does have an AGP bridge,
+# then prompt the user for the size of it's I/O, memory,
+# and prefetchable memory space size.
+#
+
+bool ' PCI AGP bridge' CONFIG_PCI_AGP_BRIDGE
+
+if [ "$CONFIG_PCI_AGP_BRIDGE" = "y" ]; then
+ hex ' PCI AGP bridge I/O space size' CONFIG_PCI_AGP_IO_SIZE 00000000
+ hex ' PCI AGP bridge memory space size' CONFIG_PCI_AGP_MEM_SIZE 00100000
+ hex ' PCI AGP prefetch memory space size' CONFIG_PCI_AGP_MEMPF_SIZE 01000000
+fi
+
+#
+# Prompt user for local domain PCI IRQ values for PIRQA, PIRQB,
+# PIRQC, and PIRQD.
+#
+
+int ' PCI local IRQ A' CONFIG_PCI_LOCAL_PIRQA 5
+int ' PCI local IRQ B' CONFIG_PCI_LOCAL_PIRQB 9
+int ' PCI local IRQ C' CONFIG_PCI_LOCAL_PIRQC 5
+int ' PCI local IRQ D' CONFIG_PCI_LOCAL_PIRQD 10
+
+#
+# Prompt user as to whether the system is a multi-domain system
+# or not. If so, then prompt the user for remote domain PCI IRQ
+# values for PIRQA, PIRQB, PIRQC, and PIRQD.
+#
+
+bool ' PCI multi-domain system' CONFIG_PCI_MULTI_DOMAIN
+
+if [ "$CONFIG_PCI_MULTI_DOMAIN" = "y" ]; then
+ int ' PCI remote IRQ A' CONFIG_PCI_REMOTE_PIRQA 5
+ int ' PCI remote IRQ B' CONFIG_PCI_REMOTE_PIRQB 9
+ int ' PCI remote IRQ C' CONFIG_PCI_REMOTE_PIRQC 5
+ int ' PCI remote IRQ D' CONFIG_PCI_REMOTE_PIRQD 10
+ hex ' PCI remote domain bridge device/function' CONFIG_PCI_REMOTE_DEV 00000068
+ hex ' PCI local domain bridge device/function' CONFIG_PCI_LOCAL_DEV 00000088
+fi
+
+#
+# Prompt user as well as whether to configure hardware
+# interrupts or not.
+#
+
+bool ' PCI PIRQ registers update' CONFIG_PCI_PIRQ_UPDATE
+
+#
+# Prompt user as to whether to configure PCI bus 0
+# devices or not, excluding PCI-to-PCI bridges.
+#
+
+bool ' PCI Bus 0 device configuration' CONFIG_PCI_BUS_0_DEVICES
+
+#
+# Prompt user for devices' Command register bits.
+#
+
+bool ' PCI Command Reg. - Special Cycle Recognition' CONFIG_PCI_COMMAND_SPECIAL
+bool ' PCI Command Reg. - Memory Write/Invalidate' CONFIG_PCI_COMMAND_INVALIDATE
+bool ' PCI Command Reg. - Parity Error Response' CONFIG_PCI_COMMAND_PARITY
+bool ' PCI Command Reg. - Wait Cycle' CONFIG_PCI_COMMAND_WAIT
+bool ' PCI Command Reg. - System Error' CONFIG_PCI_COMMAND_SERR
+
+#
+# Prompt user for devices' Cache Line Size value.
+#
+
+int ' PCI Cache Line Size' CONFIG_PCI_CACHE_LINE_SIZE 4
+
+#
+# Prompt user for devices' Latency Timer value.
+#
+
+int ' PCI Latency Timer' CONFIG_PCI_LATENCY_TIMER 64
+
+#
+# Prompt user for bridges' Secondary Latency Timer value.
+#
+
+int ' PCI Secondary Latency Timer' CONFIG_PCI_SEC_LATENCY_TIMER 64
+
+#
+# Prompt user for bridges' Bridge Control register bits.
+#
+
+bool ' PCI Bridge Ctl. - Parity Error Response' CONFIG_PCI_BRIDGE_CTL_PARITY
+bool ' PCI Bridge Ctl. - System Error' CONFIG_PCI_BRIDGE_CTL_SERR
+bool ' PCI Bridge Ctl. - ISA Mode' CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+bool ' PCI Bridge Ctl. - Master Abort Mode' CONFIG_PCI_BRIDGE_CTL_MASTER_ABORT
+
diff -u -r --new-file linux/drivers/pci/Config.in.cpx8216 linux_mot/drivers/pci/Config.in.cpx8216
--- linux/drivers/pci/Config.in.cpx8216 Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/Config.in.cpx8216 Tue Jun 8 10:36:04 1999
@@ -0,0 +1,127 @@
+#
+# drivers/pci/Config.in.cpx8216
+#
+# See drivers/pci/README.CONFIG for more information.
+#
+
+
+#
+# Prompt user for number of nodes at each Bus Level.
+#
+
+int ' PCI Bus Level 0 nodes' CONFIG_PCI_BUSLVL0_NODES 1
+int ' PCI Bus Level 1 nodes' CONFIG_PCI_BUSLVL1_NODES 2
+int ' PCI Bus Level 2 nodes' CONFIG_PCI_BUSLVL2_NODES 6
+int ' PCI Bus Level 3 nodes' CONFIG_PCI_BUSLVL3_NODES 1
+
+#
+# Prompt user for starting/ending address for PCI I/O space,
+# PCI 20-bit memory space, PCI normal memory space, and PCI
+# prefetch memory space.
+#
+
+hex ' PCI I/O space starting address' CONFIG_PCI_IO_START 00001000
+hex ' PCI I/O space ending address' CONFIG_PCI_IO_END 0000efff
+
+hex ' PCI 20-bit memory space starting address' CONFIG_PCI_MEM20_START 00000000
+hex ' PCI 20-bit memory space ending address' CONFIG_PCI_MEM20_END 000fffff
+
+hex ' PCI memory space starting address' CONFIG_PCI_MEM_START 01000000
+hex ' PCI memory space ending address' CONFIG_PCI_MEM_END 3affffff
+
+hex ' PCI prefetch memory space starting address' CONFIG_PCI_MEMPF_START 00000000
+hex ' PCI prefetch memory space ending address' CONFIG_PCI_MEMPF_END ffffffff
+
+#
+# Prompt the user as to whether the system has an AGP
+# PCI-2-PCI bridge or not. If it does have an AGP bridge,
+# then prompt the user for the size of it's I/O, memory,
+# and prefetchable memory space size.
+#
+
+bool ' PCI AGP bridge' CONFIG_PCI_AGP_BRIDGE
+
+if [ "$CONFIG_PCI_AGP_BRIDGE" = "y" ]; then
+ hex ' PCI AGP bridge I/O space size' CONFIG_PCI_AGP_IO_SIZE 00001000
+ hex ' PCI AGP bridge memory space size' CONFIG_PCI_AGP_MEM_SIZE 00100000
+ hex ' PCI AGP prefetch memory space size' CONFIG_PCI_AGP_MEMPF_SIZE 00100000
+fi
+
+#
+# Prompt user for local domain PCI IRQ values for PIRQA, PIRQB,
+# PIRQC, and PIRQD.
+#
+
+int ' PCI local IRQ A' CONFIG_PCI_LOCAL_PIRQA 24
+int ' PCI local IRQ B' CONFIG_PCI_LOCAL_PIRQB 25
+int ' PCI local IRQ C' CONFIG_PCI_LOCAL_PIRQC 26
+int ' PCI local IRQ D' CONFIG_PCI_LOCAL_PIRQD 27
+
+#
+# Prompt user as to whether the system is a multi-domain system
+# or not. If so, then prompt the user for remote domain PCI IRQ
+# values for PIRQA, PIRQB, PIRQC, and PIRQD.
+#
+
+bool ' PCI multi-domain system' CONFIG_PCI_MULTI_DOMAIN
+
+if [ "$CONFIG_PCI_MULTI_DOMAIN" = "y" ]; then
+ int ' PCI remote IRQ A' CONFIG_PCI_REMOTE_PIRQA 28
+ int ' PCI remote IRQ B' CONFIG_PCI_REMOTE_PIRQB 29
+ int ' PCI remote IRQ C' CONFIG_PCI_REMOTE_PIRQC 30
+ int ' PCI remote IRQ D' CONFIG_PCI_REMOTE_PIRQD 31
+ hex ' PCI remote domain bridge device/function' CONFIG_PCI_REMOTE_DEV 000000c0
+ hex ' PCI local domain bridge device/function' CONFIG_PCI_LOCAL_DEV 000000a0
+fi
+
+#
+# Prompt user as well as whether to configure hardware
+# interrupts or not.
+#
+
+bool ' PCI PIRQ registers update' CONFIG_PCI_PIRQ_UPDATE
+
+#
+# Prompt user as to whether to configure PCI bus 0
+# devices or not, excluding PCI-to-PCI bridges.
+#
+
+bool ' PCI Bus 0 device configuration' CONFIG_PCI_BUS_0_DEVICES
+
+#
+# Prompt user for devices' Command register bits.
+#
+
+bool ' PCI Command Reg. - Special Cycle Recognition' CONFIG_PCI_COMMAND_SPECIAL
+bool ' PCI Command Reg. - Memory Write/Invalidate' CONFIG_PCI_COMMAND_INVALIDATE
+bool ' PCI Command Reg. - Parity Error Response' CONFIG_PCI_COMMAND_PARITY
+bool ' PCI Command Reg. - Wait Cycle' CONFIG_PCI_COMMAND_WAIT
+bool ' PCI Command Reg. - System Error' CONFIG_PCI_COMMAND_SERR
+
+#
+# Prompt user for devices' Cache Line Size value.
+#
+
+int ' PCI Cache Line Size' CONFIG_PCI_CACHE_LINE_SIZE 8
+
+#
+# Prompt user for devices' Latency Timer value.
+#
+
+int ' PCI Latency Timer' CONFIG_PCI_LATENCY_TIMER 128
+
+#
+# Prompt user for bridges' Secondary Latency Timer value.
+#
+
+int ' PCI Secondary Latency Timer' CONFIG_PCI_SEC_LATENCY_TIMER 128
+
+#
+# Prompt user for bridges' Bridge Control register bits.
+#
+
+bool ' PCI Bridge Ctl. - Parity Error Response' CONFIG_PCI_BRIDGE_CTL_PARITY
+bool ' PCI Bridge Ctl. - System Error' CONFIG_PCI_BRIDGE_CTL_SERR
+bool ' PCI Bridge Ctl. - ISA Mode' CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+bool ' PCI Bridge Ctl. - Master Abort Mode' CONFIG_PCI_BRIDGE_CTL_MASTER_ABORT
+
diff -u -r --new-file linux/drivers/pci/Config.in.default linux_mot/drivers/pci/Config.in.default
--- linux/drivers/pci/Config.in.default Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/Config.in.default Tue Jun 8 10:36:04 1999
@@ -0,0 +1,127 @@
+#
+# drivers/pci/Config.in.cpv5350
+#
+# See drivers/pci/README.CONFIG for more information.
+#
+
+
+#
+# Prompt user for number of nodes at each Bus Level.
+#
+
+int ' PCI Bus Level 0 nodes' CONFIG_PCI_BUSLVL0_NODES 1
+int ' PCI Bus Level 1 nodes' CONFIG_PCI_BUSLVL1_NODES 2
+int ' PCI Bus Level 2 nodes' CONFIG_PCI_BUSLVL2_NODES 7
+int ' PCI Bus Level 3 nodes' CONFIG_PCI_BUSLVL3_NODES 1
+
+#
+# Prompt user for starting/ending address for PCI I/O space,
+# PCI 20-bit memory space, PCI normal memory space, and PCI
+# prefetch memory space.
+#
+
+hex ' PCI I/O space starting address' CONFIG_PCI_IO_START 00002000
+hex ' PCI I/O space ending address' CONFIG_PCI_IO_END 0000ffff
+
+hex ' PCI 20-bit memory space starting address' CONFIG_PCI_MEM20_START 00000000
+hex ' PCI 20-bit memory space ending address' CONFIG_PCI_MEM20_END 000fffff
+
+hex ' PCI memory space starting address' CONFIG_PCI_MEM_START f4300000
+hex ' PCI memory space ending address' CONFIG_PCI_MEM_END f4ffffff
+
+hex ' PCI prefetch memory space starting address' CONFIG_PCI_MEMPF_START f5000000
+hex ' PCI prefetch memory space ending address' CONFIG_PCI_MEMPF_END f7ffffff
+
+#
+# Prompt the user as to whether the system has an AGP
+# PCI-2-PCI bridge or not. If it does have an AGP bridge,
+# then prompt the user for the size of it's I/O, memory,
+# and prefetchable memory space size.
+#
+
+bool ' PCI AGP bridge' CONFIG_PCI_AGP_BRIDGE
+
+if [ "$CONFIG_PCI_AGP_BRIDGE" = "y" ]; then
+ hex ' PCI AGP bridge I/O space size' CONFIG_PCI_AGP_IO_SIZE 00001000
+ hex ' PCI AGP bridge memory space size' CONFIG_PCI_AGP_MEM_SIZE 00100000
+ hex ' PCI AGP prefetch memory space size' CONFIG_PCI_AGP_MEMPF_SIZE 00100000
+fi
+
+#
+# Prompt user for local domain PCI IRQ values for PIRQA, PIRQB,
+# PIRQC, and PIRQD.
+#
+
+int ' PCI local IRQ A' CONFIG_PCI_LOCAL_PIRQA 5
+int ' PCI local IRQ B' CONFIG_PCI_LOCAL_PIRQB 9
+int ' PCI local IRQ C' CONFIG_PCI_LOCAL_PIRQC 5
+int ' PCI local IRQ D' CONFIG_PCI_LOCAL_PIRQD 10
+
+#
+# Prompt user as to whether the system is a multi-domain system
+# or not. If so, then prompt the user for remote domain PCI IRQ
+# values for PIRQA, PIRQB, PIRQC, and PIRQD.
+#
+
+bool ' PCI multi-domain system' CONFIG_PCI_MULTI_DOMAIN
+
+if [ "$CONFIG_PCI_MULTI_DOMAIN" = "y" ]; then
+ int ' PCI remote IRQ A' CONFIG_PCI_REMOTE_PIRQA 5
+ int ' PCI remote IRQ B' CONFIG_PCI_REMOTE_PIRQB 9
+ int ' PCI remote IRQ C' CONFIG_PCI_REMOTE_PIRQC 5
+ int ' PCI remote IRQ D' CONFIG_PCI_REMOTE_PIRQD 10
+ hex ' PCI remote domain bridge device/function' CONFIG_PCI_REMOTE_DEV 000000c0
+ hex ' PCI local domain bridge device/function' CONFIG_PCI_LOCAL_DEV 000000a0
+fi
+
+#
+# Prompt user as well as whether to configure hardware
+# interrupts or not.
+#
+
+bool ' PCI PIRQ registers update' CONFIG_PCI_PIRQ_UPDATE
+
+#
+# Prompt user as to whether to configure PCI bus 0
+# devices or not, excluding PCI-to-PCI bridges.
+#
+
+bool ' PCI Bus 0 device configuration' CONFIG_PCI_BUS_0_DEVICES
+
+#
+# Prompt user for devices' Command register bits.
+#
+
+bool ' PCI Command Reg. - Special Cycle Recognition' CONFIG_PCI_COMMAND_SPECIAL
+bool ' PCI Command Reg. - Memory Write/Invalidate' CONFIG_PCI_COMMAND_INVALIDATE
+bool ' PCI Command Reg. - Parity Error Response' CONFIG_PCI_COMMAND_PARITY
+bool ' PCI Command Reg. - Wait Cycle' CONFIG_PCI_COMMAND_WAIT
+bool ' PCI Command Reg. - System Error' CONFIG_PCI_COMMAND_SERR
+
+#
+# Prompt user for devices' Cache Line Size value.
+#
+
+int ' PCI Cache Line Size' CONFIG_PCI_CACHE_LINE_SIZE 4
+
+#
+# Prompt user for devices' Latency Timer value.
+#
+
+int ' PCI Latency Timer' CONFIG_PCI_LATENCY_TIMER 64
+
+#
+# Prompt user for bridges' Secondary Latency Timer value.
+#
+
+int ' PCI Secondary Latency Timer' CONFIG_PCI_SEC_LATENCY_TIMER 64
+
+#
+# Prompt user for bridges' Bridge Control register bits.
+#
+
+bool ' PCI Bridge Ctl. - Parity Error Response' CONFIG_PCI_BRIDGE_CTL_PARITY
+bool ' PCI Bridge Ctl. - System Error' CONFIG_PCI_BRIDGE_CTL_SERR
+bool ' PCI Bridge Ctl. - ISA Mode' CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+bool ' PCI Bridge Ctl. - Master Abort Mode' CONFIG_PCI_BRIDGE_CTL_MASTER_ABORT
+
diff -u -r --new-file linux/drivers/pci/Makefile linux_mot/drivers/pci/Makefile
--- linux/drivers/pci/Makefile Tue Apr 28 22:41:33 1998
+++ linux_mot/drivers/pci/Makefile Tue Mar 16 22:11:21 1999
@@ -32,6 +32,10 @@
L_OBJS += quirks.o
endif

+ifdef CONFIG_PCI_SERVICES
+L_OBJS += pci_alloc.o pci_conf.o pci_node.o pci_scan.o pci_hwints.o
+endif
+
L_OBJS += compat.o

include $(TOPDIR)/Rules.make
diff -u -r --new-file linux/drivers/pci/README.CONFIG linux_mot/drivers/pci/README.CONFIG
--- linux/drivers/pci/README.CONFIG Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/README.CONFIG Tue Jun 8 10:36:04 1999
@@ -0,0 +1,229 @@
+PCI Services Configuration Notes
+
+01 Feb 1998
+
+Config.in defines a set of symbols with the form CONFIG_PCI_*.
+These are the -native symbols-. Here is a description:
+
+ CONFIG_PCI
+
+ This is the master symbol. It controls whether the basic
+ PCI driver code is present or not.
+
+ If the basic PCI driver code is not present, the PCI
+ Services code will not be present.
+
+
+
+ CONFIG_PCI_SERVICES
+
+ This is the PCI Services symbol. It determines whether the
+ PCI Services code is present or not.
+
+
+
+ CONFIG_PCI_BUSLVL0_NODES
+ CONFIG_PCI_BUSLVL1_NODES
+ CONFIG_PCI_BUSLVL2_NODES
+ CONFIG_PCI_BUSLVL3_NODES
+
+ These define the number of nodes (possible PCI-2-PCI bridge
+ devices, excluding AGP bridge devices) at each bus level. Bus
+ Level 0 usually has only one node, i.e. the primary Host Bridge.
+ Bus Level 2 usually only has one node, i.e. one PCI-to-PCI bridge.
+ Bus Level 3 usually has about 8 nodes, i.e. 8 CompactPCI slots
+ with one PCI-to-PCI bridge per slot/card. Bus Level 4 ususally
+ has only one node, i.e. one PCI-to-PCI bridge.
+
+
+
+ CONFIG_PCI_IO_START
+ CONFIG_PCI_IO_END
+
+ These define the starting and ending addresses for PCI I/O
+ space, respectively. If no PCI I/O space is needed/available,
+ then the starting address should be set to 00000000 and the
+ ending address set to ffffffff.
+
+
+
+ CONFIG_PCI_MEM20_START
+ CONFIG_PCI_MEM20_END
+
+ These define the starting and ending addresses for PCI 1M
+ memory space, respectively.
+
+
+
+ CONFIG_PCI_MEM_START
+ CONFIG_PCI_MEM_END
+
+ These define the starting and ending addresses for PCI normal
+ memory space, respectively.
+
+
+
+ CONFIG_PCI_MEMPF_START
+ CONFIG_PCI_MEMPF_END
+
+ These define the starting and ending addresses for PCI prefetch
+ memory space, respectively. If no PCI prefetch space is needed
+ or available, then the starting address should be set to 00000000
+ and the ending address set to ffffffff.
+
+
+
+ CONFIG_PCI_AGP_BRIDGE
+
+ This is the PCI AGP PCI-2-PCI bridge symbol. It determines whether
+ an AGP bridge device exists or not in the system.
+
+
+
+ CONFIG_PCI_AGP_IO_SIZE
+ CONFIG_PCI_AGP_MEM_SIZE
+ CONFIG_PCI_AGP_MEMPF_SIZE
+
+ If an AGP PCI-2-PCI bridge device exists, then these define the
+ I/O, memory, and prefetchable memory size size, respectively,
+ needed by the PCI AGP PCI-2-PCI bridge device.
+
+
+
+ CONFIG_PCI_LOCAL_PIRQA
+ CONFIG_PCI_LOCAL_PIRQB
+ CONFIG_PCI_LOCAL_PIRQC
+ CONFIG_PCI_LOCAL_PIRQD
+
+ These define the PIRQ values for the system's interrupt
+ controller for local domain PCI INT A, INT B, INT C, and
+ INT D, respectively.
+
+
+
+ CONFIG_PCI_MULTI_DOMAIN
+
+ This defines whether there are multiple PCI domains in
+ the system or not.
+
+
+
+ CONFIG_PCI_REMOTE_PIRQA
+ CONFIG_PCI_REMOTE_PIRQB
+ CONFIG_PCI_REMOTE_PIRQC
+ CONFIG_PCI_REMOTE_PIRQD
+
+ If the system is a multi-domain system, these define the
+ PIRQ values for the system's interrupt controller for remote
+ domain PCI INT A, INT B, INT C, and INT D, respectively.
+
+
+
+ CONFIG_PCI_REMOTE_DEV
+ CONFIG_PCI_LOCAL_DEV
+
+ If the system is a multi-domain system, these define the
+ device/function values for the remote domain PCI bridge and
+ the local domain PCI bridge.
+
+
+
+ CONFIG_PCI_PIRQ_UPDATE
+
+ This definition determines whether the PIRQ registers for the
+ system's interrupt controller get updated or not with the
+ CONFIG_PCI_LOCAL_PIRQx value.
+
+
+
+ CONFIG_PCI_BUS_0_DEVICES
+
+ This is the PCI Bus 0 Devices Configuration symbol. It
+ determines whether Bus 0 devices are configured by the PCI
+ Services code or not.
+
+
+
+ CONFIG_PCI_COMMAND_SPECIAL
+
+ This definition, when defined, will set the Special Cycle
+ Recognition bit in each device's command register.
+
+
+
+ CONFIG_PCI_COMMAND_INVALIDATE
+
+ This definition, when defined, will set the Memory Write
+ and Invalidate Enable bit in each device's command register.
+
+
+
+ CONFIG_PCI_COMMAND_PARITY
+
+ This definition, when defined, will set the Parity Error
+ Response bit in each device's command register.
+
+
+
+ CONFIG_PCI_COMMAND_WAIT
+
+ This definition, when defined, will set the Wait Cycle
+ Enable bit in each device's command register.
+
+
+
+ CONFIG_PCI_COMMAND_SERR
+
+ This definition, when defined, will set the System Error
+ Enable bit in each device's command register.
+
+
+
+ CONFIG_PCI_CACHE_LINE_SIZE
+
+ This defines the Cache Line Size value for each device.
+
+
+
+ CONFIG_PCI_LATENCY_TIMER
+
+ This defines the Latency Timer value for each device.
+
+
+
+ CONFIG_PCI_SEC_LATENCY_TIMER
+
+ This defines the Secondary Latency Timer value for each
+ bridge device, except the primary Host Bridge.
+
+
+
+ CONFIG_PCI_BRIDGE_CTL_PARITY
+
+ This definition, when defined, will set the Parity Error
+ Response bit in each bridge device's bridge control register,
+ except the primary Host Bridge.
+
+
+
+ CONFIG_PCI_BRIDGE_CTL_SERR
+
+ This definition, when defined, will set the System Error
+ Enable bit in each bridge device's bridge control register,
+ except the primary Host Bridge.
+
+
+
+ CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+
+ This definition, when defined, will set the ISA Mode
+ bit in each bridge device's bridge control register,
+ except the primary Host Bridge.
+
+
+
+ CONFIG_PCI_BRIDGE_CTL_MASTER_ABORT
+
+ This definition, when defined, will set the Master Abort
+ Mode bit in each bridge device's bridge control register,
+ except the primary Host Bridge.
diff -u -r --new-file linux/drivers/pci/pci.c linux_mot/drivers/pci/pci.c
--- linux/drivers/pci/pci.c Sun Mar 7 16:19:55 1999
+++ linux_mot/drivers/pci/pci.c Fri Jul 9 13:49:34 1999
@@ -16,6 +16,9 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/malloc.h>
+#ifdef CONFIG_PCI_SERVICES
+#include <linux/pci_res.h>
+#endif

#include <asm/page.h>

@@ -29,8 +32,12 @@

struct pci_bus pci_root;
struct pci_dev *pci_devices = NULL;
+#ifndef CONFIG_PCI_SERVICES
static struct pci_dev **pci_last_dev_p = &pci_devices;
static int pci_reverse __initdata = 0;
+#else
+int pci_reverse = 0;
+#endif

struct pci_dev *
pci_find_slot(unsigned int bus, unsigned int devfn)
@@ -156,6 +163,7 @@
}


+#ifndef CONFIG_PCI_SERVICES
__initfunc(unsigned int pci_scan_bus(struct pci_bus *bus))
{
unsigned int devfn, l, max, class;
@@ -367,6 +375,7 @@
DBG("PCI: pci_scan_bus returning with max=%02x\n", max);
return max;
}
+#endif /* CONFIG_PCI_SERVICES */

struct pci_bus * __init pci_scan_peer_bridge(int bus)
{
@@ -393,6 +402,8 @@
printk("PCI: Probing PCI hardware\n");

memset(&pci_root, 0, sizeof(pci_root));
+
+#ifndef CONFIG_PCI_SERVICES
pci_root.subordinate = pci_scan_bus(&pci_root);

/* give BIOS a chance to apply platform specific fixes: */
@@ -405,6 +416,36 @@
#ifdef CONFIG_PROC_FS
pci_proc_init();
#endif
+
+#else /* CONFIG_PCI_SERVICES */
+
+ if (pci_alloc_businit() != PCI_OK)
+ return;
+
+#ifdef CONFIG_PROC_FS
+ pci_proc_init();
+#endif
+
+ pci_root.subordinate = pci_scan_bus(&pci_root);
+
+#ifdef CONFIG_PCI_PIRQ_UPDATE
+ if (pci_hwints_update_pirqs() != PCI_OK)
+ return;
+#endif
+
+#ifdef CONFIG_VISWS
+ pci_other.number = 1; /* XXX unless bridge(s) on pci_root */
+ pci_other.subordinate = pci_scan_bus(&pci_other);
+ pci_root.next = &pci_other;
+#endif
+
+ /* give BIOS a chance to apply platform specific fixes: */
+ pcibios_fixup();
+
+#ifdef CONFIG_PCI_QUIRKS
+ pci_quirks_init();
+#endif
+#endif /* CONFIG_PCI_SERVICES */
}

__initfunc(void pci_setup (char *str, int *ints))
diff -u -r --new-file linux/drivers/pci/pci_alloc.c linux_mot/drivers/pci/pci_alloc.c
--- linux/drivers/pci/pci_alloc.c Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/pci_alloc.c Tue Jun 8 10:36:04 1999
@@ -0,0 +1,2664 @@
+/*
+** PCI Bus Number/Device Resource Allocation
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_res.h>
+
+#include <asm/errno.h>
+#include <asm/system.h>
+
+
+
+
+
+#if (CONFIG_PCI_BUSLVL0_NODES > 1)
+/*
+** PCI Host Bridge Structure
+**
+** This structure is used by the pci_alloc_hosts()
+** functions only.
+*/
+
+struct pci_host
+{
+ unsigned int devfn; /* Host Device/Function Number */
+ unsigned int number; /* Host Current Bus Number */
+ unsigned int primary; /* Host New Primary Number */
+ unsigned int secondary; /* Host New Secondary Number */
+ unsigned int subordinate; /* Host New Subordinate Number */
+};
+#endif
+
+
+
+
+
+/*
+** Array of maximum number of PCI bus nodes per
+** PCI bus level.
+*/
+
+static int pci_max_busnodes_perlevel[MAX_PCI_LEVELS] =
+{
+ CONFIG_PCI_BUSLVL0_NODES, /* Bus Level 0 Nodes */
+ CONFIG_PCI_BUSLVL1_NODES, /* Bus Level 1 Nodes */
+ CONFIG_PCI_BUSLVL2_NODES, /* Bus Level 2 Nodes */
+ CONFIG_PCI_BUSLVL3_NODES /* Bus Level 3 Nodes */
+};
+
+/*
+** Array of PCI bus numbers at each level. The
+** array will be filled in as follows, with H0
+** denoting host node 0, H1 denoting host node 1,
+** etc.:
+**
+** BusH0, Level 0
+** BusH0, BusH0,..., Level 1
+** BusH0, BusH0,..., Level 2
+** BusH0, BusH0,..., Level 3
+**
+** BusH1, Level 0
+** BusH1, BusH1,..., Level 1
+** BusH1, BusH1,..., Level 2
+** BusH1, BusH1,..., Level 3
+**
+** BusH2, Level 0
+** BusH2, BusH2,..., Level 1
+** BusH2, BusH2,..., Level 2
+** BusH2, BusH2,..., Level 3
+**
+** For example, with two Bus Level 0 nodes, two Bus Level 1
+** nodes, four Bus Level 2 nodes, and two Bus Level 3 nodes,
+** (for a maximum node count of 54) the array would look
+** like this:
+**
+** {
+** 0, Level 0 - Host 0
+** 1, 14, Level 1
+** 2, 5, 8, 11, Level 2
+** 15, 18, 21, 24,
+** 3, 4, Level 3
+** 6, 7,
+** 9, 10,
+** 12, 13,
+** 16, 17,
+** 19, 20,
+** 22, 23,
+** 25, 26,
+**
+** 27, Level 0 - Host 1
+** 28, 41, Level 1
+** 29, 32, 35, 38, Level 2
+** 42, 45, 48, 51,
+** 30, 31, Level 3
+** 33, 34,
+** 36, 37,
+** 39, 40,
+** 43, 44,
+** 46, 47,
+** 49, 50,
+** 52, 53
+** }
+*/
+
+static int pci_busnum_perlevel[MAX_PCI_NODES];
+
+/*
+** Array of indexes into the pci_busnum_perlevel[]
+** array to provide the starting index of bus
+** children. A -1 value indicates there are no
+** child bus numbers. The input to this array is
+** a bus number.
+**
+** For example, with two Bus Level 0 nodes, two Bus Level 1
+** nodes, four Bus Level 2 nodes, and two Bus Level 3 nodes,
+** (for a maximum node count of 54) the array would look
+** like this:
+**
+** { 1, *Bus 0 * - Host 0
+** 3, *Bus 1 *
+** 11, *Bus 2 *
+** -1, -1, *Buses 3-4 *
+** 13, *Bus 5 *
+** -1, -1, *Buses 6-7 *
+** 15, *Bus 8 *
+** -1, -1, *Buses 9-10 *
+** 17, *Bus 11 *
+** -1, -1, *Buses 12-13*
+** 7, *Bus 14 *
+** 19, *Bus 15 *
+** -1, -1, *Buses 16-17*
+** 21, *Bus 18 *
+** -1, -1, *Buses 19-20*
+** 23, *Bus 21 *
+** -1, -1, *Buses 22-23*
+** 25, *Bus 24 *
+** -1, -1, *Buses 25-26*
+**
+** 28, *Bus 27 * - Host 1
+** 30, *Bus 28 *
+** 38, *Bus 29 *
+** -1, -1, *Buses 30-31*
+** 40, *Bus 32 *
+** -1, -1, *Buses 33-34*
+** 42, *Bus 35 *
+** -1, -1, *Buses 36-37*
+** 44, *Bus 38 *
+** -1, -1, *Buses 39-40*
+** 34, *Bus 41 *
+** 46, *Bus 42 *
+** -1, -1, *Buses 43-44*
+** 48, *Bus 45 *
+** -1, -1, *Buses 46-47*
+** 50, *Bus 48 *
+** -1, -1, *Buses 49-50*
+** 52, *Bus 51 *
+** -1, -1 *Buses 52-53*
+** }
+*/
+
+static int pci_busnum_indx[MAX_PCI_NODES];
+
+/*
+** Array of subordinate bus numbers for each bus.
+** Leaf bus nodes just return their own bus number.
+** The input to this array is a bus number.
+**
+** For example, with two Bus Level 0 nodes, two Bus Level 1
+** nodes, four Bus Level 2 nodes, and two Bus Level 3 nodes,
+** (for a maximum node count of 54) the array would look
+** like this:
+**
+** {
+** * HOST 0 *
+** 26, *Bus 0* 13, *Bus 1* 4, *Bus 2* 3, *Bus 3*
+** 4, *Bus 4* 7, *Bus 5* 6, *Bus 6* 7, *Bus 7*
+** 10, *Bus 8* 9, *Bus 9* 10, *Bus 10* 13, *Bus 11*
+** 12, *Bus 12* 13, *Bus 13* 26, *Bus 14* 17, *Bus 15*
+** 16, *Bus 16* 17, *Bus 17* 20, *Bus 18* 19, *Bus 19*
+** 20, *Bus 20* 23, *Bus 21* 22, *Bus 22* 23, *Bus 23*
+** 26, *Bus 24* 25, *Bus 25* 26, *Bus 26*
+**
+** * HOST 1 *
+** 53, *Bus 27* 40, *Bus 28* 31, *Bus 29* 30, *Bus 30*
+** 31, *Bus 31* 34, *Bus 32* 33, *Bus 33* 34, *Bus 34*
+** 37, *Bus 35* 36, *Bus 36* 37, *Bus 37* 40, *Bus 38*
+** 39, *Bus 39* 40, *Bus 40* 53, *Bus 41* 44, *Bus 42*
+** 43, *Bus 43* 44, *Bus 44* 47, *Bus 45* 46, *Bus 46*
+** 47, *Bus 47* 50, *Bus 48* 49, *Bus 49* 50, *Bus 50*
+** 53, *Bus 51* 52, *Bus 52* 53 *Bus 53*
+** }
+*/
+
+static int pci_sub_busnum[MAX_PCI_NODES];
+
+/*
+** Array to hold bus number allocation status,
+** i.e. allocated (PCI_BUS_ALLOC) or not
+** allocated (PCI_BUS_NOT_ALLOC).
+*/
+
+static unsigned char pci_busnum_alloc_status[MAX_PCI_NODES];
+
+/*
+** Array to hold amount (in bytes) of available PCI
+** I/O space size per bus level.
+*/
+
+static unsigned long pci_bus_io_size[MAX_PCI_LEVELS];
+
+/*
+** Array to hold amount (in bytes) of available PCI
+** memory space size per bus level.
+*/
+
+static unsigned long pci_bus_mem_size[MAX_PCI_LEVELS];
+
+/*
+** Array to hold amount (in bytes) of available PCI
+** 20-bit memory space size per bus level.
+*/
+
+static unsigned long pci_bus_mem20_size[MAX_PCI_LEVELS];
+
+/*
+** Array to hold amount (in bytes) of available PCI
+** prefetchable memory space size per bus level.
+*/
+
+static unsigned long pci_bus_mempf_size[MAX_PCI_LEVELS];
+
+/*
+** Some common error messages.
+*/
+
+static char no_bus_struct[] = "no PCI-2-PCI bridge bus structure";
+
+static char no_dev_struct[] = "no PCI-2-PCI bridge device structure";
+
+
+
+
+
+/*
+** pci_alloc_businit - PCI Bus Number Allocation Initialization
+**
+** This is the PCI bus number allocation initialization
+** function. It will fill in the pci_busnum_perlevel[],
+** pci_busnum_indx[], and pci_sub_busnum[] arrays per the
+** Bus Level 0 (CONFIG_PCI_BUSLVL0_NODES),
+** Bus Level 1 (CONFIG_PCI_BUSLVL1_NODES),
+** Bus Level 2 (CONFIG_PCI_BUSLVL2_NODES), and
+** Bus Level 3 (CONFIG_PCI_BUSLVL3_NODES)
+** node configuration parameters.
+**
+** It will then set the entries in the bus number
+** allocation array, pci_busnum_alloc_status[], to "not
+** allocated" (PCI_BUS_NOT_ALLOC).
+**
+** Finally, it will initialize the PCI I/O and memory
+** space arrays (i.e. pci_bus_io_size[], pci_bus_mem_size[],
+** pci_bus_mem20_size[], and pci_bus_mempf_size[]) for
+** available space per node at each bus level.
+*/
+
+__initfunc(int pci_alloc_businit(void))
+{
+ unsigned int busnum; /* Current Bus Number */
+
+ unsigned int l0sub; /* Bus Level 0 Subordinate Bus Number */
+ unsigned int l0cnt; /* Bus Level 0 Count */
+ unsigned int l0indx; /* Bus Level 0 Index */
+
+ unsigned int l1sub; /* Bus Level 1 Subordinate Bus Number */
+ unsigned int l1cnt; /* Bus Level 1 Count */
+ unsigned int l1indx; /* Bus Level 1 Index */
+
+ unsigned int l2sub; /* Bus Level 2 Subordinate Bus Number */
+ unsigned int l2cnt; /* Bus Level 2 Count */
+ unsigned int l2indx; /* Bus Level 2 Index */
+
+ unsigned int l3sub; /* Bus Level 3 Subordinate Bus Number */
+ unsigned int l3cnt; /* Bus Level 3 Count */
+ unsigned int l3indx; /* Bus Level 3 Index */
+
+ unsigned int indx; /* Just An Array Index */
+
+ unsigned long size; /* PCI Memory or I/O Space Size */
+
+ int ret_code; /* Function Return Code */
+
+ char *func; /* Function Name */
+
+ /*
+ ** Validate the maximum node count against the
+ ** maximum allowed for bus nodes.
+ */
+
+ func = "pci_alloc_businit";
+
+ ret_code = PCI_OK;
+
+ if ((unsigned int)MAX_PCI_NODES == 0)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)MAX_PCI_NODES > 255)
+ ret_code = PCI_ERR;
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Invalid number of bus nodes.
+ */
+
+ pci_kern_err(func, "invalid number of bus nodes");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the I/O space address definitions.
+ */
+
+ if ((unsigned int)CONFIG_PCI_IO_START > (unsigned int)CONFIG_PCI_IO_END)
+ ret_code = PCI_ERR;
+
+ if (((unsigned int)CONFIG_PCI_IO_END - (unsigned int)CONFIG_PCI_IO_START) < 0x1000)
+ ret_code = PCI_ERR;
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Invalid I/O space addresses.
+ */
+
+ pci_kern_err(func, "invalid PCI I/O space addresses");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the 20-bit memory space address definitions.
+ */
+
+ if ((unsigned int)CONFIG_PCI_MEM20_END > 0x000fffff)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_MEM20_START > (unsigned int)CONFIG_PCI_MEM20_END)
+ ret_code = PCI_ERR;
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Invalid 20-bit memory space addresses.
+ */
+
+ pci_kern_err(func, "invalid PCI 20-bit memory space addresses");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the memory space address definitions.
+ */
+
+ if ((unsigned int)CONFIG_PCI_MEM_START < (unsigned int)CONFIG_PCI_MEM20_END)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_MEM_START > (unsigned int)CONFIG_PCI_MEM_END)
+ ret_code = PCI_ERR;
+
+ if (((unsigned int)CONFIG_PCI_MEM_END - (unsigned int)CONFIG_PCI_MEM_START) < 0x00100000)
+ ret_code = PCI_ERR;
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Invalid memory space addresses.
+ */
+
+ pci_kern_err(func, "invalid PCI memory space addresses");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the prefetchable memory space address definitions.
+ */
+
+ if ((unsigned int)CONFIG_PCI_MEMPF_START > (unsigned int)CONFIG_PCI_MEMPF_END)
+ ret_code = PCI_ERR;
+
+ if (((unsigned int)CONFIG_PCI_MEMPF_END - (unsigned int)CONFIG_PCI_MEMPF_START) < 0x00100000)
+ ret_code = PCI_ERR;
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Invalid prefetchable memory space addresses.
+ */
+
+ pci_kern_err(func, "invalid PCI prefetchable memory space addresses");
+
+ return (PCI_ERR);
+ }
+
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ /*
+ ** Validate the I/O space size definition for the AGP bridge.
+ */
+
+ if ((unsigned int)CONFIG_PCI_AGP_IO_SIZE > ((unsigned int)(CONFIG_PCI_IO_END + 1) - (unsigned int)CONFIG_PCI_IO_START))
+ {
+ /*
+ ** Invalid I/O space size for the AGP bridge.
+ */
+
+ pci_kern_err(func, "invalid I/O size for AGP bridge");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the memory space size definition for the AGP bridge.
+ */
+
+ if ((unsigned int)CONFIG_PCI_AGP_MEM_SIZE > ((unsigned int)(CONFIG_PCI_MEM_END + 1) - (unsigned int)CONFIG_PCI_MEM_START))
+ {
+ /*
+ ** Invalid memory space size for the AGP bridge.
+ */
+
+ pci_kern_err(func, "invalid memory size for AGP bridge");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the prefetchable memory space size definition
+ ** for the AGP bridge.
+ */
+
+ if ((unsigned int)CONFIG_PCI_AGP_MEMPF_SIZE > ((unsigned int)(CONFIG_PCI_MEMPF_END + 1) - (unsigned int)CONFIG_PCI_MEMPF_START))
+ {
+ /*
+ ** Invalid prefetchable memory space size for the AGP bridge.
+ */
+
+ pci_kern_err(func, "invalid prefetchable memory size for AGP bridge");
+
+ return (PCI_ERR);
+ }
+#endif /* CONFIG_PCI_AGP_BRIDGE */
+
+ /*
+ ** Validate the PCI local IRQs.
+ */
+
+ if ((unsigned int)CONFIG_PCI_LOCAL_PIRQA > 255)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_LOCAL_PIRQB > 255)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_LOCAL_PIRQC > 255)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_LOCAL_PIRQD > 255)
+ ret_code = PCI_ERR;
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Invalid PCI local IRQ.
+ */
+
+ pci_kern_err(func, "invalid PCI local IRQ");
+
+ return (PCI_ERR);
+ }
+
+#ifdef CONFIG_PCI_MULTI_DOMAIN
+ /*
+ ** Validate the PCI remote IRQs.
+ */
+
+ if ((unsigned int)CONFIG_PCI_REMOTE_PIRQA > 255)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_REMOTE_PIRQB > 255)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_REMOTE_PIRQC > 255)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_REMOTE_PIRQD > 255)
+ ret_code = PCI_ERR;
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Invalid PCI remote IRQ.
+ */
+
+ pci_kern_err(func, "invalid PCI remote IRQ");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the PCI local domain bridge device/function.
+ */
+
+ if ((unsigned int)CONFIG_PCI_LOCAL_DEV == 0x00)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_LOCAL_DEV > 0xff)
+ ret_code = PCI_ERR;
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Invalid PCI local domain bridge device/function.
+ */
+
+ pci_kern_err(func, "invalid PCI local domain bridge device/function");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the PCI remote domain bridge device/function.
+ */
+
+ if ((unsigned int)CONFIG_PCI_REMOTE_DEV == 0x00)
+ ret_code = PCI_ERR;
+
+ if ((unsigned int)CONFIG_PCI_REMOTE_DEV > 0xff)
+ ret_code = PCI_ERR;
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Invalid PCI remote domain bridge device/function.
+ */
+
+ pci_kern_err(func, "invalid PCI remote domain bridge device/function");
+
+ return (PCI_ERR);
+ }
+#endif /* CONFIG_PCI_MULTI_DOMAIN */
+
+ /*
+ ** Validate the device's cache line size.
+ */
+
+ if ((unsigned int)CONFIG_PCI_CACHE_LINE_SIZE > 255)
+ {
+ /*
+ ** Invalid cache line size.
+ */
+
+ pci_kern_err(func, "invalid device cache line size");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the devices' latency timer value.
+ */
+
+ if ((unsigned int)CONFIG_PCI_LATENCY_TIMER > 255)
+ {
+ /*
+ ** Invalid latency timer value.
+ */
+
+ pci_kern_err(func, "invalid device latency timer value");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Validate the bridges' secondary latency timer value.
+ */
+
+ if ((unsigned int)CONFIG_PCI_SEC_LATENCY_TIMER > 255)
+ {
+ /*
+ ** Invalid secondary latency timer value.
+ */
+
+ pci_kern_err(func, "invalid bridge secondary latency timer value");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Initialize the bus number, then loop
+ ** through the "Bus Level 0" node count.
+ */
+
+ busnum = 0;
+
+ for (l0cnt = 0; l0cnt < CONFIG_PCI_BUSLVL0_NODES; ++l0cnt)
+ {
+ /*
+ ** Generate "Bus Level 0" index, then
+ ** set "Bus Level 0" node bus number in
+ ** the array. Also save it as the "Bus
+ ** Level 0" subordinate bus number.
+ */
+
+ l0indx = BUSLVL1_NODES * l0cnt;
+ l0indx += l0cnt;
+
+ pci_busnum_perlevel[l0indx] = l0sub = busnum;
+
+ /*
+ ** Generate starting "Bus Level 1" index. Then
+ ** set the starting index of bus children for
+ ** this bus number and increment the bus number.
+ */
+
+ l1indx = l0indx + 1;
+
+ pci_busnum_indx[busnum++] = l1indx;
+
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ /*
+ ** Reserve this bus number for the AGP PCI-2-PCI
+ ** bridge device.
+ */
+
+ ++busnum;
+#endif
+
+ /*
+ ** Loop through the "Bus Level 1" node count.
+ */
+
+ for (l1cnt = 0; l1cnt < CONFIG_PCI_BUSLVL1_NODES; ++l1cnt)
+ {
+ /*
+ ** Set "Bus Level 1" node bus number in
+ ** the array. Also save it as the "Bus
+ ** Level 1" subordinate bus number.
+ */
+
+ pci_busnum_perlevel[l1indx++] = l1sub = busnum;
+
+ /*
+ ** Generate starting "Bus Level 2". Then
+ ** set the starting index of bus children
+ ** for this bus number and increment the
+ ** bus number.
+ */
+
+ l2indx = ( CONFIG_PCI_BUSLVL1_NODES + l0indx + 1 );
+ l2indx += ( CONFIG_PCI_BUSLVL2_NODES * l1cnt );
+
+ pci_busnum_indx[busnum++] = l2indx;
+
+ /*
+ ** Loop through the "Bus Level 2" node count.
+ */
+
+ for (l2cnt = 0; l2cnt < CONFIG_PCI_BUSLVL2_NODES; ++l2cnt)
+ {
+ /*
+ ** Set "Bus Level 2" node bus number in
+ ** the array. Also save it as the "Bus
+ ** Level 2" subordinate bus number.
+ */
+
+ pci_busnum_perlevel[l2indx++] = l2sub = busnum;
+
+ /*
+ ** Generate starting "Bus Level 3". Then
+ ** set the starting index of bus children
+ ** for this bus number and increment the
+ ** bus number.
+ */
+
+ l3indx = ( CONFIG_PCI_BUSLVL1_NODES + l0indx + 1 );
+ l3indx += ( CONFIG_PCI_BUSLVL1_NODES * CONFIG_PCI_BUSLVL2_NODES );
+
+ l3indx += ( CONFIG_PCI_BUSLVL2_NODES * CONFIG_PCI_BUSLVL3_NODES * l1cnt );
+ l3indx += ( CONFIG_PCI_BUSLVL3_NODES * l2cnt );
+
+ pci_busnum_indx[busnum++] = l3indx;
+
+ /*
+ ** Loop through the "Bus Level 3" node count.
+ */
+
+ for (l3cnt = 0; l3cnt < CONFIG_PCI_BUSLVL3_NODES; ++l3cnt)
+ {
+ /*
+ ** Set "Bus Level 3" node bus number in
+ ** the array. Also save it as the "Bus
+ ** Level 3" subordinate bus number.
+ */
+
+ pci_busnum_perlevel[l3indx++] = l3sub = busnum;
+
+ /*
+ ** Set "no more bus children" flag in
+ ** the child index array and increment
+ ** the bus number.
+ */
+
+ pci_busnum_indx[busnum++] = -1;
+
+ /*
+ ** Set "Bus Level 3" subordinate bus number.
+ ** This is a leaf node, thus it has the
+ ** same number.
+ */
+
+ pci_sub_busnum[l3sub] = l3sub;
+ }
+
+ /*
+ ** Set "Bus Level 2" subordinate bus number.
+ */
+
+ pci_sub_busnum[l2sub] = busnum - 1;
+ }
+
+ /*
+ ** Set "Bus Level 1" subordinate bus number.
+ */
+
+ pci_sub_busnum[l1sub] = busnum - 1;
+ }
+
+ /*
+ ** Set "Bus Level 0" subordinate bus number.
+ */
+
+ pci_sub_busnum[l0sub] = busnum - 1;
+ }
+
+ /*
+ ** Clear the bus number allocation array.
+ */
+
+ for (indx = 0; indx < MAX_PCI_NODES; ++indx)
+ pci_busnum_alloc_status[indx] = PCI_BUS_NOT_ALLOC;
+
+ /*
+ ** Set bus level 0 PCI "spaces". This is based upon
+ ** the ending address minus the starting address,
+ ** divided by the maximum number of "Bus Level 0"
+ ** nodes.
+ */
+
+ pci_bus_io_size[0] = (CONFIG_PCI_IO_END + 1);
+ pci_bus_io_size[0] -= CONFIG_PCI_IO_START;
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ pci_bus_io_size[0] -= CONFIG_PCI_AGP_IO_SIZE;
+#endif
+ pci_bus_io_size[0] /= CONFIG_PCI_BUSLVL0_NODES;
+
+ pci_bus_mem_size[0] = (CONFIG_PCI_MEM_END + 1);
+ pci_bus_mem_size[0] -= CONFIG_PCI_MEM_START;
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ pci_bus_mem_size[0] -= CONFIG_PCI_AGP_MEM_SIZE;
+#endif
+ pci_bus_mem_size[0] /= CONFIG_PCI_BUSLVL0_NODES;
+
+ pci_bus_mempf_size[0] = (CONFIG_PCI_MEMPF_END + 1);
+ pci_bus_mempf_size[0] -= CONFIG_PCI_MEMPF_START;
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ pci_bus_mempf_size[0] -= CONFIG_PCI_AGP_MEMPF_SIZE;
+#endif
+ pci_bus_mempf_size[0] /= CONFIG_PCI_BUSLVL0_NODES;
+
+ pci_bus_mem20_size[0] = (CONFIG_PCI_MEM20_END + 1);
+ pci_bus_mem20_size[0] -= CONFIG_PCI_MEM20_START;
+
+ /*
+ ** Set PCI "spaces" for each subordinate
+ ** bus level, i.e. "Bus Level 1" and on.
+ */
+
+ for (indx = 1; indx < MAX_PCI_LEVELS; ++indx)
+ {
+ /*
+ ** Clear the space sizes at this level.
+ */
+
+ pci_bus_io_size[indx] = 0;
+ pci_bus_mem_size[indx] = 0;
+ pci_bus_mem20_size[indx] = 0;
+ pci_bus_mempf_size[indx] = 0;
+
+ /*
+ ** Check to see if we have any nodes
+ ** at this level.
+ */
+
+ if (pci_max_busnodes_perlevel[indx] != 0)
+ {
+ /*
+ ** Generate PCI I/O space.
+ */
+
+ size = pci_bus_io_size[indx - 1];
+ size /= (pci_max_busnodes_perlevel[indx] * CONFIG_PCI_BUSLVL0_NODES);
+
+ if (size > 0)
+ {
+ if (size > PCI_ALIGN_IO)
+ size &= ~(PCI_ALIGN_IO - 1);
+ else
+ size = PCI_ALIGN_IO;
+
+ pci_bus_io_size[indx] = size;
+ }
+
+ /*
+ ** Generate PCI memory space.
+ */
+
+ size = pci_bus_mem_size[indx - 1];
+ size /= (pci_max_busnodes_perlevel[indx] * CONFIG_PCI_BUSLVL0_NODES);
+
+ if (size > 0)
+ {
+ if (size > PCI_ALIGN_MEM)
+ size &= ~(PCI_ALIGN_MEM - 1);
+ else
+ size = PCI_ALIGN_MEM;
+
+ pci_bus_mem_size[indx] = size;
+ }
+
+ /*
+ ** Generate PCI prefetchable memory space.
+ */
+
+ size = pci_bus_mempf_size[indx - 1];
+ size /= (pci_max_busnodes_perlevel[indx] * CONFIG_PCI_BUSLVL0_NODES);
+
+ if (size > 0)
+ {
+ if (size > PCI_ALIGN_MEM)
+ size &= ~(PCI_ALIGN_MEM - 1);
+ else
+ size = PCI_ALIGN_MEM;
+
+ pci_bus_mempf_size[indx] = size;
+ }
+ }
+ }
+
+ /*
+ ** Everything is OK!
+ */
+
+ return (PCI_OK);
+}
+
+
+
+
+
+#if (CONFIG_PCI_BUSLVL0_NODES > 1)
+/*
+** pci_alloc_hosts - Allocate Bus Nubmers For Host Bridge Devices
+**
+** This function will probe the PCI bus for Host
+** Bridge Devices and reconfigure their bus numbers.
+** This is done to prevent possible PCI bus access
+** problems during the initial scanning.
+*/
+
+__initfunc(int pci_alloc_hosts(void))
+{
+ struct pci_host *phost; /* Pointer to Current Host */
+
+ unsigned int number; /* Bus Number */
+
+ unsigned int devfn; /* Device/Function Number */
+
+ unsigned int buses; /* Buses Config. Register */
+
+ int numhosts; /* Number of Hosts */
+
+ struct pci_host hosts[CONFIG_PCI_BUSLVL0_NODES];
+
+ /*
+ ** Initialize the number of Host Bridge devices. Then
+ ** loop through each bus/dev to find Host Bridges.
+ */
+
+ numhosts = 0;
+
+ for (number = 0; number <= MAX_PCI_BUS; ++number)
+ {
+ /*
+ ** Look for a Host Bridge on this bus.
+ */
+
+ if (pci_find_host(number, &devfn) == PCI_OK)
+ {
+ /*
+ ** We have found one. Check to see if we
+ ** have exceeded the number of configurable
+ ** Host Bridge devices.
+ */
+
+ if (numhosts >= CONFIG_PCI_BUSLVL0_NODES)
+ {
+ /*
+ ** We have exceeded the number of
+ ** configurable Host Bridge devices.
+ */
+
+ pci_kern_err("pci_alloc_hosts", "too many Host Bridge devices");
+
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Set the host structure pointer, along
+ ** with the device/function and current
+ ** bus number for the Host Bridge device.
+ */
+
+ phost = &(hosts[numhosts]);
+
+ phost->devfn = devfn;
+ phost->number = number;
+
+ /*
+ ** Set the new primray, secondary, and
+ ** subordinate bus numbers for the Host
+ ** Bridge device.
+ */
+
+ phost->primary = 0;
+
+ if (numhosts != 0)
+ {
+ phost->primary = hosts[numhosts - 1].subordinate;
+ phost->primary += 1;
+ }
+
+ phost->secondary = phost->primary;
+ phost->subordinate = pci_sub_busnum[phost->primary];
+
+ /*
+ ** Increment the number of hosts.
+ */
+
+ ++numhosts;
+ }
+ }
+
+ /*
+ ** Starting with the last Host Bridge device,
+ ** reconfigure the bus numbers for each host.
+ */
+
+ while (numhosts-- > 0)
+ {
+ /*
+ ** Set the host structure pointer. Then
+ ** set the new Subordinate, Primary, and
+ ** Secondary bus numbers.
+ */
+
+ phost = &(hosts[numhosts]);
+
+ buses = 0;
+
+ buses = (buses << 8) | phost->subordinate;
+ buses = (buses << 8) | phost->secondary;
+ buses = (buses << 8) | phost->primary;
+
+ pcibios_write_config_dword(phost->number, phost->devfn, PCI_PRIMARY_BUS, buses);
+ }
+
+ /*
+ ** Everything is ok!
+ */
+
+ return (PCI_OK);
+}
+#endif /* (CONFIG_PCI_BUSLVL0_NODES > 1) */
+
+
+
+
+
+#ifdef CONFIG_PCI_AGP_BRIDGE
+/*
+** pci_agp_bridge - Is Device An AGP Bridge
+**
+** This function will determine if the given device
+** is an AGP bridge device (TRUE) or not (FALSE).
+**
+** NOTE: This list will need to be filled in with
+** future AGP bridge devices.
+*/
+
+int
+pci_agp_bridge(struct pci_bus *pbus, unsigned int devfn)
+{
+ unsigned short vendor; /* Vendor ID */
+
+ unsigned short device; /* Device ID */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** Clear the return code. Then, determine if the
+ ** device is an AGP bridge or not.
+ */
+
+ ret_code = FALSE;
+
+ pcibios_read_config_word(pbus->number, devfn, PCI_VENDOR_ID, &vendor);
+
+ pcibios_read_config_word(pbus->number, devfn, PCI_DEVICE_ID, &device);
+
+ switch (vendor)
+ {
+ case PCI_VENDOR_ID_INTEL:
+ {
+ switch (device)
+ {
+ case 0x7181: /* Intel 440LX - 82443LX AGP bridge */
+ case 0x7191: /* Intel 440BX/ZX - 82443BX/ZX AGP bridge */
+ case 0x71a1: /* Intel 440GX - 82443GX AGP bridge */
+ {
+ ret_code = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ ** Return function result.
+ */
+
+ return (ret_code);
+}
+#endif /* CONFIG_PCI_AGP_BRIDGE */
+
+
+
+
+
+/*
+** pci_find_level - Determine PCI Bus Level
+**
+** This function will return the PCI bus level for
+** the given bus node.
+*/
+
+static int
+pci_find_level(struct pci_bus *pbus)
+{
+ struct pci_bus *nbus; /* Pointer To Next Bus Parent */
+
+ unsigned int bus_level; /* Current Bus Level */
+
+ /*
+ ** Initialize the bus level value, then
+ ** find the actual level of the bus node.
+ */
+
+ bus_level = 0;
+
+ for (nbus = pbus->parent; nbus != (struct pci_bus *)NULL; nbus = nbus->parent)
+ ++bus_level;
+
+ return (bus_level);
+}
+
+
+
+
+
+/*
+** pci_alloc_busnum - PCI Bus Number Allocation
+**
+** This is the PCI bus number allocation function. It will
+** allocate secondary and subordinate bus numbers.
+*/
+
+int
+pci_alloc_busnum(struct pci_bus *pbus, unsigned int devfn)
+{
+ unsigned long flags; /* CPU Interrupt Flags */
+
+ int bus_level; /* Current Bus Level */
+
+ int bus_num; /* Current Bus Number */
+
+ int child_indx; /* Child Bus Index */
+
+ int i; /* Just An Array Index */
+
+ char *func; /* Function Name */
+
+ /*
+ ** Initialize the bus number and the bus
+ ** level. Then check for bus level 0.
+ */
+
+ func = "pci_alloc_busnum";
+
+ bus_num = 0;
+
+ bus_level = pci_find_level(pbus);
+
+ if (bus_level == 0)
+ {
+ /*
+ ** We are at bus level 0. Disable interrupts
+ ** for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Look for free bus numbers for this host node.
+ */
+
+ for (i = 0; i < pci_max_busnodes_perlevel[0]; ++i)
+ {
+ if (pci_busnum_alloc_status[bus_num] == PCI_BUS_NOT_ALLOC)
+ {
+ pci_busnum_alloc_status[bus_num] = PCI_BUS_ALLOC;
+
+ break;
+ }
+
+ bus_num += (pci_sub_busnum[bus_num] + 1);
+ }
+
+ /*
+ ** Restore interrupts.
+ */
+
+ restore_flags(flags);
+
+ /*
+ ** Did we find free host bus numbers at this
+ ** level? If not, then set the bus number
+ ** to indicate an error.
+ */
+
+ if (i < pci_max_busnodes_perlevel[0])
+ {
+ /*
+ ** We have free host bus numbers. Hence, set
+ ** the primary, secondary, and subordinate
+ ** bus numbers.
+ */
+
+ pbus->number = bus_num;
+ pbus->primary = bus_num;
+ pbus->secondary = bus_num;
+ pbus->subordinate = pci_sub_busnum[bus_num];
+
+ return (PCI_OK);
+ }
+
+ pci_kern_err(func, "couldn't find free bus numbers for the Host bridge");
+
+ return (-ENOSPC);
+ }
+ else
+ {
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ /*
+ ** Check to see if this is an AGP bridge device.
+ */
+
+ if (pci_agp_bridge(pbus->parent, devfn) == TRUE)
+ {
+ /*
+ ** Check the bus level. An AGP bridge device
+ ** can only be at bus level 1.
+ */
+
+ if (bus_level == 1)
+ {
+ /*
+ ** We are an AGP bridge device. Look for free
+ ** bus numbers for this bridge.
+ */
+
+ save_flags(flags);
+
+ bus_num = (pbus->parent)->secondary + 1;
+
+ if (pci_busnum_alloc_status[bus_num] == PCI_BUS_NOT_ALLOC)
+ {
+ /*
+ ** We have free AGP bridge bus numbers. Hence,
+ ** set the primary, secondary, and subordinate
+ ** bus numbers.
+ */
+
+ pci_busnum_alloc_status[bus_num] = PCI_BUS_ALLOC;
+
+ restore_flags(flags);
+
+ pbus->number = bus_num;
+ pbus->primary = (pbus->parent)->secondary;
+ pbus->secondary = bus_num;
+ pbus->subordinate = bus_num;
+
+ return (PCI_OK);
+ }
+
+ /*
+ ** Couldn't find free bus numbers for the
+ ** AGP bridge device.
+ */
+
+ restore_flags(flags);
+
+ pci_kern_err(func, "couldn't find free bus numbers for the AGP bridge");
+
+ return (-ENOSPC);
+ }
+
+ /*
+ ** An AGP bridge device is only allowed at
+ ** bus level 1.
+ */
+
+ pci_kern_err(func, "an AGP bridge is only allowed at bus level 1");
+
+ return (-EACCES);
+ }
+#endif /* CONFIG_PCI_AGP_BRIDGE */
+
+ /*
+ ** Get the bus child index. If no child buses
+ ** at this level, then display an error message
+ ** and return an error.
+ */
+
+ child_indx = pci_busnum_indx[(pbus->parent)->secondary];
+
+ if (child_indx != -1)
+ {
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Initialize the bus number (not found), then
+ ** allocate the child bus.
+ */
+
+ bus_num = -1;
+
+ for (i = 0; i < pci_max_busnodes_perlevel[bus_level]; ++i)
+ {
+ bus_num = pci_busnum_perlevel[child_indx + i];
+
+ if (pci_busnum_alloc_status[bus_num] == PCI_BUS_NOT_ALLOC)
+ {
+ pci_busnum_alloc_status[bus_num] = PCI_BUS_ALLOC;
+
+ break;
+ }
+
+ bus_num = -1;
+ }
+
+ /*
+ ** Restore interrupts.
+ */
+
+ restore_flags(flags);
+
+ /*
+ ** Did we find free bus numbers at this level?
+ */
+
+ if (bus_num != -1)
+ {
+ /*
+ ** Set the primary, secondary, and
+ ** subordinate bus numbers.
+ */
+
+ pbus->number = bus_num;
+ pbus->primary = (pbus->parent)->secondary;
+ pbus->secondary = bus_num;
+ pbus->subordinate = pci_sub_busnum[bus_num];
+
+ return (PCI_OK);
+ }
+
+ pci_kern_err(func, "couldn't find free bus numbers");
+
+ return (-ENOSPC);
+ }
+
+ pci_kern_err(func, "no child bus numbers");
+
+ return (-ENODEV);
+ }
+}
+
+
+
+
+/*
+** pci_alloc_busres - PCI Bus Resource Allocation
+**
+** This is the PCI bus resource allocation function. It will
+** allocate I/O and memory space from it's parent. 64-bit
+** and prefetch memory space are not allocated for bus nodes.
+*/
+
+int
+pci_alloc_busres(struct pci_bus *pbus)
+{
+ struct pci_res *pres; /* Pointer To Bus Resources */
+
+ struct pci_dev *pdev; /* Pointer to Bus Device */
+
+ unsigned long flags; /* CPU Interrupt Flags */
+
+ unsigned int indx; /* Resource Index */
+
+ unsigned int host_num; /* Host Number */
+
+ int bus_level; /* Current Bus Level */
+
+ char *func; /* Function Name */
+
+#if (CONFIG_PCI_BUSLVL0_NODES > 1)
+ unsigned int bus_min; /* Host Minimum Bus Number */
+
+ unsigned int bus_max; /* Host Maximum Bus Number */
+#endif
+
+ /*
+ ** First, set the function name for possible error
+ ** messages. Then, ensure that there is a P2P bridge
+ ** device structure associated with this bus.
+ */
+
+ func = "pci_alloc_busres";
+
+ pdev = pbus->self;
+
+ if (pdev != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Next, initialize the bus level and
+ ** host number.
+ */
+
+ bus_level = pci_find_level(pbus);
+
+ host_num = 0;
+
+#if (CONFIG_PCI_BUSLVL0_NODES > 1)
+ /*
+ ** Initialize the starting minimum bus number.
+ ** Then loop until the host number is generated.
+ */
+
+ for (bus_min = 0; host_num < pci_max_busnodes_perlevel[0]; ++host_num)
+ {
+ /*
+ ** Set the maximum bus number, which is the
+ ** subordinate bus number for the minimum
+ ** bus number.
+ */
+
+ bus_max = pci_sub_busnum[bus_min];
+
+ /*
+ ** Compare the bus number against the minimum
+ ** and maximum numbers. If within range, then
+ ** we have found our host number.
+ */
+
+ if ((pbus->number >= bus_min) && (pbus->number <= bus_max))
+ break;
+
+ /*
+ ** Set the next minimum bus number, which is
+ ** just one more than the maximum number.
+ */
+
+ bus_min = bus_max + 1;
+ }
+#endif
+
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ /*
+ ** Does this bridge have a parent? If not, then it
+ ** is a host bridge and not a P2P bridge.
+ */
+
+ if (pbus->parent != (struct pci_bus *)NULL)
+ {
+ /*
+ ** Check to see if this is an AGP bridge device.
+ */
+
+ if (pci_agp_bridge(pbus->parent, pdev->devfn) == TRUE)
+ {
+ /*
+ ** Check the bus level. An AGP bridge device
+ ** can only be at bus level 1.
+ */
+
+ if (bus_level == 1)
+ {
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Set the AGP bridge device's PCI bus node resources
+ ** here starting with the PCI I/O space resource.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_IO]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_IO;
+ pres->align = PCI_ALIGN_IO;
+ pres->size = CONFIG_PCI_AGP_IO_SIZE;
+
+ pres = &((pdev->bus)->resources[PCI_RES_INDX_IO]);
+ pres->size += CONFIG_PCI_AGP_IO_SIZE;
+
+ /*
+ ** Set the PCI memory resource.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEM]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_MEM;
+ pres->align = PCI_ALIGN_MEM;
+ pres->size = CONFIG_PCI_AGP_MEM_SIZE;
+
+ pres = &((pdev->bus)->resources[PCI_RES_INDX_MEM]);
+ pres->size += CONFIG_PCI_AGP_MEM_SIZE;
+
+ /*
+ ** Clear the PCI 20-bit memory resource.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEM20]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_MEM20;
+ pres->align = PCI_ALIGN_MEM20;
+ pres->size = 0;
+
+ /*
+ ** Set the PCI prefetchable memory resource.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEMPF]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_MEMPF;
+ pres->align = PCI_ALIGN_MEM;
+ pres->size = CONFIG_PCI_AGP_MEMPF_SIZE;
+
+ pres = &((pdev->bus)->resources[PCI_RES_INDX_MEMPF]);
+ pres->size += CONFIG_PCI_AGP_MEMPF_SIZE;
+
+ /*
+ ** Clear the child device resource link lists.
+ */
+
+ pbus->res_head_io = (struct pci_res *)NULL;
+ pbus->res_head_mem = (struct pci_res *)NULL;
+ pbus->res_head_mem20 = (struct pci_res *)NULL;
+ pbus->res_head_mempf = (struct pci_res *)NULL;
+
+ /*
+ ** Restore interrupts.
+ */
+
+ restore_flags(flags);
+
+ /*
+ ** For each node resource, allocate space.
+ */
+
+ for (indx = PCI_RES_INDX_IO; indx <= PCI_RES_INDX_MEMPF; ++indx)
+ {
+ /*
+ ** Set the resource pointer. Then, if there
+ ** is space available, allocate it from the
+ ** parent bus node and link it up.
+ */
+
+ pres = &(pbus->resources[indx]);
+
+ if (pres->size != 0)
+ pci_alloc_devres(pdev, pres, indx);
+ }
+
+ /*
+ ** Everything is A-OK.
+ */
+
+ return (PCI_OK);
+ }
+
+ /*
+ ** An AGP bridge device is only allowed at
+ ** bus level 1.
+ */
+
+ pci_kern_err(func, "an AGP bridge is only allowed at bus level 1");
+
+ return (-EACCES);
+ }
+ }
+#endif /* CONFIG_PCI_AGP_BRIDGE */
+
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Set the PCI bus node resources here
+ ** starting with the PCI I/O space resource.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_IO]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_IO;
+ pres->align = PCI_ALIGN_IO;
+ pres->size = pci_bus_io_size[bus_level];
+
+ if (bus_level == 0)
+ {
+ pres->baddr = pci_bus_io_size[0];
+ pres->baddr *= host_num;
+ pres->baddr += CONFIG_PCI_IO_START;
+
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ if (host_num != 0)
+ pres->baddr += CONFIG_PCI_AGP_IO_SIZE;
+#endif
+ }
+
+ /*
+ ** Set the PCI memory resource.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEM]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_MEM;
+ pres->align = PCI_ALIGN_MEM;
+ pres->size = pci_bus_mem_size[bus_level];
+
+ if (bus_level == 0)
+ {
+ pres->baddr = pci_bus_mem_size[0];
+ pres->baddr *= host_num;
+ pres->baddr += CONFIG_PCI_MEM_START;
+
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ if (host_num != 0)
+ pres->baddr += CONFIG_PCI_AGP_MEM_SIZE;
+#endif
+ }
+
+ /*
+ ** Set the PCI 20-bit memory resource.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEM20]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_MEM20;
+ pres->align = PCI_ALIGN_MEM20;
+ pres->size = pci_bus_mem20_size[bus_level];
+
+ if ((bus_level == 0) && (host_num == 0))
+ pres->baddr = CONFIG_PCI_MEM20_START;
+
+ /*
+ ** Set the PCI prefetchable memory resource.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEMPF]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_MEMPF;
+ pres->align = PCI_ALIGN_MEM;
+ pres->size = pci_bus_mempf_size[bus_level];
+
+ if (bus_level == 0)
+ {
+ pres->baddr = pci_bus_mempf_size[0];
+ pres->baddr *= host_num;
+ pres->baddr += CONFIG_PCI_MEMPF_START;
+
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ if (host_num != 0)
+ pres->baddr += CONFIG_PCI_AGP_MEMPF_SIZE;
+#endif
+ }
+
+ /*
+ ** Clear the child device resource link lists.
+ */
+
+ pbus->res_head_io = (struct pci_res *)NULL;
+ pbus->res_head_mem = (struct pci_res *)NULL;
+ pbus->res_head_mem20 = (struct pci_res *)NULL;
+ pbus->res_head_mempf = (struct pci_res *)NULL;
+
+ /*
+ ** Restore interrupts.
+ */
+
+ restore_flags(flags);
+
+ /*
+ ** Check for bus level 0 - it's a special case.
+ */
+
+ if (bus_level != 0)
+ {
+ /*
+ ** For each node resource, allocate space.
+ */
+
+ for (indx = PCI_RES_INDX_IO; indx <= PCI_RES_INDX_MEMPF; ++indx)
+ {
+ /*
+ ** Set the resource pointer. Then, if there
+ ** is space available, allocate it from the
+ ** parent bus node and link it up.
+ */
+
+ pres = &(pbus->resources[indx]);
+
+ if (pres->size != 0)
+ pci_alloc_devres(pdev, pres, indx);
+ }
+ }
+
+ /*
+ ** Everything is A-OK.
+ */
+
+ return (PCI_OK);
+ }
+
+ /*
+ ** No P2P bridge device structure.
+ */
+
+ pci_kern_err(func, no_dev_struct);
+
+ return (-ENOLINK);
+}
+
+
+
+
+
+/*
+** pci_alloc_devres - PCI Device Resource Allocation
+**
+** This is the PCI device resource allocation function. It will
+** allocate I/O and memory space from it's parent bus. A linked
+** list of resources is maintained in the parent node. There
+** is one linked list per type. This routine searches on a
+** first-fit basis for a gap to accomodate the new resource
+** and inserts the resource into the list.
+*/
+
+int
+pci_alloc_devres(struct pci_dev *pdev, struct pci_res *pres, int bar)
+{
+ struct pci_bus *pbus; /* Parent Bus Node Pointer */
+
+ struct pci_res *pres_bus; /* Bus Node Resource Pointer */
+
+ struct pci_res **pres_head; /* Resource Head Pointer */
+
+ struct pci_res *pres_cur; /* Current Resource Pointer */
+
+ struct pci_res *pres_nxt; /* Next Resource Pointer */
+
+ unsigned long flags; /* CPU Interrupt Flags */
+
+ unsigned long baddr; /* Base Address */
+
+ unsigned long align; /* Base Address Alignment */
+
+ long size; /* PCI Space Size */
+
+ long gap; /* PCI Space Gap */
+
+ char *func; /* Function Name */
+
+ char err_msg[256]; /* Error Message */
+
+ /*
+ ** First, set the function name for possible error
+ ** messages. Then, ensure that there is a P2P bridge
+ ** bus structure associated with this device.
+ */
+
+ func = "pci_alloc_devres";
+
+ pbus = pdev->bus;
+
+ if (pbus != (struct pci_bus *)NULL)
+ {
+#ifndef CONFIG_PCI_BUS_0_DEVICES
+ /*
+ ** Check for a Bus 0 non-P2P bridge device.
+ */
+
+ if ((pbus->number == 0) && ((pdev->class >> 8) != PCI_CLASS_BRIDGE_PCI))
+ {
+ u32 base_reg; /* Base Address Register */
+
+ u8 base; /* Base Register Offset */
+
+ /*
+ ** Bus 0 non-PCI-2-PCI device resources are allocated
+ ** by the BIOS and are static. Hence, just read the
+ ** Base Address register then adjust the resource
+ ** type and pointers based upon the value in the
+ ** Base Address register.
+ */
+
+ base = PCI_BASE_ADDRESS_0 + (bar << 2);
+
+ pci_read_config_dword(pdev, base, &base_reg);
+
+ if ((base_reg & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+ {
+ /*
+ ** PCI I/O space. Set PCI I/O variables.
+ */
+
+ baddr = base_reg & PCI_BASE_ADDRESS_IO_MASK;
+
+ pres_head = &(pbus->res_head_io);
+
+ pres->type = PCI_RES_TYPE_IO;
+ pres->align = pres->size;
+ }
+ else
+ {
+ /*
+ ** PCI memory space. Set default PCI
+ ** memory variables.
+ */
+
+ baddr = base_reg & PCI_BASE_ADDRESS_MEM_MASK;
+
+ pres_head = &(pbus->res_head_mem);
+
+ pres->type = PCI_RES_TYPE_MEM;
+ pres->align = pres->size;
+
+ /*
+ ** Is it a 64-bit address?
+ */
+
+ if ((base_reg & PCI_BASE_ADDRESS_MEM_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
+ {
+#if (BITS_PER_LONG == 64)
+ /*
+ ** 64-bit address. Thus, do a double read.
+ */
+
+ base = PCI_BASE_ADDRESS_0 + ((bar + 1) << 2);
+
+ pci_read_config_dword(pdev, base, &base_reg);
+
+ baddr = base_reg;
+
+ baddr <<= 32;
+
+ base = PCI_BASE_ADDRESS_0 + (bar << 2);
+
+ pci_read_config_dword(pdev, base, &base_reg);
+
+ baddr |= (base_reg & PCI_BASE_ADDRESS_MEM_MASK);
+#else
+ printk("PCI: Unable to handle 64-bit address for device %02x:%02x\n",
+ pbus->number, pdev->devfn);
+#endif
+ }
+
+ /*
+ ** Prefetchable memory?
+ */
+
+ if ((base_reg & PCI_BASE_ADDRESS_MEM_PREFETCH) != 0)
+ {
+ /*
+ ** Prefetchable memory. Set PCI
+ ** prefetch memory variables.
+ */
+
+ pres_head = &(pbus->res_head_mempf);
+
+ pres->type = PCI_RES_TYPE_MEMPF;
+ }
+
+ /*
+ ** Check to see if address is below 1M.
+ */
+
+ if (baddr < 0x00100000UL)
+ {
+ /*
+ ** Below 1M. Set PCI memory variables.
+ */
+
+ pres_head = &(pbus->res_head_mem20);
+
+ pres->type = PCI_RES_TYPE_MEM20;
+ }
+ }
+
+ /*
+ ** Clear the next field and set the
+ ** Base Address register field.
+ */
+
+ pres->next = (struct pci_res *)NULL;
+ pres->baddr = baddr;
+
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Is this the first entry into the list?
+ */
+
+ if ((*pres_head) == (struct pci_res *)NULL)
+ {
+ /*
+ ** This is the first entry in the linked list.
+ */
+
+ (*pres_head) = pres;
+ }
+ else
+ {
+ /*
+ ** Should this be the new first entry?
+ */
+
+ if ((*pres_head)->baddr > baddr)
+ {
+ /*
+ ** This is the new first entry in the linked list.
+ */
+
+ pres->next = (*pres_head);
+
+ (*pres_head) = pres;
+ }
+ else
+ {
+ /*
+ ** Find the entry point in the list.
+ */
+
+ pres_cur = (*pres_head);
+
+ while (pres_cur->next != (struct pci_res *)NULL)
+ {
+ if ((pres_cur->next)->baddr > baddr)
+ {
+ pres->next = pres_cur->next;
+
+ break;
+ }
+ else
+ pres_cur = pres_cur->next;
+ }
+
+ pres_cur->next = pres;
+ }
+ }
+
+ /*
+ ** Restore interrupts and return.
+ */
+
+ restore_flags(flags);
+
+ return (PCI_OK);
+ }
+#endif /* CONFIG_PCI_BUS_0_DEVICES */
+
+ /*
+ ** Determine which resource we will
+ ** allocate from.
+ */
+
+ switch (pres->type)
+ {
+ /*
+ ** PCI I/O space
+ */
+
+ case PCI_RES_TYPE_IO:
+ {
+ pres_bus = &(pbus->resources[PCI_RES_INDX_IO]);
+ pres_head = &(pbus->res_head_io);
+
+ break;
+ }
+
+ /*
+ ** PCI memory space
+ */
+
+ case PCI_RES_TYPE_MEM:
+ {
+ pres_bus = &(pbus->resources[PCI_RES_INDX_MEM]);
+ pres_head = &(pbus->res_head_mem);
+
+ break;
+ }
+
+ /*
+ ** PCI 20-bit memory space
+ */
+
+ case PCI_RES_TYPE_MEM20:
+ {
+ pres_bus = &(pbus->resources[PCI_RES_INDX_MEM20]);
+ pres_head = &(pbus->res_head_mem20);
+
+ break;
+ }
+
+ /*
+ ** PCI prefetch memory space
+ */
+
+ case PCI_RES_TYPE_MEMPF:
+ {
+ pres_bus = &(pbus->resources[PCI_RES_INDX_MEMPF]);
+ pres_head = &(pbus->res_head_mempf);
+
+ break;
+ }
+
+ default:
+ {
+ /*
+ ** Return an error if the child/parent resource
+ ** structure is not setup properly.
+ */
+
+ sprintf(err_msg, "unknown resource type for bus %d, devfn = 0x%02x, bar = %d",
+ pbus->number,
+ pdev->devfn,
+ bar);
+
+ pci_kern_err(func, err_msg);
+
+ return (-EIDRM);
+ }
+ }
+
+ /*
+ ** Get the PCI size and alignment values.
+ */
+
+ size = pres->size;
+ align = pres->align;
+
+ /*
+ ** Use a first fit algorithim for allocating the bus
+ ** address. There are four possible scenarios when
+ ** inserting into the resource list.
+ **
+ ** 1. This is a empty list and insertion happens at the
+ ** head.
+ **
+ ** 2. This is a non empty list and there is room at the
+ ** head of the list. Insertion happens at the head
+ ** of the list.
+ **
+ ** 3. This is a non empty list. Scanning for gaps in list
+ ** succeeds and insertion happens in between two
+ ** existing entries.
+ **
+ ** 4. This is a non empty list. Scanning for gaps fails
+ ** and insertion happens at the end of the list.
+ **
+ **
+ ** Scenario 1: Empty list
+ */
+
+ save_flags(flags);
+
+ if (*pres_head == (struct pci_res *)NULL)
+ {
+ /*
+ ** This is the first entry in the linked list.
+ */
+
+ pres->next = *pres_head;
+
+ *pres_head = pres;
+
+ /*
+ ** The bus address is the start address of the bus.
+ */
+
+ pres->baddr = PCI_ALIGN_ADDR(pres_bus->baddr, align);
+
+ /*
+ ** Restore interrupts and return.
+ */
+
+ restore_flags(flags);
+
+ return (PCI_OK);
+ }
+
+ /*
+ ** Scenario 2: Non Empty list
+ **
+ ** First, check if there is a gap at the head.
+ */
+
+ gap = (*pres_head)->baddr - pres_bus->baddr;
+
+ if (gap > size)
+ {
+ /*
+ ** Do an address alignment first.
+ */
+
+ baddr = PCI_ALIGN_ADDR(pres_bus->baddr, align);
+
+#ifdef CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+ /*
+ ** Is this an I/O address?
+ */
+
+ if (pres->type == PCI_RES_TYPE_IO)
+ {
+ /*
+ ** Check for an "unusable ISA address". If
+ ** so, then adjust for a "usable ISA address".
+ */
+
+ if ((baddr & 0x0300) != 0)
+ baddr = PCI_ALIGN_ADDR(baddr, 0x400);
+ }
+#endif
+
+ /*
+ ** Do a size check.
+ */
+
+ gap = (*pres_head)->baddr - baddr;
+
+ if (gap > size)
+ {
+ /*
+ ** We can fit the resource at the head. Thus,
+ ** setup the linked list.
+ */
+
+ pres->next = (*pres_head);
+
+ (*pres_head) = pres;
+
+ /*
+ ** The bus address is the start address of the bus
+ */
+
+ pres->baddr = baddr;
+
+ /*
+ ** Restore interrupts and return.
+ */
+
+ restore_flags(flags);
+
+ return (PCI_OK);
+ }
+ }
+
+ /*
+ ** Scenario 3: Non Empty list
+ **
+ ** Check if there is a gap in the middle of the linked list.
+ */
+
+ pres_cur = (*pres_head);
+ pres_nxt = pres_cur->next;
+
+ while (pres_nxt != (struct pci_res *)NULL)
+ {
+ /*
+ ** This check speeds up the search.
+ */
+
+ gap = pres_nxt->baddr - (pres_cur->baddr + pres_cur->size);
+
+ if (gap > size )
+ {
+ /*
+ ** Do an address alignment first.
+ */
+
+ baddr = pres_cur->baddr + pres_cur->size;
+ baddr = PCI_ALIGN_ADDR(baddr, align);
+
+#ifdef CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+ /*
+ ** Is this an I/O address?
+ */
+
+ if (pres->type == PCI_RES_TYPE_IO)
+ {
+ /*
+ ** Check for an "unusable ISA address". If
+ ** so, then adjust for a "usable ISA address".
+ */
+
+ if ((baddr & 0x0300) != 0)
+ baddr = PCI_ALIGN_ADDR(baddr, 0x400);
+ }
+#endif
+
+ /*
+ ** Do a size check.
+ */
+
+ gap = pres_nxt->baddr - baddr;
+
+ if (gap > size)
+ {
+ /*
+ ** This is an aligned fit. Setup the
+ ** linked list.
+ */
+
+ pres->next = pres_nxt;
+ pres_cur->next = pres;
+
+ /*
+ ** The bus address is the start address
+ ** of the bus.
+ */
+
+ pres->baddr = baddr;
+
+ /*
+ ** Restore interrupts and return.
+ */
+
+ restore_flags(flags);
+
+ return (PCI_OK);
+ }
+ }
+
+ /*
+ ** Try next one.
+ */
+
+ pres_cur = pres_nxt;
+ pres_nxt = pres_cur->next;
+ }
+
+ /*
+ ** Scenario 4: Non Empty list
+ **
+ ** Current pointer is at end of list. Thus,
+ ** append to the list. First, check here to
+ ** see that we are within bounds. If no space
+ ** to allocate the BAR resource, then return
+ ** an error.
+ */
+
+ baddr = pres_cur->baddr + pres_cur->size;
+ baddr = PCI_ALIGN_ADDR(baddr, align);
+
+#ifdef CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+ /*
+ ** Is this an I/O address?
+ */
+
+ if (pres->type == PCI_RES_TYPE_IO)
+ {
+ /*
+ ** Check for an "unusable ISA address". If
+ ** so, then adjust for a "usable ISA address".
+ */
+
+ if ((baddr & 0x0300) != 0)
+ baddr = PCI_ALIGN_ADDR(baddr, 0x400);
+ }
+#endif
+
+ /*
+ ** Do a size check.
+ */
+
+ if ((baddr + size) <= (pres_bus->baddr + pres_bus->size))
+ {
+ /*
+ ** Setup the linked list.
+ */
+
+ pres->next = pres_nxt;
+ pres_cur->next = pres;
+
+ /*
+ ** The bus address is the start address of the bus.
+ */
+
+ pres->baddr = baddr;
+
+ /*
+ ** Restore interrupts and return.
+ */
+
+ restore_flags(flags);
+
+ return (PCI_OK);
+ }
+
+ /*
+ ** Restore interrupts. Then display an error message
+ ** and return an errorj
+ */
+
+ restore_flags(flags);
+
+ pci_kern_err(func, "no space left");
+
+ return (-ENOMEM);
+ }
+
+ /*
+ ** No P2P bridge bus structure.
+ */
+
+ pci_kern_err(func, no_bus_struct);
+
+ return (-ENOLINK);
+}
+
+
+
+
+
+/*
+** pci_free_busnum - Free PCI Bus Number
+**
+** This function will free the PCI bus number for
+** re-allocation.
+*/
+
+int
+pci_free_busnum(struct pci_bus *pbus)
+{
+ pci_busnum_alloc_status[pbus->secondary] = PCI_BUS_NOT_ALLOC;
+
+ return (PCI_OK);
+}
+
+
+
+
+
+/*
+** pci_free_busres - Free PCI Bus Resources
+**
+** This is the free PCI bus resources function. It will
+** re-allocate I/O and memory space to it's parent.
+*/
+
+int
+pci_free_busres(struct pci_bus *pbus)
+{
+ struct pci_res *pres; /* Pointer To Bus Resources */
+
+ struct pci_dev *pdev; /* Pointer to Bus Device */
+
+ unsigned long flags; /* CPU Interrupt Flags */
+
+ unsigned int indx; /* Resource Index */
+
+ int bus_level; /* Current Bus Level */
+
+ char *func; /* Function Name */
+
+ /*
+ ** First, set the function name for possible error
+ ** messages. Then, initialize the bus level.
+ */
+
+ func = "pci_free_busres";
+
+ bus_level = pci_find_level(pbus);
+
+ /*
+ ** Next, ensure child resources have been freed for
+ ** this bus.
+ */
+
+ if ((pbus->res_head_io == (struct pci_res *)NULL)
+ && (pbus->res_head_mem == (struct pci_res *)NULL)
+ && (pbus->res_head_mem20 == (struct pci_res *)NULL)
+ && (pbus->res_head_mempf == (struct pci_res *)NULL))
+ {
+ /*
+ ** Check for bus level 0 - it's a special case.
+ */
+
+ if (bus_level != 0)
+ {
+ /*
+ ** Ensure that there is a P2P bridge device
+ ** structure associated with this bus.
+ */
+
+ pdev = pbus->self;
+
+ if (pdev == (struct pci_dev *)NULL)
+ {
+ /*
+ ** No P2P bridge device structure.
+ */
+
+ pci_kern_err(func, no_dev_struct);
+
+ return (-ENOLINK);
+ }
+
+ /*
+ ** For each node resource, free the space.
+ */
+
+ for (indx = PCI_RES_INDX_IO; indx <= PCI_RES_INDX_MEMPF; ++indx)
+ {
+ /*
+ ** Set the resource pointer. Then, if space
+ ** has been allocated, free it back to the
+ ** parent bus node and link it up.
+ */
+
+ pres = &(pbus->resources[indx]);
+
+ if (pres->size != 0)
+ pci_free_devres(pdev, pres);
+ }
+ }
+
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Free PCI I/O resources.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_IO]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_NOTUSED;
+ pres->align = 0;
+ pres->size = 0;
+ pres->baddr = 0;
+
+ /*
+ ** Free PCI memory resources.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEM]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_NOTUSED;
+ pres->align = 0;
+ pres->size = 0;
+ pres->baddr = 0;
+
+ /*
+ ** Free PCI 20-bit memory resources.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEM20]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_NOTUSED;
+ pres->align = 0;
+ pres->size = 0;
+ pres->baddr = 0;
+
+ /*
+ ** Free PCI prefetch memory resources.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEMPF]);
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_NOTUSED;
+ pres->align = 0;
+ pres->size = 0;
+ pres->baddr = 0;
+
+ /*
+ ** Restore interrupts and return.
+ */
+
+ restore_flags(flags);
+
+ return (PCI_OK);
+ }
+
+ /*
+ ** Child resources not freed.
+ */
+
+ pci_kern_err(func, "child resources not freed");
+
+ return (-ENOTEMPTY);
+}
+
+
+
+
+
+/*
+** pci_free_devres - Free PCI Device Resources
+**
+** This is the free PCI device resources function. It will
+** re-allocate I/O and memory space to it's parent.
+*/
+
+int
+pci_free_devres(struct pci_dev *pdev, struct pci_res *pres)
+{
+ struct pci_bus *pbus; /* Parent Bus Node Pointer */
+
+ struct pci_res **pres_head; /* Resource Head Pointer */
+
+ struct pci_res *pres_prv; /* Previous Resource Pointer */
+
+ unsigned long flags; /* CPU Interrupt Flags */
+
+ char *func; /* Function Name */
+
+ /*
+ ** First, set the function name for possible error
+ ** messages. Then, ensure that there is a P2P bridge
+ ** bus structure associated with this device.
+ */
+
+ func = "pci_free_devres";
+
+ pbus = pdev->bus;
+
+ if (pbus != (struct pci_bus *)NULL)
+ {
+ /*
+ ** Setup pointer to the device and parent resource
+ ** structures. Then determine which resource we will
+ ** allocate from.
+ */
+
+ switch (pres->type)
+ {
+ /*
+ ** PCI I/O space
+ */
+
+ case PCI_RES_TYPE_IO:
+ {
+ pres_head = &(pbus->res_head_io);
+ break;
+ }
+
+ /*
+ ** PCI memory space
+ */
+
+ case PCI_RES_TYPE_MEM:
+ {
+ pres_head = &(pbus->res_head_mem);
+ break;
+ }
+
+ /*
+ ** PCI 20-bit memory space
+ */
+
+ case PCI_RES_TYPE_MEM20:
+ {
+ pres_head = &(pbus->res_head_mem20);
+ break;
+ }
+
+ /*
+ ** PCI prefetch memory space
+ */
+
+ case PCI_RES_TYPE_MEMPF:
+ {
+ pres_head = &(pbus->res_head_mempf);
+ break;
+ }
+
+ /*
+ ** Unused PCI resource
+ */
+
+ case PCI_RES_TYPE_NOTUSED:
+ {
+ return (PCI_OK);
+ }
+
+ default:
+ {
+ /*
+ ** Return an error if the child/parent resource
+ ** structure is not setup properly.
+ */
+
+ pci_kern_err(func, "child/parent resource structure not setup");
+
+ return (-EIDRM);
+ }
+ }
+
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** The resource being removed can be the first on the
+ ** list and, hence, has no previous entry. The other
+ ** case is that the the resource has a previous entry.
+ */
+
+ if (*pres_head == pres)
+ {
+ /*
+ ** Case 1: First on the list
+ **
+ ** Make the next in the list the resource head.
+ */
+
+ *pres_head = pres->next;
+ }
+ else
+ {
+ /*
+ ** Case 2: search the linked list for the entry.
+ */
+
+ pres_prv = *pres_head;
+
+ while ((pres_prv != (struct pci_res *)NULL) && (pres_prv->next != pres))
+ pres_prv = pres_prv->next;
+
+ /*
+ ** If we have come to the end of the list without
+ ** finding the resource, the list is somehow busted.
+ */
+
+ if (pres_prv == (struct pci_res *)NULL)
+ {
+ /*
+ ** Restore interrupts.
+ */
+
+ restore_flags(flags);
+
+ pci_kern_err(func, "resource structure not on list");
+
+ return (-ENOENT);
+ }
+
+ /*
+ ** We have found the previous entry, fix the
+ ** list pointers.
+ */
+
+ pres_prv->next = pres->next;
+ }
+
+ /*
+ ** Clear the entry.
+ */
+
+ pres->next = (struct pci_res *)NULL;
+ pres->type = PCI_RES_TYPE_NOTUSED;
+ pres->align = 0;
+ pres->size = 0;
+ pres->baddr = 0;
+
+ /*
+ ** Restore interrupts and return.
+ */
+
+ restore_flags(flags);
+
+ return (PCI_OK);
+ }
+
+ /*
+ ** No P2P bridge bus structure.
+ */
+
+ pci_kern_err(func, no_bus_struct);
+
+ return (-ENOLINK);
+}
diff -u -r --new-file linux/drivers/pci/pci_conf.c linux_mot/drivers/pci/pci_conf.c
--- linux/drivers/pci/pci_conf.c Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/pci_conf.c Tue Jun 8 10:36:04 1999
@@ -0,0 +1,1532 @@
+/*
+** PCI Bus/Device Node Configuration
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_res.h>
+
+#include <asm/errno.h>
+
+
+
+
+
+/*
+**
+** pci_conf_int_line - Configure Interrupt Line Register
+**
+** This function will determine the correct value
+** for the device's Interrupt Line and set it.
+*/
+
+static void
+pci_conf_int_line(struct pci_dev *pdev)
+{
+ u8 irq; /* Interrupt Pin/Line */
+
+ /*
+ ** First, read the Interrupt Pin register. It is
+ ** used to determine the value for the Interrupt
+ ** Line register.
+ */
+
+ pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &irq);
+
+ if (irq != PCI_INT_NONE)
+ {
+#ifndef CONFIG_PCI_BUS_0_DEVICES
+ /*
+ ** Check for a non-bridge Bus 0 device.
+ */
+
+ if ((pdev->bus)->number == 0)
+ {
+ if ((pdev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ {
+ /*
+ ** Bus 0 device resources are configured by
+ ** the BIOS and are static. Hence, just read
+ ** the Interrupt Line register and use it.
+ */
+
+ pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &irq);
+
+ /*
+ ** Set the Interrupt Line register and save the
+ ** IRQ number in the device's structure and exit.
+ */
+
+ pdev->irq = irq;
+
+ return;
+ }
+ }
+#endif
+
+ /*
+ ** Initialize the device's Interrupt Line register.
+ */
+
+ pci_hwints_getirq(pdev);
+ }
+}
+
+
+
+
+
+/*
+**
+** pci_conf_cache - Configure Cache Line Size Register
+**
+** This function will write the Cache Line Size
+** register with the configuration value.
+*/
+
+static void
+pci_conf_cache(struct pci_dev *pdev)
+{
+#ifndef CONFIG_PCI_BUS_0_DEVICES
+ /*
+ ** Check for a non-bridge Bus 0 device. If so,
+ ** just return because resources are configured
+ ** by the BIOS and are static.
+ */
+
+ if ((pdev->bus)->number == 0)
+ if ((pdev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ return;
+#endif
+
+ /*
+ ** Set the Cache Line Size register
+ ** and exit.
+ */
+
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, CONFIG_PCI_CACHE_LINE_SIZE);
+}
+
+
+
+
+
+/*
+**
+** pci_conf_latency - Configure Latency Timer Register
+**
+** This function will write the latency timer
+** register with the configuratino value.
+*/
+
+static void
+pci_conf_latency(struct pci_dev *pdev)
+{
+#ifndef CONFIG_PCI_BUS_0_DEVICES
+ /*
+ ** Check for a non-bridge Bus 0 device. If so,
+ ** just return because resources are configured
+ ** by the BIOS and are static.
+ */
+
+ if ((pdev->bus)->number == 0)
+ if ((pdev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ return;
+#endif
+
+ /*
+ ** Set the Latency Timer register
+ ** and exit.
+ */
+
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, CONFIG_PCI_LATENCY_TIMER);
+}
+
+
+
+
+
+/*
+** pci_conf_cmd - Configure Command Register
+**
+** This function will write the Command register
+** for the device with the configured bits.
+*/
+
+static void
+pci_conf_cmd(struct pci_dev *pdev, u16 cmd)
+{
+ unsigned int number; /* Bus Number */
+
+ unsigned int dev; /* Device Number */
+
+ unsigned int func; /* Function Number */
+
+ unsigned int devfn; /* Device/Function Number */
+
+ unsigned short status; /* Status Register */
+
+ unsigned short class; /* Class Code */
+
+ u16 tmpcmd; /* Temporary Command Register */
+
+ /*
+ ** First, read the current Command register.
+ */
+
+ pci_read_config_word(pdev, PCI_COMMAND, &tmpcmd);
+
+ /*
+ ** Next, ensure the appropriate space enable bit(s)
+ ** are set in the Command register.
+ */
+
+ class = pdev->class >> 8;
+
+ if ((class == PCI_CLASS_BRIDGE_HOST) || (class == PCI_CLASS_BRIDGE_PCI))
+ cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+
+ /*
+ ** Next, check to see if we are a bus master.
+ */
+
+ if (pdev->master == TRUE)
+ {
+ /*
+ ** Set the Enable Master bit.
+ */
+
+ cmd |= PCI_COMMAND_MASTER;
+
+ /*
+ ** Set the Fast Back-to-Back Enable bit.
+ ** Then, search each device on this bus,
+ ** i.e. device 0 to 31.
+ */
+
+ cmd |= PCI_COMMAND_FAST_BACK;
+
+ number = (pdev->bus)->number;
+
+ for (dev = 0; dev <= MAX_PCI_DEV; ++dev)
+ {
+ /*
+ ** Function loop, from 0 to 7.
+ */
+
+ for (func = 0; func <= MAX_PCI_FUNC; ++func)
+ {
+ /*
+ ** Generate the Device/Function number,
+ ** then read and validate the Device ID
+ ** word from the device's configuration
+ ** space.
+ */
+
+ devfn = PCI_DEVFN(dev, func);
+
+ if (pci_valid_devid(number, devfn) == TRUE)
+ {
+ /*
+ ** Read the Status register and check the
+ ** Fast Back-to-Back Capable bit. If not
+ ** set, then clear the bit in the Command
+ ** register.
+ */
+
+ pcibios_read_config_word(number, devfn, PCI_STATUS, &status);
+
+ if ((status & PCI_STATUS_FAST_BACK) == 0)
+ cmd &= ~PCI_COMMAND_FAST_BACK;
+
+ /*
+ ** Check for a multi-function device.
+ */
+
+ if (pci_multi_func(number, devfn) == FALSE)
+ break;
+ }
+ }
+ }
+ }
+
+#ifdef CONFIG_PCI_COMMAND_SPECIAL
+ /*
+ ** Next, set the Special Cycle Recognition bit.
+ */
+
+ cmd |= PCI_COMMAND_SPECIAL;
+#endif
+
+#ifdef CONFIG_PCI_COMMAND_INVALIDATE
+ /*
+ ** Next, set the Memory Write and Invalidate Enable bit.
+ */
+
+ cmd |= PCI_COMMAND_INVALIDATE;
+#endif
+
+#ifdef CONFIG_PCI_COMMAND_PARITY
+ /*
+ ** Next, set the Parity Error Response bit.
+ */
+
+ cmd |= PCI_COMMAND_PARITY;
+#endif
+
+#ifdef CONFIG_PCI_COMMAND_WAIT
+ /*
+ ** Next, set the Wait Cycle Enable bit.
+ */
+
+ cmd |= PCI_COMMAND_WAIT;
+#endif
+
+#ifdef CONFIG_PCI_COMMAND_SERR
+ /*
+ ** Next, set the System Error Enable bit.
+ */
+
+ cmd |= PCI_COMMAND_SERR;
+#endif
+
+ /*
+ ** Finally, "or" in the new command bits and
+ ** write the Command register.
+ */
+
+ cmd |= tmpcmd;
+
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+}
+
+
+
+
+
+/*
+** pci_conf_bridge_ctl - Configure Bridge Control Register
+**
+** This function will write the Bridge Control
+** register for the bridge device with the
+** configured bits.
+*/
+
+static void
+pci_conf_bridge_ctl(struct pci_dev *pdev)
+{
+ unsigned int number; /* Bus Number */
+
+ unsigned int dev; /* Device Number */
+
+ unsigned int func; /* Function Number */
+
+ unsigned int devfn; /* Device/Function Number */
+
+ unsigned short status; /* Status Register */
+
+ u16 brdgctl; /* Bridge Control Register */
+
+ /*
+ ** First, read and save the configuration
+ ** Bridge Control register. This will be
+ ** used later.
+ */
+
+ pci_read_config_word(pdev, PCI_BRIDGE_CONTROL, &brdgctl);
+
+ /*
+ ** Next, set the Fast Back-to-Back Enable bit.
+ ** Then, search each device on the secondary
+ ** bus, i.e. device 0 to 31.
+ */
+
+ brdgctl |= PCI_BRIDGE_CTL_FAST_BACK;
+
+ number = (pdev->bus)->secondary;
+
+ for (dev = 0; dev <= MAX_PCI_DEV; ++dev)
+ {
+ /*
+ ** Function loop, from 0 to 7.
+ */
+
+ for (func = 0; func <= MAX_PCI_FUNC; ++func)
+ {
+ /*
+ ** Generate the Device/Function number,
+ ** then read and validate the Device ID
+ ** word from the device's configuration
+ ** space.
+ */
+
+ devfn = PCI_DEVFN(dev, func);
+
+ if (pci_valid_devid(number, devfn) == TRUE)
+ {
+ /*
+ ** Read the Status register and check the
+ ** Fast Back-to-Back Capable bit. If not
+ ** set, then clear the bit in the Command
+ ** register.
+ */
+
+ pcibios_read_config_word(number, devfn, PCI_STATUS, &status);
+
+ if ((status & PCI_STATUS_FAST_BACK) == 0)
+ brdgctl &= ~PCI_BRIDGE_CTL_FAST_BACK;
+
+ /*
+ ** Check for a multi-function device.
+ */
+
+ if (pci_multi_func(number, devfn) == FALSE)
+ break;
+ }
+ }
+ }
+
+#ifdef CONFIG_PCI_BRIDGE_CTL_PARITY
+ /*
+ ** Next, set the Parity Error Response bit.
+ */
+
+ brdgctl |= PCI_BRIDGE_CTL_PARITY;
+#endif
+
+#ifdef CONFIG_PCI_BRIDGE_CTL_SERR
+ /*
+ ** Next, set the System Error Enable bit.
+ */
+
+ brdgctl |= PCI_BRIDGE_CTL_SERR;
+#endif
+
+#ifdef CONFIG_PCI_BRIDGE_CTL_ISA_MODE
+ /*
+ ** Next, set the ISA Mode bit.
+ */
+
+ brdgctl |= PCI_BRIDGE_CTL_NO_ISA;
+#endif
+
+#ifdef CONFIG_PCI_BRIDGE_CTL_VGA
+ /*
+ ** Next, set the VGA Enable bit
+ */
+
+ brdgctl |= PCI_BRIDGE_CTL_VGA;
+#endif
+
+#ifdef CONFIG_PCI_BRIDGE_CTL_MASTER_ABORT
+ /*
+ ** Next, set the Master Abort Mode bit.
+ */
+
+ brdgctl |= PCI_BRIDGE_CTL_MASTER_ABORT;
+#endif
+
+ /*
+ ** Finally, write the Bridge Control register.
+ */
+
+ pci_write_config_word(pdev, PCI_BRIDGE_CONTROL, brdgctl);
+}
+
+
+
+
+
+/*
+**
+** pci_conf_bar - Determine Base Address Register Requirements
+**
+** This function will determine the memory or I/O space
+** requirements for the given base address register.
+** The PCI specification defines that after 0xffffffff
+** is written to a base address register, the value
+** read back will indicate the size requirements of the
+** base address register. The highest bit set in register
+** can be converted to the address space size.
+*/
+
+static unsigned int
+pci_conf_bar(struct pci_dev *pdev, unsigned int bar, unsigned int *size)
+{
+ struct pci_bus *pbus; /* Device's Bus Structure Pointer */
+
+ unsigned int type; /* Resource Type */
+
+ u32 base_reg; /* Base Address Register */
+
+ u32 saved_base; /* Saved Base Address Register */
+
+ /*
+ ** Write all F's to the base address registers so we
+ ** can later read them back and determine what type
+ ** of space the device needs and how much space it
+ ** needs.
+ */
+
+ bar = PCI_BASE_ADDRESS_0 + (bar << 2);
+
+ pci_read_config_dword(pdev, bar, &saved_base);
+
+ pci_write_config_dword(pdev, bar, 0xffffffff);
+
+ pci_read_config_dword(pdev, bar, &base_reg);
+
+ pci_write_config_dword(pdev, bar, saved_base);
+
+ /*
+ ** Set the resource type and clear the size. Then
+ ** check the base register value. If it is zero,
+ ** then the base register isn't implemented. If
+ ** it is 0xffffffff, then it may be broken.
+ */
+
+ type = PCI_RES_TYPE_NOTUSED;
+
+ *size = 0;
+
+ if ((base_reg != 0) && (base_reg != 0xffffffff))
+ {
+ /*
+ ** Get the parent bus structure pointer. Then
+ ** see if the base register is an I/O type.
+ */
+
+ pbus = pdev->bus;
+
+ if ((base_reg & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+ {
+ /*
+ ** It is an I/O base register. Set the
+ ** resource type if we have space.
+ */
+
+ if (pbus->resources[PCI_RES_INDX_IO].size != 0)
+ type = PCI_RES_TYPE_IO;
+
+ /*
+ ** Adjust the base address register content
+ ** for the I/O bits and initialize the size.
+ */
+
+ base_reg >>= 2;
+
+ *size = 4;
+ }
+ else
+ {
+ /*
+ ** It is a memory base register. Set the
+ ** default resource type to anywhere in
+ ** memory.
+ */
+
+ type = PCI_RES_TYPE_MEM;
+
+ /*
+ ** Is it prefetchable memory?
+ */
+
+ if ((base_reg & PCI_BASE_ADDRESS_MEM_PREFETCH) != 0)
+ {
+ /*
+ ** Prefetchable memory. See if we can locate
+ ** in prefetchable memory space.
+ */
+
+ if (pbus->resources[PCI_RES_INDX_MEMPF].size != 0)
+ type = PCI_RES_TYPE_MEMPF;
+ }
+
+ /*
+ ** Locate below 1MB?
+ */
+
+ if ((base_reg & PCI_BASE_ADDRESS_MEM_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_1M)
+ {
+ /*
+ ** Only bus 0 devices can be mapped below 1MB.
+ ** See if this device is a bus 0 device and if
+ ** we have 20-bit space.
+ */
+
+ if (pbus->number == 0)
+ if (pbus->resources[PCI_RES_INDX_MEM20].size != 0)
+ type = PCI_RES_TYPE_MEM20;
+ }
+
+ /*
+ ** Adjust the base address register content
+ ** for the address memory bits and initialize
+ ** the size.
+ */
+
+ base_reg >>= 4;
+
+ *size = 16;
+ }
+
+ /*
+ ** Did we find a good resource type?
+ */
+
+ if (type != PCI_RES_TYPE_NOTUSED)
+ {
+ /*
+ ** Shift the base register right till a
+ ** 0 bit is seen.
+ */
+
+ while ((base_reg != 0) && ((base_reg & 1) == 0))
+ {
+ /*
+ ** Multiply size by 2 and look for
+ ** another bit in the base address
+ ** register.
+ */
+
+ *size <<= 1;
+
+ base_reg >>= 1;
+ }
+ }
+ }
+
+ /*
+ ** Return the resource type.
+ */
+
+ return (type);
+}
+
+
+
+
+
+/*
+** pci_get_bars - Get Number Of BARs
+**
+** This function will return the number of Base
+** Address registers for the device.
+*/
+
+int
+pci_get_bars(struct pci_dev *pdev, int *num_bars)
+{
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** Initialize the return code, then determine
+ ** the number of Base Address registers we need.
+ */
+
+ ret_code = PCI_OK;
+
+ switch (pdev->hdr_type & 0x7f)
+ {
+ /*
+ ** Standard Header
+ */
+
+ case PCI_HEADER_TYPE_NORMAL:
+ {
+ *num_bars = 6;
+ break;
+ }
+
+ /*
+ ** Bridge Header
+ */
+
+ case PCI_HEADER_TYPE_BRIDGE:
+ {
+ *num_bars = 2;
+ break;
+ }
+
+ /*
+ ** CardBus Bridge Header
+ */
+
+ case PCI_HEADER_TYPE_CARDBUS:
+ {
+ *num_bars = 1;
+ break;
+ }
+
+ /*
+ ** Anything else is an error.
+ */
+
+ default:
+ {
+ *num_bars = 0;
+ ret_code = -EFAULT;
+ }
+ }
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_conf_dev - Configure Device
+**
+** This function will configure memory and I/O space
+** for each function on the given device. 64-bit
+** memory and prefetch memory are not allocated at
+** this time.
+*/
+
+int
+pci_conf_dev(struct pci_dev *pdev)
+{
+ struct pci_res *pres; /* Resource Structure Pointer */
+
+ unsigned int num_bars; /* Maximum Number Of BARs */
+
+ unsigned int bar; /* Base Address Register */
+
+ unsigned int size; /* Size Requirement */
+
+ unsigned int type; /* PCI Space Type */
+
+ unsigned int barindx; /* Base Address Reg. Index */
+
+ u32 base_reg; /* Base Address Register */
+
+ u16 cmd; /* Command Register */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** First, set the Cache Line Size register.
+ */
+
+ pci_conf_cache(pdev);
+
+ /*
+ ** Next, configure the Latency Timer register.
+ */
+
+ pci_conf_latency(pdev);
+
+ /*
+ ** Next, configure the Interrupt Line register.
+ */
+
+ pci_conf_int_line(pdev);
+
+ /*
+ ** Next, determine the number of Base Address
+ ** registers we need to allocate resources for.
+ */
+
+ ret_code = pci_get_bars(pdev, &num_bars);
+
+ for (cmd = 0, bar = 0; (ret_code == PCI_OK) && (bar < num_bars); ++bar)
+ {
+ /*
+ ** Next, get the Base Address Register size and
+ ** resource type. If the size is zero or the
+ ** type is unknown, then we are done.
+ */
+
+ type = pci_conf_bar(pdev, bar, &size);
+
+ if ((size != 0) && (type != PCI_RES_TYPE_NOTUSED))
+ {
+ /*
+ ** Get the current resource structure pointer.
+ ** Then, set the resource type, size, and
+ ** alignment. Then based upon the resource
+ ** type, set command space access enable bit.
+ */
+
+ pres = &(pdev->resources[bar]);
+
+ pres->type = type;
+ pres->size = size;
+ pres->align = size;
+
+ if (type == PCI_RES_TYPE_IO)
+ {
+ /*
+ ** Set command I/O Access Enable.
+ */
+
+ cmd |= PCI_COMMAND_IO;
+ }
+ else
+ {
+ /*
+ ** Set command Memory Access Enable.
+ */
+
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+
+ /*
+ ** Allocate device memory and I/O resources.
+ */
+
+ ret_code = pci_alloc_devres(pdev, pres, bar);
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** If allocated, then write the configuration
+ ** Base Address Register with the allocated
+ ** address value. Also, read it back and
+ ** place the value in the base address register
+ ** array.
+ */
+
+ barindx = PCI_BASE_ADDRESS_0 + (bar << 2);
+
+ base_reg = pres->baddr;
+
+ pci_write_config_dword(pdev, barindx, base_reg);
+
+ pci_read_config_dword(pdev, barindx, &base_reg);
+
+ pdev->base_address[bar] = base_reg;
+
+ /*
+ ** Check for a 64-bit memory register.
+ */
+
+ if ((base_reg & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
+ {
+ if ((base_reg & PCI_BASE_ADDRESS_MEM_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
+ {
+ /*
+ ** It is a 64-bit register. Thus, write the next
+ ** configuration Base Address Register with the
+ ** allocated upper address value. Also, read it
+ ** back and place the value in the base address
+ ** register array.
+ */
+
+#if (BITS_PER_LONG == 64)
+ base_reg = pres->baddr >> 32;
+#else
+ base_reg = 0;
+#endif
+
+ barindx = PCI_BASE_ADDRESS_0 + (++bar << 2);
+
+ pci_write_config_dword(pdev, barindx, base_reg);
+
+ pci_read_config_dword(pdev, barindx, &base_reg);
+
+ pdev->base_address[bar] = base_reg;
+ }
+ }
+
+ }
+ }
+ }
+
+ /*
+ ** Any errors?
+ */
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Configure and write the Command register.
+ */
+
+ pci_conf_cmd(pdev, cmd);
+
+ /*
+ ** If it is a bridge device, then configure and
+ ** write the Bridge Control register.
+ */
+
+ if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ pci_conf_bridge_ctl(pdev);
+ }
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_conf_bus - Configure Bus
+**
+** This function will configure memory and I/O space
+** for the bus and its devices.
+*/
+
+int
+pci_conf_bus(struct pci_bus *pbus)
+{
+ struct pci_bus *child; /* Child Bus Pointer */
+
+ struct pci_dev *pdev; /* Device Structure Pointer */
+
+ struct pci_res *pres; /* Pointer To Bus Resources */
+
+ unsigned int class; /* Class Code */
+
+ u32 memupper; /* Base/Limit Upper 32 Bits */
+
+ u16 membaddr; /* Memory Base Address */
+
+ u16 membase; /* Memory Base register */
+
+ u16 iobaddr; /* I/O Base Address */
+
+ u8 iobase; /* I/O Base Register */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** First, allocate bus resources.
+ */
+
+ ret_code = pci_alloc_busres(pbus);
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Next, configure the bridge device first,
+ ** if it's an actual bridge.
+ */
+
+ pdev = pbus->self;
+
+ if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ {
+ /*
+ ** Set the Secondary Latency Timer register.
+ */
+
+ pci_write_config_byte(pdev, PCI_SEC_LATENCY_TIMER, CONFIG_PCI_SEC_LATENCY_TIMER);
+
+ /*
+ ** Next, shut off PCI I/O space. Then read
+ ** the I/O Base register to be used later to
+ ** determine the bridge's I/O range.
+ */
+
+ pci_write_config_byte(pdev, PCI_IO_BASE, 0xf0);
+
+ pci_write_config_byte(pdev, PCI_IO_LIMIT, 0x00);
+
+ pci_write_config_word(pdev, PCI_IO_BASE_UPPER16, 0xffff);
+
+ pci_write_config_word(pdev, PCI_IO_LIMIT_UPPER16, 0x0000);
+
+ pci_read_config_byte(pdev, PCI_IO_BASE, &iobase);
+
+ iobase &= PCI_IO_RANGE_TYPE_MASK;
+
+ /*
+ ** Next, set the I/O resource pointer and see
+ ** if we have any allocated I/O space for this
+ ** this node.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_IO]);
+
+ if (pres->size != 0)
+ {
+ /*
+ ** We have space. Is the I/O decoder correct?
+ */
+
+ if ((iobase == PCI_IO_RANGE_TYPE_16) || (iobase == PCI_IO_RANGE_TYPE_32))
+ {
+ /*
+ ** Set the I/O Base register.
+ */
+
+ iobaddr = pres->baddr >> 8;
+ iobaddr &= 0xf0;
+
+ pci_write_config_byte(pdev, PCI_IO_BASE, (u8)iobaddr);
+
+ /*
+ ** Set the I/O Limit register.
+ */
+
+ iobaddr = (pres->baddr + (pres->size - 1)) >> 8;
+ iobaddr &= 0xf0;
+
+ pci_write_config_byte(pdev, PCI_IO_LIMIT, (u8)iobaddr);
+
+ /*
+ ** Next, see if we need to set the I/O
+ ** Base/Limit Upper 16 Bits registers.
+ */
+
+ if (iobase == PCI_IO_RANGE_TYPE_32)
+ {
+ /*
+ ** Set the I/O Base Upper 16-Bits
+ ** register.
+ */
+
+ iobaddr = pres->baddr >> 16;
+ iobaddr &= 0xffff;
+
+ pci_write_config_word(pdev, PCI_IO_BASE_UPPER16, iobaddr);
+
+ /*
+ ** Set the I/O Limit Upper 16-Bits
+ ** register.
+ */
+
+ iobaddr = (pres->baddr + (pres->size - 1)) >> 16;
+ iobaddr &= 0xffff;
+
+ pci_write_config_word(pdev, PCI_IO_LIMIT_UPPER16, iobaddr);
+ }
+ }
+ }
+
+ /*
+ ** Next, shut off PCI memory space. Then set
+ ** the memory resource pointer and see if we
+ ** have any allocated 32-bit memory for this
+ ** node.
+ */
+
+ pci_write_config_word(pdev, PCI_MEMORY_BASE, 0xffff);
+
+ pci_write_config_word(pdev, PCI_MEMORY_LIMIT, 0x0000);
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEM]);
+
+ if (pres->size != 0)
+ {
+ /*
+ ** Set the Memory Base register.
+ */
+
+ membaddr = pres->baddr >> 16;
+ membaddr &= 0xffff;
+
+ pci_write_config_word(pdev, PCI_MEMORY_BASE, membaddr);
+
+ /*
+ ** Set the Memory Limit register.
+ */
+
+ membaddr = (pres->baddr + (pres->size - 1)) >> 16;
+ membaddr &= 0xffff;
+
+ pci_write_config_word(pdev, PCI_MEMORY_LIMIT, membaddr);
+ }
+
+ /*
+ ** Next, shut off PCI prefetch memory space. Then
+ ** read the Prefetchable Memory Base register to
+ ** be used later to determine the bridge's prefetchable
+ ** memory range.
+ */
+
+ pci_write_config_word(pdev, PCI_PREF_MEMORY_BASE, 0xfff0);
+
+ pci_write_config_word(pdev, PCI_PREF_MEMORY_LIMIT, 0x0000);
+
+ pci_write_config_dword(pdev, PCI_PREF_BASE_UPPER32, 0xffffffff);
+
+ pci_write_config_dword(pdev, PCI_PREF_LIMIT_UPPER32, 0x00000000);
+
+ pci_read_config_word(pdev, PCI_PREF_MEMORY_BASE, &membase);
+
+ membase &= PCI_PREF_RANGE_TYPE_MASK;
+
+ /*
+ ** Next, set the prefetchable memory resource pointer
+ ** and see if we have any allocated prefetchable
+ ** memory for this node and if the memory decoder is
+ ** correct.
+ */
+
+ pres = &(pbus->resources[PCI_RES_INDX_MEMPF]);
+
+ if (pres->size != 0)
+ {
+ /*
+ ** We have space. Is the memory decoder correct?
+ */
+
+ if ((membase == PCI_PREF_RANGE_TYPE_32) || (membase == PCI_PREF_RANGE_TYPE_64))
+ {
+ /*
+ ** Set the Prefetchable Memory
+ ** Base register.
+ */
+
+ membaddr = pres->baddr >> 16;
+ membaddr &= 0xfff0;
+
+ pci_write_config_word(pdev, PCI_PREF_MEMORY_BASE, membaddr);
+
+ /*
+ ** Set the Prefetchable Memory
+ ** Limit register.
+ */
+
+ membaddr = (pres->baddr + (pres->size - 1)) >> 16;
+ membaddr &= 0xfff0;
+
+ pci_write_config_word(pdev, PCI_PREF_MEMORY_LIMIT, membaddr);
+
+ /*
+ ** Next, determine if we need to set the
+ ** Prefetchable Base/Limit Upper 32 Bits registers.
+ */
+
+ if (membase == PCI_PREF_RANGE_TYPE_64)
+ {
+ /*
+ ** Set the Prefetchable Base Upper 32-Bits
+ ** register.
+ */
+
+#if (BITS_PER_LONG == 64)
+ memupper = pres->baddr >> 32;
+#else
+ memupper = 0;
+#endif
+
+ pci_write_config_dword(pdev, PCI_PREF_BASE_UPPER32, memupper);
+
+ /*
+ ** Set the Prefetchable Limit Upper 32-Bits
+ ** register.
+ */
+
+#if (BITS_PER_LONG == 64)
+ memupper = (pres->baddr + (pres->size - 1)) >> 32;
+#else
+ memupper = 0;
+#endif
+
+ pci_write_config_dword(pdev, PCI_PREF_LIMIT_UPPER32, memupper);
+ }
+ }
+ }
+
+ /*
+ ** Finally, do the bridge device.
+ */
+
+ ret_code = pci_conf_dev(pbus->self);
+ }
+
+ /*
+ ** Next, configure each bridge and it's devices
+ ** on the bus.
+ */
+
+ child = pbus->children;
+
+ while ((ret_code == PCI_OK) && (child != (struct pci_bus *)NULL))
+ {
+ /*
+ ** Allocate/assign memory and I/O space to
+ ** each bridge and it's devices on this bus.
+ */
+
+ ret_code = pci_conf_bus(child);
+
+ /*
+ ** Do the next child.
+ */
+
+ child = child->next;
+ }
+
+ /*
+ ** Next, configure each non-bridge device on
+ ** the bus.
+ */
+
+ pdev = pbus->devices;
+
+ while ((ret_code == PCI_OK) && (pdev != (struct pci_dev *)NULL))
+ {
+ /*
+ ** Get the device's class. If it's either a
+ ** Host Bridge or a PCI-2-PCI bridge, then
+ ** don't configure the device.
+ */
+
+ class = pdev->class >> 8;
+
+ if (class != PCI_CLASS_BRIDGE_HOST)
+ if (class != PCI_CLASS_BRIDGE_PCI)
+ ret_code = pci_conf_dev(pdev);
+
+ /*
+ ** Do the next sibling.
+ */
+
+ pdev = pdev->sibling;
+ }
+ }
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+**
+** pci_conf_display - Configure VGA and GFX Display Controllers
+**
+** This function is used to detect and set up all
+** VGA-compatible controllers and non-VGA, GFX,
+** controllers.
+*/
+
+void
+pci_conf_display(void)
+{
+ struct pci_bus *pbus; /* Bus Structure Pointer */
+
+ struct pci_dev *pdev; /* Device Structure Pointer */
+
+ struct pci_dev *pdev_vga; /* VGA Device Structure Pointer */
+
+ struct pci_dev *pdev_gfx; /* GFX Device Structure Pointer */
+
+ unsigned int number; /* Bus Number */
+
+ unsigned int dev; /* Device Number */
+
+ unsigned int func; /* Function Number */
+
+ unsigned short class; /* Class Code */
+
+ u16 cnfgreg; /* Command/Bridge Control Register */
+
+ /*
+ ** Identify the VGA display device to be utilized
+ ** during initialization. This is accomplished by
+ ** first scanning the standard expansion bus (i.e.,
+ ** ISA, EISA or Micro Channel). If the VGA display
+ ** device is found on the expansion bus, that display
+ ** is used during initialization and the display
+ ** configuration process has completed.
+ */
+
+ pdev_vga = (struct pci_dev *)NULL;
+
+ pdev = pci_find_class((PCI_CLASS_BRIDGE_ISA << 8), (struct pci_dev *)NULL);
+
+ if (pdev == (struct pci_dev *)NULL)
+ pdev = pci_find_class((PCI_CLASS_BRIDGE_EISA << 8), (struct pci_dev *)NULL);
+
+ if (pdev == (struct pci_dev *)NULL)
+ pdev = pci_find_class((PCI_CLASS_BRIDGE_MC << 8), (struct pci_dev *)NULL);
+
+ if (pdev != (struct pci_dev *)NULL)
+ {
+ /*
+ ** An expansion bus bridge device has been found.
+ ** Save the bridge's bus and device numbers. Then,
+ ** loop through each function looking for a VGA
+ ** display device.
+ */
+
+ number = (pdev->bus)->number;
+
+ dev = PCI_SLOT(pdev->devfn);
+
+ for (func = 0; func <= MAX_PCI_FUNC; ++func)
+ {
+ /*
+ ** Is there a device here?
+ */
+
+ pdev = pci_find_slot(number, PCI_DEVFN(dev, func));
+
+ if (pdev != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Read the Class register and check for
+ ** a VGA-compatible controller. If so,
+ ** then we are done here.
+ */
+
+ if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+ return;
+ }
+ }
+ }
+
+ /*
+ ** Is a VGA device on the PCI bus?
+ */
+
+ pdev_vga = pci_find_class((PCI_CLASS_DISPLAY_VGA << 8), (struct pci_dev *)NULL);
+
+ if (pdev_vga != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Set the I/O ENABLE and MEMORY ENABLE
+ ** bits in the device's command register
+ ** so it can respond to VGA accesses.
+ */
+
+ pci_read_config_word(pdev_vga, PCI_COMMAND, &cnfgreg);
+
+ cnfgreg |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+
+ pci_write_config_word(pdev_vga, PCI_COMMAND, cnfgreg);
+
+ /*
+ ** Starting at the PCI bus number the VGA
+ ** display device is on, scan the PCI bus
+ ** hierarchy upstream (towards the Host Bridge).
+ */
+
+ pbus = pdev_vga->bus;
+
+ while (pbus->primary != pbus->secondary)
+ {
+ /*
+ ** In each PCI-to-PCI bridge detected, set
+ ** the VGA ENABLE bit in its bridge control
+ ** register.
+ */
+
+ pci_read_config_word(pbus->self, PCI_BRIDGE_CONTROL, &cnfgreg);
+
+ cnfgreg |= PCI_BRIDGE_CTL_VGA;
+
+ pci_write_config_word(pbus->self, PCI_BRIDGE_CONTROL, cnfgreg);
+
+ pbus = pbus->parent;
+ }
+
+ /*
+ ** Starting at the PCI bus number the VGA
+ ** display device is on, scan the PCI buses
+ ** downstream (all buses subordinate to
+ ** this bus) looking for GFXs.
+ */
+
+ pdev_gfx = (struct pci_dev *)NULL;
+
+ for (number = (pdev_vga->bus)->number; number <= (pdev_vga->bus)->subordinate; ++number)
+ {
+ /*
+ ** Device loop, from 0 to 31.
+ */
+
+ for (dev = 0; dev <= MAX_PCI_DEV; ++dev)
+ {
+ /*
+ ** Function loop, from 0 to 7.
+ */
+
+ for (func = 0; func <= MAX_PCI_FUNC; ++func)
+ {
+ /*
+ ** Is there a device here?
+ */
+
+ pdev = pci_find_slot(number, PCI_DEVFN(dev, func));
+
+ if (pdev != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Read the Class register and
+ ** check for a GFX controller.
+ */
+
+ class = pdev->class >> 8;
+
+ if (class != PCI_CLASS_DISPLAY_XGA)
+ if (class != PCI_CLASS_DISPLAY_OTHER)
+ pdev = (struct pci_dev *)NULL;
+ }
+
+ /*
+ ** Was a GFX controller found?
+ */
+
+ if (pdev != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Set the GFX device's I/O ENABLE
+ ** and VGA SNOOP ENABLE bits in the
+ ** device's command register.
+ */
+
+ pdev_gfx = pdev;
+
+ pci_read_config_word(pdev_gfx, PCI_COMMAND, &cnfgreg);
+
+ cnfgreg |= (PCI_COMMAND_IO | PCI_COMMAND_VGA_PALETTE);
+
+ pci_write_config_word(pdev_gfx, PCI_COMMAND, cnfgreg);
+
+ /*
+ ** Scan back upstream from the bus
+ ** the GFX is on towards the bus the
+ ** VGA display device resides on.
+ */
+
+ pbus = pdev_gfx->bus;
+
+ while (pbus->number != (pdev_vga->bus)->number)
+ {
+ /*
+ ** At each PCI-to-PCI bridge
+ ** encountered, set the VGA
+ ** SNOOP ENABLE bit in the
+ ** bridge command register.
+ */
+
+ pci_read_config_word(pbus->self, PCI_COMMAND, &cnfgreg);
+
+ cnfgreg |= PCI_COMMAND_VGA_PALETTE;
+
+ pci_write_config_word(pbus->self, PCI_COMMAND, cnfgreg);
+
+ pbus = pbus->parent;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ ** Was a GFX controller found?
+ */
+
+ if (pdev_gfx != (struct pci_dev *)NULL)
+ {
+ /*
+ ** A GFX controller was found. Set the
+ ** the VGA SNOOP ENABLE bit in the VGA
+ ** display device's command register.
+ */
+
+ pci_read_config_word(pdev_vga, PCI_COMMAND, &cnfgreg);
+
+ cnfgreg |= PCI_COMMAND_VGA_PALETTE;
+
+ pci_write_config_word(pdev_vga, PCI_COMMAND, cnfgreg);
+ }
+ else
+ {
+ /*
+ ** A GFX controller was not found. Clear
+ ** the the VGA SNOOP ENABLE bit in the
+ ** VGA display device's command register.
+ */
+
+ pci_read_config_word(pdev_vga, PCI_COMMAND, &cnfgreg);
+
+ cnfgreg &= ~PCI_COMMAND_VGA_PALETTE;
+
+ pci_write_config_word(pdev_vga, PCI_COMMAND, cnfgreg);
+ }
+
+ /*
+ ** We are done here.
+ */
+
+ return;
+ }
+
+ /*
+ ** We have no VGA device on the PCI bus. Hence,
+ ** we need to reset the SNOOP ENABLE bits.
+ */
+
+ for (pdev = pci_devices; pdev != (struct pci_dev *)NULL; pdev = pdev->next)
+ {
+ /*
+ ** Read the Class register and check for
+ ** a GFX controller.
+ */
+
+ class = pdev->class >> 8;
+
+ if ((class == PCI_CLASS_DISPLAY_XGA) || (class == PCI_CLASS_DISPLAY_OTHER))
+ {
+ /*
+ ** It is a GFX controller. Hence, set
+ ** the the VGA SNOOP ENABLE bit in the
+ ** device's command register.
+ */
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cnfgreg);
+
+ cnfgreg |= PCI_COMMAND_VGA_PALETTE;
+
+ pci_write_config_word(pdev, PCI_COMMAND, cnfgreg);
+ }
+ else
+ {
+ /*
+ ** It is not a GFX controller. Hence, clear
+ ** the the VGA SNOOP ENABLE bit in the device's
+ ** command register.
+ */
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cnfgreg);
+
+ cnfgreg &= ~PCI_COMMAND_VGA_PALETTE;
+
+ pci_write_config_word(pdev, PCI_COMMAND, cnfgreg);
+ }
+
+ /*
+ ** Is it a bridge device?
+ */
+
+ if (class == PCI_CLASS_BRIDGE_PCI)
+ {
+ /*
+ ** In each bridge detected, clear the VGA
+ ** ENABLE bit in its bridge control register.
+ */
+
+ pci_read_config_word(pdev, PCI_BRIDGE_CONTROL, &cnfgreg);
+
+ cnfgreg &= ~PCI_BRIDGE_CTL_VGA;
+
+ pci_write_config_word(pdev, PCI_BRIDGE_CONTROL, cnfgreg);
+ }
+ }
+}
diff -u -r --new-file linux/drivers/pci/pci_hwints.c linux_mot/drivers/pci/pci_hwints.c
--- linux/drivers/pci/pci_hwints.c Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/pci_hwints.c Tue Jun 8 10:36:04 1999
@@ -0,0 +1,292 @@
+/*
+** PCI PIRQ Hardware Interrupt Register Update
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_res.h>
+
+
+
+
+
+/*
+** Array of PCI local domain IRQs.
+*/
+
+static unsigned int pci_localpirqs[4] =
+{
+ CONFIG_PCI_LOCAL_PIRQA,
+ CONFIG_PCI_LOCAL_PIRQB,
+ CONFIG_PCI_LOCAL_PIRQC,
+ CONFIG_PCI_LOCAL_PIRQD
+};
+
+
+#ifdef CONFIG_PCI_MULTI_DOMAIN
+/*
+** Array of PCI remote domain IRQs.
+*/
+
+static unsigned int pci_remotepirqs[4] =
+{
+ CONFIG_PCI_REMOTE_PIRQA,
+ CONFIG_PCI_REMOTE_PIRQB,
+ CONFIG_PCI_REMOTE_PIRQC,
+ CONFIG_PCI_REMOTE_PIRQD
+};
+
+/*
+** PCI remote domain bridge device/function.
+*/
+
+static unsigned int pci_remotedev = CONFIG_PCI_REMOTE_DEV;
+#endif
+
+
+
+
+
+#ifdef CONFIG_PCI_PIRQ_UPDATE
+/*
+** Mapping from PCI vendor/device ID pairs to PIRQ
+** hardware interrupt register update function types
+** and arguments
+*/
+
+typedef int (*pci_hwints_handler)(struct pci_dev *);
+
+struct pci_hwints_info
+{
+ unsigned short vendor; /* Vendor ID */
+ unsigned short device; /* Device ID */
+ pci_hwints_handler handler; /* Function/Handler */
+};
+
+
+
+
+
+/*
+**
+** set_82371 - Intel 82371 ISA Bridge
+**
+** This function will write the IRQ value to the
+** i82371SB's PIIX3 ISA PIRQ register.
+*/
+
+__initfunc(static int set_82371(struct pci_dev *pdev))
+{
+ unsigned int intnum; /* PIRQ Interrupt Number */
+
+ u8 offset; /* PIRQ Register Offset */
+
+ u8 irq; /* Interrupt Pin/Line */
+
+ /*
+ ** Loop through each one.
+ */
+
+ for (intnum = 0; intnum < 4; ++intnum)
+ {
+ /*
+ ** First, read the current IRQ value from the
+ ** i82371's PIRQ PCI configuration register.
+ ** Check to see if it has been initialized by
+ ** the BIOS or not. If it has, then save the
+ ** PIRQ value in the PIRQ array.
+ */
+
+ offset = 0x60 + intnum;
+
+ pci_read_config_byte(pdev, offset, &irq);
+
+ if ((irq & 0x80) != 0)
+ {
+ /*
+ ** This PIRQ PCI configuration register has
+ ** not been initialized. Hence, write the
+ ** IRQ value to the i82371's PIRQ PCI
+ ** configuration register.
+ */
+
+ irq = pci_pirqs[intnum];
+
+ pci_write_config_byte(pdev, offset, 0x80);
+
+ pci_write_config_byte(pdev, offset, irq);
+ }
+ else
+ pci_pirqs[intnum] = irq;
+ }
+
+ /*
+ ** Everything is OK!
+ */
+
+ return (PCI_OK);
+}
+
+
+
+
+
+/*
+** Table of devices and handlers.
+*/
+
+static struct pci_hwints_info pci_hwints_list[] __initdata =
+{
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, set_82371 },
+ { 0xffff, 0xffff, NULL },
+};
+
+
+
+
+
+/*
+**
+** pci_hwints_update_pirqs - Update PIRQ hardware interrupt register
+**
+** This function will call a function/handler to write
+** the given IRQ value to the PIRQ hardware interrupt
+** register for the selected devices.
+*/
+
+__initfunc(int pci_hwints_update_pirqs(void))
+{
+ struct pci_dev *pdev; /* Device Structure Pointer */
+
+ struct pci_hwints_info *pinfo; /* Hardware Info Structure Pointer */
+
+ /*
+ ** Go through each vendor/device in the list
+ ** of hardware interrupt handlers.
+ */
+
+ for (pinfo = pci_hwints_list; pinfo->vendor != 0xffff; ++pinfo)
+ {
+ /*
+ ** Compare the vendor and device IDs. If the same, then
+ ** call the hardware interrupt update handler.
+ */
+
+ pdev = pci_find_device(pinfo->vendor, pinfo->device, (struct pci_dev *)NULL);
+ if (pdev != (struct pci_dev *)NULL)
+ if (pinfo->handler(pdev) != PCI_OK)
+ return (PCI_ERR);
+ }
+
+ /*
+ ** Everything is OK!
+ */
+
+ return (PCI_OK);
+}
+#endif
+
+
+
+
+
+/*
+**
+** pci_hwints_getirq - Return IRQ value
+**
+** This function will return the IRQ value for the
+** given device. It will also update the Interrupt
+** Line register of the device with the value.
+*/
+
+void
+pci_hwints_getirq(struct pci_dev *pdev)
+{
+ struct pci_bus *pbus; /* Parent Bus Structure Pointer */
+
+ unsigned int devnum; /* Accumulated Device Number */
+
+ unsigned int irq; /* IRQ Value */
+
+ /*
+ ** Device Interrupt Line register initialization.
+ */
+
+ devnum = PCI_SLOT(pdev->devfn);
+
+ pbus = pdev->bus;
+
+ /*
+ ** Check to see if this could possibly be a
+ ** peer Host Bridge device.
+ */
+
+ if (pbus->parent != (struct pci_bus *)NULL)
+ {
+ /*
+ ** The IRQ line number will be generated after
+ ** taking into account all the PCI-2-PCI bridge
+ ** devices between the device and the Host Bridge.
+ */
+
+ while ((pbus->parent)->primary != (pbus->parent)->secondary)
+ {
+ devnum += PCI_SLOT((pbus->self)->devfn);
+
+ pbus = pbus->parent;
+ }
+ }
+
+ devnum &= 0x03;
+
+ /*
+ ** By default, get the PCI local domain IRQ value.
+ */
+
+ irq = pci_localpirqs[devnum];
+
+#ifdef CONFIG_PCI_MULTI_DOMAIN
+ /*
+ ** Check to see if this could possibly be a
+ ** peer Host Bridge device.
+ */
+
+ pbus = pdev->bus;
+
+ if (pbus->parent != (struct pci_bus *)NULL)
+ {
+ /*
+ ** Determine if the device is located in the
+ ** remote domain or not. We must find the
+ ** domain's bridge device located on bus 0.
+ */
+
+ while (pbus->primary != 0)
+ pbus = pbus->parent;
+
+ /*
+ ** Check the device/function of domain's bridge
+ ** device against the remote device/function.
+ ** If the same, then the device is located in
+ ** the remote domain. Thus, get the PCI remote
+ ** domain IRQ value.
+ */
+
+ if ((pbus->self)->devfn == pci_remotedev)
+ irq = pci_remotepirqs[devnum];
+ }
+#endif
+
+ /*
+ ** Set the device's Interrupt Line register
+ ** to the IRQ number and save it in the
+ ** device's structure.
+ */
+
+ pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, (u8)irq);
+
+ pdev->irq = irq;
+}
diff -u -r --new-file linux/drivers/pci/pci_node.c linux_mot/drivers/pci/pci_node.c
--- linux/drivers/pci/pci_node.c Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/pci_node.c Tue Jun 8 10:36:04 1999
@@ -0,0 +1,1434 @@
+/*
+** PCI Bus/Device Node Management
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/pci.h>
+#include <linux/pci_res.h>
+
+#include <asm/errno.h>
+#include <asm/system.h>
+
+
+
+
+
+/*
+** pci_add_dev - Add Device Structure
+**
+** This function will allocate a device structure
+** and fill it with the appropriate device information,
+** If the device structure cannot be allocated or
+** if the device header is incorrect, a NULL pointer
+** will be returned.
+*/
+
+int
+pci_add_dev(struct pci_bus *pbus, unsigned int devfn, struct pci_dev **pdev)
+{
+ struct pci_dev *pdev_list; /* PCI Device List Pointer */
+
+ unsigned long flags; /* CPU Interrupt Flags */
+
+ unsigned int cmp_stat; /* Compare Status For Device/Func. */
+
+ int ret_code; /* Function Return Code */
+
+ u32 devid; /* Device/Vendor ID */
+
+ u32 class; /* Configuration Class Code */
+
+ u32 rom_adr; /* Configuration Expansion ROM Base Addr. */
+
+ u16 cmd; /* Configuration Command Register */
+
+ u16 tmp; /* Just A Temporary */
+
+ u8 hdr_type; /* Configuration Header Type */
+
+ char *func; /* Function Name */
+
+ char err_msg[256]; /* Error Message */
+
+ /*
+ ** First, set the function name for possible error
+ ** messages. Then, clear the return code and allocate
+ ** a device structure.
+ */
+
+ func = "pci_add_dev";
+
+ ret_code = PCI_OK;
+
+ *pdev = (struct pci_dev *)kmalloc(sizeof(struct pci_dev), GFP_ATOMIC);
+
+ if (*pdev != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Next, clear it and fill in the bus pointer,
+ ** device, function, and vendor/device IDs.
+ */
+
+ memset(*pdev, 0, sizeof(struct pci_dev));
+
+ (*pdev)->bus = pbus;
+ (*pdev)->devfn = devfn;
+
+ /*
+ ** Get the device ID and put the vendor and
+ ** device IDs into the device structure.
+ */
+
+ pci_read_config_dword(*pdev, PCI_VENDOR_ID, &devid);
+
+ (*pdev)->vendor = devid & 0xffff;
+ (*pdev)->device = (devid >> 16) & 0xffff;
+
+ /*
+ ** Determine if device can be a master. Set
+ ** the master field in the device structure
+ ** appropriately. If the device is not the
+ ** Host Bridge, then disable it.
+ */
+
+ pci_read_config_word(*pdev, PCI_COMMAND, &cmd);
+
+ pci_write_config_word(*pdev, PCI_COMMAND, (cmd | PCI_COMMAND_MASTER));
+
+ pci_read_config_word(*pdev, PCI_COMMAND, &tmp);
+
+ pci_write_config_word(*pdev, PCI_COMMAND, cmd);
+
+ (*pdev)->master = ((tmp & PCI_COMMAND_MASTER) != 0) ? TRUE : FALSE;
+
+ /*
+ ** Read the class code and set it in the
+ ** device structure.
+ */
+
+ pci_read_config_dword(*pdev, PCI_CLASS_REVISION, &class);
+
+ (*pdev)->class = class >> 8;
+
+ /*
+ ** Read the header type and set it in the
+ ** device structure.
+ */
+
+ pci_read_config_byte(*pdev, PCI_HEADER_TYPE, &hdr_type);
+
+ (*pdev)->hdr_type = hdr_type;
+
+ /*
+ ** Next, fill in the remainder of the device
+ ** structure based upon the header type.
+ */
+
+ switch (hdr_type & 0x7f)
+ {
+ /*
+ ** Standard Header
+ */
+
+ case PCI_HEADER_TYPE_NORMAL:
+ {
+ /*
+ ** Check for an invalid class code,
+ ** i.e. PCI-To-PCI Bridge.
+ */
+
+ if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
+ {
+ /*
+ ** Read the ROM Expansion address. Then
+ ** see if it's a valid address.
+ */
+
+ pci_read_config_dword(*pdev, PCI_ROM_ADDRESS, &rom_adr);
+
+ if (rom_adr != 0xffffffff)
+ {
+ /*
+ ** If not a bus 0 device, then disable
+ ** the Expansion ROM Address. Otherwise,
+ ** save the address.
+ */
+
+ if (pbus->number != 0)
+ pci_write_config_dword(*pdev, PCI_ROM_ADDRESS, 0xfffffffe);
+ else
+ (*pdev)->rom_address = rom_adr;
+ }
+ }
+ else
+ ret_code = -EBADF;
+
+ break;
+ }
+
+ /*
+ ** Bridge Header
+ */
+
+ case PCI_HEADER_TYPE_BRIDGE:
+ {
+ /*
+ ** Check for a valid class code,
+ ** i.e. PCI-To-PCI Bridge.
+ */
+
+ if ((class >> 16) == PCI_CLASS_BRIDGE_PCI)
+ {
+ /*
+ ** Read the ROM Expansion address. Then
+ ** see if it's a valid address.
+ */
+
+ pci_read_config_dword(*pdev, PCI_ROM_ADDRESS1, &rom_adr);
+
+ if (rom_adr != 0xffffffff)
+ {
+ /*
+ ** If not a bus 0 bridge, then disable
+ ** the Expansion ROM Address. Otherwise,
+ ** save the address.
+ */
+
+ if (pbus->number != 0)
+ pci_write_config_dword(*pdev, PCI_ROM_ADDRESS1, 0xfffffffe);
+ else
+ (*pdev)->rom_address = rom_adr;
+ }
+ }
+ else
+ ret_code = -EBADF;
+
+ break;
+ }
+
+ /*
+ ** CardBus Bridge Header
+ */
+
+ case PCI_HEADER_TYPE_CARDBUS:
+ {
+ /*
+ ** Check for a valid class code,
+ ** i.e. CardBus Bridge. If so, then
+ ** clear the device error flag.
+ */
+
+ if ((class >> 16) != PCI_CLASS_BRIDGE_PCI)
+ ret_code = -EBADF;
+
+ break;
+ }
+
+ /*
+ ** Unknown header type.
+ */
+
+ default:
+ {
+ /*
+ ** A header error. Display a message and
+ ** free the device structure.
+ */
+
+ sprintf(err_msg, "%02x:%02x [%04x/%04x/%06x] has unknown header type %02x",
+ pbus->number,
+ (*pdev)->devfn,
+ (*pdev)->vendor,
+ (*pdev)->device,
+ class,
+ hdr_type);
+
+ pci_kern_err(func, err_msg);
+
+ ret_code = -ENOSYS;
+ }
+ }
+
+ /*
+ ** Any device errors? If not, then put the
+ ** device structure on the various lists.
+ */
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Put it into the bus node's device list
+ ** first.
+ */
+
+ if ((pdev_list = pbus->devices) != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Loop through the list to find the
+ ** position for the new device.
+ */
+
+ do
+ {
+ /*
+ ** Clear the compare status, i.e. denotes
+ ** the device/function numbers are equal.
+ ** Then, if the device/function numbers are
+ ** "greater than", try the next sibling, if
+ ** there is one.
+ */
+
+ cmp_stat = 0;
+
+ if ((*pdev)->devfn > pdev_list->devfn)
+ {
+ /*
+ ** Set the compare status. Then, see if
+ ** we at the end of the list If not, then
+ ** try the next one.
+ */
+
+ cmp_stat = 1;
+
+ if (pdev_list->sibling == (struct pci_dev *)NULL)
+ {
+ /*
+ ** Add the device at the end and
+ ** exit the compare loop.
+ */
+
+ pdev_list->sibling = *pdev;
+ break;
+ }
+ else
+ pdev_list = pdev_list->sibling;
+ }
+ else
+ {
+ /*
+ ** If "less than", then we've gone
+ ** too far.
+ */
+
+ if ((*pdev)->devfn < pdev_list->devfn)
+ {
+ /*
+ ** Set the compare status. Then,
+ ** set the next sibling pointer and
+ ** find our previous sibling.
+ */
+
+ cmp_stat = 1;
+
+ (*pdev)->sibling = pdev_list;
+
+ if ((pdev_list = pbus->devices) != (*pdev)->sibling)
+ {
+ while (pdev_list->sibling != (*pdev)->sibling)
+ pdev_list = pdev_list->sibling;
+
+ pdev_list->sibling = *pdev;
+ }
+ else
+ pbus->devices = *pdev;
+
+ break;
+ }
+ }
+ }
+ while (cmp_stat != 0);
+
+ /*
+ ** Restore interrupts, then check for same
+ ** device/function number error. If so, then
+ ** display a message and set the device error
+ ** flag.
+ */
+
+ restore_flags(flags);
+
+ if (cmp_stat == 0)
+ {
+ /*
+ ** Display an error message. Then set the
+ ** device error flag.
+ */
+
+ sprintf(err_msg, "%02x:%02x [%04x/%04x/%06x] has same devfn",
+ pbus->number,
+ (*pdev)->devfn,
+ (*pdev)->vendor,
+ (*pdev)->device,
+ class);
+
+ pci_kern_err(func, err_msg);
+
+ ret_code = -EEXIST;
+ }
+ }
+ else
+ {
+ /*
+ ** Put the device on the list and
+ ** restore interrupt.s
+ */
+
+ pbus->devices = *pdev;
+
+ restore_flags(flags);
+ }
+ }
+
+ /*
+ ** Check for any errors so far.
+ */
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Put the device into the global PCI
+ ** device chain. It's used to find
+ ** devices once everything is set up.
+ */
+
+ if ((pdev_list = pci_devices) != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Next, set the "next pointer" of the
+ ** device structure, based upon the
+ ** sort flag, pci_reverse.
+ */
+
+ if (pci_reverse == 0)
+ {
+ /*
+ ** Find the last device structure. Then
+ ** set its next pointer to the new device
+ ** structure.
+ */
+
+ while (pdev_list->next != (struct pci_dev *)NULL)
+ pdev_list = pdev_list->next;
+
+ pdev_list->next = *pdev;
+ }
+ else
+ {
+ /*
+ ** Set the initial pointer to the new
+ ** device structure.
+ */
+
+ (*pdev)->next = pdev_list;
+
+ pci_devices = *pdev;
+ }
+ }
+ else
+ pci_devices = *pdev;
+
+ /*
+ ** Restore interrupts.
+ */
+
+ restore_flags(flags);
+
+ /*
+ ** Attach a proc interface entry
+ ** to the device.
+ */
+
+ if (pci_proc_attach_device(*pdev) != 0)
+ {
+ sprintf(err_msg, "%02x:%02x [%04x/%04x/%06x] can't attach proc interface",
+ pbus->number,
+ (*pdev)->devfn,
+ (*pdev)->vendor,
+ (*pdev)->device,
+ class);
+
+ pci_kern_err(func, err_msg);
+ }
+ }
+ else
+ {
+ /*
+ ** Free the device structure and return
+ ** a NULL pointer.
+ */
+
+ kfree(*pdev);
+
+ *pdev = (struct pci_dev *)NULL;
+ }
+ }
+ else
+ {
+ pci_kern_err(func, "couldn't allocate a device structure");
+
+ ret_code = -ENOBUFS;
+ }
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_add_bus - Add Bus Structure
+**
+** This function will allocate a bus structure for
+** a child bus and fill it with the appropriate
+** bus node information. If the child bus structure
+** cannot be allocated, a NULL pointer will be
+** returned.
+*/
+
+int
+pci_add_bus(struct pci_bus *pbus, struct pci_dev *pdev, struct pci_bus **child)
+{
+ struct pci_bus *last_child; /* PCI Bus Child Last Pointer */
+
+ unsigned long flags; /* CPU Interrupt Flags */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** First, clear the return code. Then, allocate a
+ ** child pci_bus structure.
+ */
+
+ ret_code = PCI_OK;
+
+ *child = (struct pci_bus *)kmalloc(sizeof(struct pci_bus), GFP_ATOMIC);
+
+ if (*child != (struct pci_bus *)NULL)
+ {
+ /*
+ ** Next, clear it and initialize the pointers.
+ */
+
+ memset(*child, 0, sizeof(struct pci_bus));
+
+ (*child)->self = pdev;
+ (*child)->parent = pbus;
+
+ /*
+ ** Insert the child pci_bus structure into
+ ** the parent's list of children.
+ */
+
+ if (pbus != (struct pci_bus *)NULL)
+ {
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ if ((last_child = pbus->children) != (struct pci_bus *)NULL)
+ {
+ while (last_child->next != (struct pci_bus *)NULL)
+ last_child = last_child->next;
+
+ last_child->next = *child;
+ }
+ else
+ pbus->children = *child;
+
+ /*
+ ** Restore interrupts.
+ */
+
+ restore_flags(flags);
+ }
+ }
+ else
+ {
+ pci_kern_err("pci_add_bus", "couldn't allocate a bus structure");
+
+ ret_code = -ENOBUFS;
+ }
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_add_node - Add Node Structure
+**
+** This function will allocate a structure for the
+** node, i.e. either bus or device structure, and
+** all resources for that node. It will be added to
+** the various lists as well.
+*/
+
+int
+pci_add_node(unsigned int number, unsigned int devfn)
+{
+ struct pci_bus *pbus; /* PCI Parent Bus Pointer */
+
+ struct pci_bus *child; /* PCI Child Bus Pointer */
+
+ struct pci_dev *pdev; /* PCI Device Pointer */
+
+ unsigned short class; /* Class Code */
+
+ int ret_code; /* Function Return Code */
+
+ char *func; /* Function Name */
+
+ char err_msg[256]; /* Error Message */
+
+ /*
+ ** First, set the function name for possible error
+ ** messages. Then, initialize the function return
+ ** code and see if the device already exists in
+ ** the list.
+ */
+
+ func = "pci_add_node";
+
+ ret_code = PCI_OK;
+
+ if (pci_find_slot(number, devfn) == (struct pci_dev *)NULL)
+ {
+ /*
+ ** Next, ensure the Device ID is valid.
+ */
+
+ if (pci_valid_devid(number, devfn) == TRUE)
+ {
+ /*
+ ** Read the Class Code. Then add the node
+ ** based upon it.
+ */
+
+ pcibios_read_config_word(number, devfn, PCI_CLASS_DEVICE, &class);
+
+ if (class == PCI_CLASS_BRIDGE_HOST)
+ {
+ /*
+ ** Next, check for primary Host Bridge. This
+ ** we cannot add.
+ */
+
+ if (number != 0)
+ {
+ /*
+ ** Add a new bus structure to the
+ ** various lists.
+ */
+
+ ret_code = pci_add_bus((struct pci_bus *)NULL, (struct pci_dev *)NULL, &pbus);
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Fill in the bus structure and
+ ** add it to the list.
+ */
+
+ pbus->number = number;
+ pbus->primary = number;
+ pbus->secondary = number;
+ pbus->subordinate = 0xff;
+
+ pbus->next = pci_root.next;
+
+ pci_root.next = pbus;
+
+ /*
+ ** Do the initial call to pci_probe_bus()
+ ** to find all the devices for each bus
+ ** under the Host Bridge device.
+ */
+
+ ret_code = pci_probe_bus(pbus, devfn);
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Next, set the Host Bridge node's
+ ** device structure.
+ */
+
+ pbus->self = pci_find_slot(number, devfn);
+
+ /*
+ ** Finally, configure all the devices
+ ** and bridges.
+ */
+
+ ret_code = pci_conf_bus(pbus);
+ }
+
+ /*
+ ** Did we get any errors?
+ */
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Delete the bus structure.
+ */
+
+ pci_del_bus(pbus);
+ }
+ }
+ }
+ else
+ {
+ pci_kern_err(func, "cannot add primary Host Bridge");
+
+ ret_code = -EPERM;
+ }
+ }
+ else
+ {
+ /*
+ ** Not a Host Bridge. First, find the parent
+ ** bus structure.
+ */
+
+ pbus = &pci_root;
+
+ while ((pbus != (struct pci_bus *)NULL) && (pbus->secondary != number))
+ {
+ /*
+ ** Compare the subordinate bus number.
+ */
+
+ if (number < pbus->subordinate)
+ pbus = pbus->children;
+ else
+ pbus = pbus->next;
+ }
+
+ /*
+ ** Did we find the parent bus structure?
+ */
+
+ if (pbus != (struct pci_bus *)NULL)
+ {
+ /*
+ ** Get a PCI device structure and fill
+ ** it. Then add it to the various device
+ ** lists.
+ */
+
+ ret_code = pci_add_dev(pbus, devfn, &pdev);
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Is the new node a bridge? If not,
+ ** then just configure the device.
+ */
+
+ if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ {
+ /*
+ ** Add a new bus structure to the
+ ** various lists. If we can't then
+ ** delete the device node.
+ */
+
+ ret_code = pci_add_bus(pbus, pdev, &child);
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Probe for new devices.
+ */
+
+ ret_code = pci_probe_bus(child, devfn);
+
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Check to see if this is an AGP
+ ** bridge device.
+ */
+
+ if (pci_agp_bridge(pdev->bus, devfn) == TRUE)
+ {
+ sprintf(err_msg, "cannot add AGP bridge at %02x:%02x",
+ number,
+ devfn);
+
+ pci_kern_err(func, err_msg);
+
+ ret_code = -EPERM;
+ }
+ }
+#endif
+
+ /*
+ ** If no errors, then configure all
+ ** the new devices.
+ */
+
+ if (ret_code == PCI_OK)
+ ret_code = pci_conf_bus(child);
+ }
+ }
+ else
+ {
+ /*
+ ** Clear the child bus structure pointer.
+ ** Then, check for a bus 0 device. this
+ ** we cannot add.
+ */
+
+ child = (struct pci_bus *)NULL;
+
+ if (number != 0)
+ {
+ /*
+ ** Configure the device.
+ */
+
+ ret_code = pci_conf_dev(pdev);
+ }
+ else
+ {
+ pci_kern_err(func, "cannot add bus 0 device");
+
+ ret_code = -EPERM;
+ }
+ }
+
+ /*
+ ** Check for any errors.
+ */
+
+ if (ret_code != PCI_OK)
+ {
+ /*
+ ** Do we have a bus or device
+ ** structure to delete?
+ */
+
+ if (child != (struct pci_bus *)NULL)
+ pci_del_bus(child);
+ else
+ if (pdev != (struct pci_dev *)NULL)
+ pci_del_dev(pdev);
+ }
+ }
+ }
+ else
+ {
+ sprintf(err_msg, "couldn't find parent bus structure for %02x:%02x",
+ number,
+ devfn);
+
+ pci_kern_err(func, err_msg);
+
+ ret_code = -ENOENT;
+ }
+ }
+
+ /*
+ ** Finally, if no errors, ensure all the display
+ ** devices have been properly (re)configured.
+ */
+
+ if (ret_code == PCI_OK)
+ pci_conf_display();
+ }
+ else
+ {
+ sprintf(err_msg, "invalid device ID for %02x:%02x",
+ number,
+ devfn);
+
+ pci_kern_err(func, err_msg);
+
+ ret_code = -ENODEV;
+ }
+ }
+ else
+ {
+ sprintf(err_msg, "device already exists at %02x:%02x",
+ number,
+ devfn);
+
+ pci_kern_err(func, err_msg);
+
+ ret_code = -EEXIST;
+ }
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_del_dev - Delete Device Structure
+**
+** This function will delete a device structure from
+** the list of devices for the bus.. The device structure
+** memory will be freed as well.
+*/
+
+int
+pci_del_dev(struct pci_dev *pdev)
+{
+ struct pci_bus *pbus; /* PCI Bus Pointer */
+
+ struct pci_dev *pdev_del; /* PCI Deleted Device Pointer */
+
+ unsigned long flags; /* CPU Interrupt Flags */
+
+ unsigned int num_bars; /* Maximum Number Of BARs */
+
+ unsigned int bar; /* Base Address Register */
+
+ int ret_code; /* Function Return Code */
+
+ int alt_ret_code; /* Alternate Return Code */
+
+ /*
+ ** Initialize the return code, then
+ ** remove the proc interface.
+ */
+
+ ret_code = PCI_OK;
+
+ if ((alt_ret_code = pci_proc_detach_device(pdev)) != 0)
+ ret_code = alt_ret_code;
+
+ /*
+ ** Determine the number of Base Address registers
+ ** we need to free resources for.
+ */
+
+ if ((alt_ret_code = pci_get_bars(pdev, &num_bars)) != PCI_OK)
+ if (ret_code == PCI_OK)
+ ret_code = alt_ret_code;
+
+ /*
+ ** Next, free the device's resources.
+ */
+
+ for (bar = 0; bar < num_bars; ++bar)
+ if ((alt_ret_code = pci_free_devres(pdev, &(pdev->resources[bar]))) != PCI_OK)
+ if (ret_code == PCI_OK)
+ ret_code = alt_ret_code;
+
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Set the device's bus structure pointer, then
+ ** check to see if it's the first device.
+ */
+
+ pbus = pdev->bus;
+
+ if ((pdev_del = pbus->devices) != pdev)
+ {
+ /*
+ ** Loop until we find the device.
+ */
+
+ while (pdev_del->sibling != pdev)
+ pdev_del = pdev_del->sibling;
+
+ /*
+ ** Set the next sibling pointer.
+ */
+
+ pdev_del->sibling = pdev->sibling;
+ }
+ else
+ pbus->devices = pdev->sibling;
+
+ /*
+ ** Next, check to see if the device is
+ ** the first one on the list of devices.
+ */
+
+ if ((pdev_del = pci_devices) != pdev)
+ {
+ /*
+ ** Loop until we find the device.
+ */
+
+ while (pdev_del->next != pdev)
+ pdev_del = pdev_del->next;
+
+ /*
+ ** Set the next device pointer.
+ */
+
+ pdev_del->next = pdev->next;
+ }
+ else
+ pci_devices = pdev->next;
+
+ /*
+ ** Restore interrupts.
+ */
+
+ restore_flags(flags);
+
+ /*
+ ** Free the device structure memory.
+ */
+
+ kfree(pdev);
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_del_bus - Delete Bus Structure
+**
+** This function will delete a bus structure and
+** all the child bus/device structures associated
+** with it. All resources will be freed.
+*/
+
+int
+pci_del_bus(struct pci_bus *pbus)
+{
+ struct pci_bus *pbus_child; /* PCI Bus Child Pointer */
+
+ struct pci_bus *pbus_del; /* PCI Bus Deleted Child Pointer */
+
+ struct pci_bus *pbus_par; /* PCI Bus Parent Pointer */
+
+ struct pci_dev *pdev; /* PCI Device Pointer */
+
+ struct pci_dev *pdev_del; /* PCI Deleted Device Pointer */
+
+ unsigned long flags; /* CPU Interrupt Flags */
+
+ int ret_code; /* Function Return Code */
+
+ int alt_ret_code; /* Alternate Return Code */
+
+ /*
+ ** Initialize the function return code. Then,
+ ** recursively delete each child bus structure.
+ */
+
+ ret_code = PCI_OK;
+
+ pbus_child = pbus->children;
+
+ while (pbus_child != (struct pci_bus *)NULL)
+ {
+ /*
+ ** Set the pointer to the next child first.
+ */
+
+ pbus_del = pbus_child;
+
+ pbus_child = pbus_child->next;
+
+ /*
+ ** Delete the child bus structure.
+ */
+
+ if ((alt_ret_code = pci_del_bus(pbus_del)) != PCI_OK)
+ if (ret_code == PCI_OK)
+ ret_code = alt_ret_code;
+ }
+
+ /*
+ ** Next, loop and delete each device structure.
+ */
+
+ pdev = pbus->devices;
+
+ while (pdev != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Set the pointer to the next sibling first.
+ */
+
+ pdev_del = pdev;
+
+ pdev = pdev->sibling;
+
+ /*
+ ** Ensure the device to be deleted is not the
+ ** bus node's device. If it is the bus node's
+ ** device, then the device is a Host Bridge.
+ */
+
+ if (pdev_del != pbus->self)
+ {
+ /*
+ ** It is not the bus node's device. Free the
+ ** device's resources and delete the device
+ ** structure.
+ */
+
+ if ((alt_ret_code = pci_del_dev(pdev_del)) != PCI_OK)
+ if (ret_code == PCI_OK)
+ ret_code = alt_ret_code;
+ }
+ else
+ {
+ /*
+ ** It is the bus node's device. Set it as
+ ** the "only" device.
+ */
+
+ pbus->devices = pdev_del;
+
+ pdev_del->sibling = (struct pci_dev *)NULL;
+ }
+ }
+
+ /*
+ ** Free the bus' resources, i.e. memory and bus
+ ** numbers. Then delete the bus's device structure.
+ */
+
+ if ((alt_ret_code = pci_free_busres(pbus)) != PCI_OK)
+ if (ret_code == PCI_OK)
+ ret_code = alt_ret_code;
+
+ if ((alt_ret_code = pci_free_busnum(pbus)) != PCI_OK)
+ if (ret_code == PCI_OK)
+ ret_code = alt_ret_code;
+
+ if (pbus->self != (struct pci_dev *)NULL)
+ if ((alt_ret_code = pci_del_dev(pbus->self)) != PCI_OK)
+ if (ret_code == PCI_OK)
+ ret_code = alt_ret_code;
+
+ /*
+ ** Disable interrupts for now.
+ */
+
+ save_flags(flags);
+
+ /*
+ ** Set the parent bus structure pointer and
+ ** check it for the root structure.
+ */
+
+ if ((pbus_par = pbus->parent) != (struct pci_bus *)NULL)
+ {
+ /*
+ ** Check to see if it's the first bus structure.
+ */
+
+ if ((pbus_del = pbus_par->children) != pbus)
+ {
+ /*
+ ** Loop until we find the bus structure.
+ ** Then set the next sibling pointer.
+ */
+
+ while (pbus_del->next != pbus)
+ pbus_del = pbus_del->next;
+
+ pbus_del->next = pbus->next;
+ }
+ else
+ pbus_par->children = pbus->next;
+ }
+ else
+ {
+ /*
+ ** Check to see if it's the next root
+ ** bus structure.
+ */
+
+ if ((pbus_del = pci_root.next) != pbus)
+ {
+ /*
+ ** Loop until we find the bus structure.
+ ** Then set the next sibling pointer.
+ */
+
+ while (pbus_del->next != pbus)
+ pbus_del = pbus_del->next;
+
+ pbus_del->next = pbus->next;
+ }
+ else
+ pci_root.next = pbus->next;
+ }
+
+ /*
+ ** Restore interrupts and detach the
+ ** proc interface for this bus.
+ */
+
+ restore_flags(flags);
+
+ if ((alt_ret_code = pci_proc_detach_bus(pbus)) != 0)
+ if (ret_code == PCI_OK)
+ ret_code = alt_ret_code;
+
+ /*
+ ** Free the bus structure memory.
+ */
+
+ kfree(pbus);
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_del_node - Delete Node Structure
+**
+** This function will free all resources associated
+** with the node, i.e. either bus or device structure,
+** for the given bus and device/function numbers. It
+** will then remove the device structure from the bus'
+** list of devices as well as from the global list of devices.
+*/
+
+int
+pci_del_node(unsigned int number, unsigned int devfn)
+{
+ struct pci_bus *pbus; /* PCI Bus Pointer */
+
+ struct pci_dev *pdev; /* PCI Device Pointer */
+
+ unsigned int class; /* Class Code */
+
+ int ret_code; /* Function Return Code */
+
+ char *func; /* Function Name */
+
+ char err_msg[256]; /* Error Message */
+
+ /*
+ ** First, set the function name for possible error
+ ** messages. Then, initialize the function return
+ ** code and find the device structure in the devices'
+ ** list.
+ */
+
+ func = "pci_del_node";
+
+ ret_code = PCI_OK;
+
+ pdev = pci_find_slot(number, devfn);
+
+ if (pdev != (struct pci_dev *)NULL)
+ {
+ /*
+ ** Next, determine if this is a device or a
+ ** bus node.
+ */
+
+ class = pdev->class >> 8;
+
+ switch (class)
+ {
+ /*
+ ** Host Bridge
+ */
+
+ case PCI_CLASS_BRIDGE_HOST:
+ {
+ /*
+ ** Check for primary Host Bridge. This,
+ ** we cannot delete it.
+ */
+
+ if ((pdev->bus)->number == 0)
+ {
+ pci_kern_err(func, "cannot delete primary Host Bridge");
+
+ ret_code = -EPERM;
+
+ break;
+ }
+ }
+
+ /*
+ ** PCI Bridge
+ */
+
+ case PCI_CLASS_BRIDGE_PCI:
+ {
+ /*
+ ** Find the bus structure associated
+ ** with the bridge device structure.
+ */
+
+ if (class == PCI_CLASS_BRIDGE_HOST)
+ pbus = pci_root.next;
+ else
+ pbus = (pdev->bus)->children;
+
+ while (pbus != (struct pci_bus *)NULL)
+ {
+ /*
+ ** Compare for the the device
+ ** structure pointer.
+ */
+
+ if (pbus->self != pdev)
+ pbus = pbus->next;
+ else
+ break;
+ }
+
+ /*
+ ** Did we find the bus structure?
+ */
+
+ if (pbus != (struct pci_bus *)NULL)
+ {
+#ifdef CONFIG_PCI_AGP_BRIDGE
+ /*
+ ** Check to see if this is an AGP bridge device.
+ */
+
+ if (pci_agp_bridge(pdev->bus, devfn) == TRUE)
+ {
+ sprintf(err_msg, "cannot delete AGP bridge at %02x:%02x",
+ number,
+ devfn);
+
+ pci_kern_err(func, err_msg);
+
+ ret_code = -EPERM;
+ }
+#endif
+
+ /*
+ ** Delete the bus/devices.
+ */
+
+ if (ret_code == PCI_OK)
+ ret_code = pci_del_bus(pbus);
+ }
+ else
+ {
+ sprintf(err_msg, "couldn't find bus structure for %02x:%02x",
+ number,
+ devfn);
+
+ pci_kern_err(func, err_msg);
+
+ ret_code = -ENOENT;
+ }
+
+ break;
+ }
+
+ /*
+ ** PCI Device
+ */
+
+ default:
+ {
+ /*
+ ** Next, check for a bus 0 device. These,
+ ** we cannot delete.
+ */
+
+ if ((pdev->bus)->number != 0)
+ {
+ /*
+ ** Anything else is just a device. Free
+ ** the device's resources and delete the
+ ** device structure.
+ */
+
+ ret_code = pci_del_dev(pdev);
+ }
+ else
+ {
+ pci_kern_err(func, "cannot delete a bus 0 device");
+
+ ret_code = -EPERM;
+ }
+ }
+ }
+
+ /*
+ ** Finally, if no errors, ensure all the display
+ ** devices have been properly (re)configured.
+ */
+
+ if (ret_code == PCI_OK)
+ pci_conf_display();
+ }
+ else
+ {
+ sprintf(err_msg, "couldn't find device structure for %02x:%02x",
+ number,
+ devfn);
+
+ pci_kern_err(func, err_msg);
+
+ ret_code = -ENODEV;
+ }
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
diff -u -r --new-file linux/drivers/pci/pci_scan.c linux_mot/drivers/pci/pci_scan.c
--- linux/drivers/pci/pci_scan.c Wed Dec 31 17:00:00 1969
+++ linux_mot/drivers/pci/pci_scan.c Tue Jun 8 10:36:04 1999
@@ -0,0 +1,606 @@
+/*
+** PCI Bus Probe/Scan
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_res.h>
+
+
+
+
+
+/*
+** Debug info printing setup
+*/
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+
+
+
+
+/*
+** pci_find_host - Find Host Bridge Device on Bus
+**
+** This function will probe the given PCI bus for
+** a Host Bridge Device.
+*/
+
+__initfunc(int pci_find_host(unsigned int number, unsigned int *devfn))
+{
+ unsigned int dev; /* Device Number */
+
+ unsigned int func; /* Function Number */
+
+ unsigned short class; /* Class Code */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** Set the return code, then loop through each
+ ** device to find a Host Bridge.
+ */
+
+ ret_code = PCI_ERR;
+
+ for (dev = 0; (ret_code == PCI_ERR) && (dev <= MAX_PCI_DEV); ++dev)
+ {
+ /*
+ ** Function loop, from 0 to 7.
+ */
+
+ for (func = 0; (ret_code == PCI_ERR) && (func <= MAX_PCI_FUNC); ++func)
+ {
+ /*
+ ** Generate the Device/Function number,
+ ** then read and validate the Device ID
+ ** word from the device's configuration
+ ** space.
+ */
+
+ *devfn = PCI_DEVFN(dev, func);
+
+ if (pci_valid_devid(number, *devfn) == TRUE)
+ {
+ /*
+ ** Read the Class Code and see if it's a
+ ** PCI Host Bridge Device. If so, then
+ ** set good status.
+ */
+
+ pcibios_read_config_word(number, *devfn, PCI_CLASS_DEVICE, &class);
+
+ if (class != PCI_CLASS_BRIDGE_HOST)
+ {
+ /*
+ ** Check for a multi-function device.
+ */
+
+ if (pci_multi_func(number, *devfn) == FALSE)
+ break;
+ }
+ else
+ ret_code = PCI_OK;
+ }
+ }
+ }
+
+ /*
+ ** Return function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_kern_err - Display PCI Kernel Error Message
+**
+** This function will format and display a
+** PCI kernel error message. It will always
+** return PCI_ERR.
+*/
+
+int
+pci_kern_err(char *func, char *err_msg)
+{
+ /*
+ ** Do the error message.
+ */
+
+ if (func != (char *)NULL)
+ printk(KERN_ERR "PCI: %s() - %s\n", func, err_msg);
+ else
+ printk(KERN_ERR "PCI: %s\n", err_msg);
+
+ return (PCI_ERR);
+}
+
+
+
+
+
+/*
+** pci_valid_devid - Read and Validate the device ID
+**
+** This function will read the device ID at the given
+** bus, device, and function number. It will also
+** validate it.
+*/
+
+int
+pci_valid_devid(unsigned int number, unsigned int devfn)
+{
+ unsigned short devid; /* Device/Vendor ID */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** First, Read the device ID.
+ */
+
+ pcibios_read_config_word(number, devfn, PCI_DEVICE_ID, &devid);
+
+ /*
+ ** Next, set the return code and validate
+ ** the device ID.
+ **
+ ** NOTE: Some broken boards return 0 if a
+ ** slot is empty.
+ */
+
+ ret_code = TRUE;
+
+ if (devid == 0xffff)
+ ret_code = FALSE;
+
+ if (devid == 0x0000)
+ ret_code = FALSE;
+
+ /*
+ ** Return function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_multi_func - Check for Multi-Function Device
+**
+** This function will read the header type at the given
+** bus, device, and function number. It will check it
+** for a multi-function device or not.
+*/
+
+int
+pci_multi_func(unsigned int number, unsigned int devfn)
+{
+ unsigned char hdr_type; /* Device Header Type */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** First, set the return code. Then, if
+ ** we are at function 0, check for a
+ ** multi-function device.
+ */
+
+ ret_code = TRUE;
+
+ if (PCI_FUNC(devfn) == 0)
+ {
+ /*
+ ** Read the configuration header type
+ ** register and check for a multi-function
+ ** device. If not multi-function, then
+ ** clear the return code.
+ */
+
+ pcibios_read_config_byte(number, devfn, PCI_HEADER_TYPE, &hdr_type);
+
+ if ((hdr_type & 0x80) == 0)
+ ret_code = FALSE;
+ }
+
+ /*
+ ** Return function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_probe_dev - Probe PCI Bus For Devices
+**
+** This function will probe the given bus for all
+** devices connected to it. It will add the found
+** devices to the global device list and to the
+** bus structure devices list.
+*/
+
+static int
+pci_probe_dev(struct pci_bus *pbus)
+{
+ struct pci_dev *pdev; /* PCI Device Pointer */
+
+ struct pci_bus *child; /* PCI Bus Child Pointer */
+
+ unsigned int dev; /* Device Number */
+
+ unsigned int func; /* Function Number */
+
+ unsigned int devfn; /* Device/Function Number */
+
+ unsigned int buses; /* Buses Config. Register */
+
+ unsigned char slat_timer; /* Secondary Latency Timer */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** Initialize the function return code, then
+ ** search each device on this bus, i.e. device
+ ** 0 to 31.
+ */
+
+ ret_code = PCI_OK;
+
+ for (dev = 0; (ret_code == PCI_OK) && (dev <= MAX_PCI_DEV); ++dev)
+ {
+ /*
+ ** Function loop, from 0 to 7.
+ */
+
+ for (func = 0; (ret_code == PCI_OK) && (func <= MAX_PCI_FUNC); ++func)
+ {
+ /*
+ ** Generate the Device/Function number,
+ ** then read and validate the Device ID
+ ** word from the device's configuration
+ ** space.
+ */
+
+ devfn = PCI_DEVFN(dev, func);
+
+ if (pci_valid_devid(pbus->number, devfn) == TRUE)
+ {
+ /*
+ ** Next, get a PCI device structure and fill
+ ** it.
+ */
+
+ ret_code = pci_add_dev(pbus, devfn, &pdev);
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Next, check to see if it's a bridge. If so,
+ ** then disable the bus(es) behind it.
+ */
+
+ if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ {
+ /*
+ ** First, read the Secondary Latency Timer value
+ ** and save it.
+ */
+
+ pcibios_read_config_byte(pbus->number, devfn, PCI_SEC_LATENCY_TIMER, &slat_timer);
+
+ /*
+ ** Then set the Secondary Latency Timer value
+ ** and clear the Subordinate, Primary, and
+ ** Secondary bus numbers. This will disable
+ ** the bridge for now.
+ */
+
+ buses = slat_timer;
+
+ buses = (buses << 8) | 0;
+ buses = (buses << 8) | 0;
+ buses = (buses << 8) | 0;
+
+ pcibios_write_config_dword(pbus->number, devfn, PCI_PRIMARY_BUS, buses);
+ }
+
+ /*
+ ** Check for a multi-function device.
+ */
+
+ if (pci_multi_func(pbus->number, devfn) == FALSE)
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ ** Look behind all PCI-to-PCI bridges on this bus.
+ */
+
+ pdev = pbus->devices;
+
+ while ((ret_code == PCI_OK) && (pdev != (struct pci_dev *)NULL))
+ {
+ /*
+ ** If it's a bridge, scan the bus behind it.
+ */
+
+ if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
+ {
+ /*
+ ** Allocate a child pci_bus structure,
+ ** initialize it, and insert it into the
+ ** tree of buses. Then scan all the child's
+ ** subordinate buses.
+ */
+
+ ret_code = pci_add_bus(pbus, pdev, &child);
+
+ if (ret_code == PCI_OK)
+ ret_code = pci_probe_bus(child, pdev->devfn);
+ }
+
+ /*
+ ** Do the next sibling.
+ */
+
+ pdev = pdev->sibling;
+ }
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_probe_bus - Probe PCI Bus
+**
+** This function gets called recursively. However, for
+** the first time it gets called from pci_init(). The
+** argument to this function has to be bus node.
+*/
+
+int
+pci_probe_bus(struct pci_bus *pbus, unsigned int devfn)
+{
+ struct pci_bus *pbus_par; /* Parent Bus Pointer */
+
+ unsigned int buses; /* Buses Config. Register */
+
+ unsigned short cmd; /* Command Register */
+
+ unsigned short class; /* Class Code */
+
+ unsigned char slat_timer; /* Secondary Latency Timer */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** Initialize the function return code, then
+ ** see if we need to allocate bus numbers. We
+ ** only do this once.
+ */
+
+ ret_code = PCI_OK;
+
+ if ((pbus->subordinate == 0) || (pbus->subordinate == MAX_PCI_BUS))
+ {
+ /*
+ ** Allocate bus numbers, i.e. secondary and
+ ** subordinate.
+ */
+
+ ret_code = pci_alloc_busnum(pbus, devfn);
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Set the parent bus pointer. We need this
+ ** for the bridge's bus number.
+ */
+
+ if ((pbus_par = pbus->parent) == (struct pci_bus *)NULL)
+ pbus_par = pbus;
+
+ /*
+ ** Clear the Secondary Latency Timer value. Then
+ ** read the Class Code to see if this is a PCI
+ ** bridge device?
+ */
+
+ slat_timer = 0;
+
+ pcibios_read_config_word(pbus_par->number, devfn, PCI_CLASS_DEVICE, &class);
+
+ if (class == PCI_CLASS_BRIDGE_PCI)
+ {
+ /*
+ ** Disable this bridge device by clearing the
+ ** Master, Memory, and I/O enable bits.
+ */
+
+ pcibios_read_config_word(pbus_par->number, devfn, PCI_COMMAND, &cmd);
+
+ cmd &= ~0x0007;
+
+ pcibios_write_config_word(pbus_par->number, devfn, PCI_COMMAND, cmd);
+
+ /*
+ ** Read the Secondary Latency Timer value and
+ ** set it if it is below 16.
+ */
+
+ pcibios_read_config_byte(pbus_par->number, devfn, PCI_SEC_LATENCY_TIMER, &slat_timer);
+
+ if (slat_timer < 16)
+ slat_timer = 64;
+ }
+
+ /*
+ ** Then set the Secondary Latency Timer value,
+ ** the Primary Bus number, and the Secondary
+ ** Bus number. Write the configuration register.
+ */
+
+ buses = slat_timer;
+ buses = (buses << 8) | pbus->subordinate;
+ buses = (buses << 8) | pbus->secondary;
+ buses = (buses << 8) | pbus->primary;
+
+ pcibios_write_config_dword(pbus_par->number, devfn, PCI_PRIMARY_BUS, buses);
+
+ /*
+ ** Finally, clear the Status register.
+ */
+
+ pcibios_write_config_word(pbus_par->number, devfn, PCI_STATUS, 0xffff);
+ }
+ }
+
+ /*
+ ** Did we get any errors?
+ */
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Next, probe the bus for all devices.
+ */
+
+ ret_code = pci_probe_dev(pbus);
+ }
+
+ /*
+ ** Return the function result.
+ */
+
+ return (ret_code);
+}
+
+
+
+
+
+/*
+** pci_scan_bus - Scan PCI Bus
+**
+** This function gets called recursively. However, for
+** the first time it gets called from pci_init(). The
+** argument to this function has to be bus node.
+*/
+
+__initfunc(unsigned int pci_scan_bus(struct pci_bus *pbus))
+{
+ unsigned int devfn; /* Host Device/Function Number */
+
+ int ret_code; /* Function Return Code */
+
+ /*
+ ** First, find the Host Bridge on this bus
+ ** and check for probing errors.
+ */
+
+ DBG("pci_scan_bus for bus %d\n", pbus->number);
+
+ ret_code = pci_find_host(pbus->number, &devfn);
+
+#if (CONFIG_PCI_BUSLVL0_NODES > 1)
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Next, check to see if this is our first time
+ ** through.
+ */
+
+ if (pbus->number == 0)
+ {
+ /*
+ ** It is our first time through. Thus, we must
+ ** reassign bus numbers to all Host Bridge
+ ** devices before probing.
+ */
+
+ ret_code = pci_alloc_hosts();
+ }
+ }
+#endif
+
+ /*
+ ** Any errors yet?
+ */
+
+ if (ret_code == PCI_OK)
+ {
+ /*
+ ** Next, if no errors, do the initial call
+ ** to pci_probe_bus() to find all the devices
+ ** for each bus under the Host Bridge device.
+ */
+
+ if (pci_probe_bus(pbus, devfn) == PCI_OK)
+ {
+ /*
+ ** Next, set the Host Bridge node's
+ ** device structure.
+ */
+
+ pbus->self = pci_find_slot(pbus->number, devfn);
+
+ /*
+ ** Configure all the devices and bridges.
+ */
+
+ pci_conf_bus(pbus);
+
+ /*
+ ** Finally, ensure all the display devices
+ ** have been properly configured.
+ */
+
+ pci_conf_display();
+
+ /*
+ ** We've scanned the bus and so we know
+ ** all about what's on the other side of
+ ** any bridges that may be on this bus
+ ** plus any devices.
+ */
+
+ DBG("PCI: pci_scan_bus returning with max = %d\n", pbus->subordinate);
+ }
+ }
+
+ /*
+ ** Return the subordinate bus number.
+ */
+
+ return (pbus->subordinate);
+}
diff -u -r --new-file linux/drivers/pci/pcisyms.c linux_mot/drivers/pci/pcisyms.c
--- linux/drivers/pci/pcisyms.c Wed Dec 16 14:35:49 1998
+++ linux_mot/drivers/pci/pcisyms.c Tue Mar 16 22:11:22 1999
@@ -33,6 +33,9 @@
#ifdef CONFIG_PROC_FS
EXPORT_SYMBOL(pci_proc_attach_device);
EXPORT_SYMBOL(pci_proc_detach_device);
+#ifdef CONFIG_PCI_SERVICES
+EXPORT_SYMBOL(pci_proc_detach_bus);
+#endif
#endif

/* Backward compatibility */
diff -u -r --new-file linux/drivers/pci/proc.c linux_mot/drivers/pci/proc.c
--- linux/drivers/pci/proc.c Mon Aug 24 13:14:10 1998
+++ linux_mot/drivers/pci/proc.c Fri Jul 9 13:51:04 1999
@@ -9,9 +9,12 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
+#include <linux/init.h>
#include <linux/pci.h>
+#ifdef CONFIG_PCI_SERVICES
+#include <linux/pci_res.h>
+#endif
#include <linux/proc_fs.h>
-#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>

@@ -195,6 +198,77 @@
return nbytes;
}

+#ifdef CONFIG_PCI_SERVICES
+static int
+proc_node_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ unsigned char *nodep;
+ unsigned char *buf;
+ unsigned char val;
+
+ unsigned int cnt;
+
+ int ret_code;
+
+ struct pci_dev *pdev;
+
+ struct pci_node node_info;
+
+ if (capable(CAP_SYS_ADMIN) == 0)
+ return (-EPERM);
+
+ cnt = sizeof(struct pci_node);
+
+ buf = (unsigned char *)arg;
+
+ if (access_ok(VERIFY_READ, buf, cnt) == 0)
+ return (-EINVAL);
+
+ for (nodep = (unsigned char *)&node_info; cnt > 0; --cnt, ++nodep, ++buf)
+ {
+ __get_user(val, buf);
+
+ *nodep = val;
+ }
+
+ printk(KERN_INFO "PCI proc: cmd = %d, node bus = %d, devfn = 0x%02x\n",
+ node_info.cmd, node_info.number, node_info.devfn);
+
+ switch (node_info.cmd)
+ {
+ case PCI_NODE_NOP:
+ {
+ if ((pdev = pci_find_slot(node_info.number, node_info.devfn)) == NULL)
+ return (-ENOENT);
+ break;
+ }
+
+ case PCI_NODE_ADD:
+ {
+ if ((ret_code = pci_add_node(node_info.number, node_info.devfn)) != PCI_OK)
+ return (ret_code);
+
+ break;
+ }
+
+ case PCI_NODE_DEL:
+ {
+ if ((ret_code = pci_del_node(node_info.number, node_info.devfn)) != PCI_OK)
+ return (ret_code);
+
+ break;
+ }
+
+ default:
+ {
+ return (-EINVAL);
+ }
+ }
+
+ return (0);
+}
+#endif /* CONFIG_PCI_SERVICES */
+
static struct file_operations proc_bus_pci_operations = {
proc_bus_pci_lseek,
proc_bus_pci_read,
@@ -229,6 +303,42 @@
NULL /* permission */
};

+#ifdef CONFIG_PCI_SERVICES
+static struct file_operations proc_node_pci_operations = {
+ NULL, /* lseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ proc_node_pci_ioctl,
+ NULL, /* mmap */
+ NULL, /* no special open code */
+ NULL, /* flush */
+ NULL, /* no special release code */
+ NULL /* can't fsync */
+};
+
+static struct inode_operations proc_node_pci_inode_operations = {
+ &proc_node_pci_operations, /* default base directory file-ops */
+ NULL, /* create */
+ NULL, /* lookup */
+ NULL, /* link */
+ NULL, /* unlink */
+ NULL, /* symlink */
+ NULL, /* mkdir */
+ NULL, /* rmdir */
+ NULL, /* mknod */
+ NULL, /* rename */
+ NULL, /* readlink */
+ NULL, /* follow_link */
+ NULL, /* readpage */
+ NULL, /* writepage */
+ NULL, /* bmap */
+ NULL, /* truncate */
+ NULL /* permission */
+};
+#endif /* CONFIG_PCI_SERVICES */
+
int
get_pci_dev_info(char *buf, char **start, off_t pos, int count, int wr)
{
@@ -282,6 +392,9 @@
};

static struct proc_dir_entry *proc_bus_pci_dir;
+#ifdef CONFIG_PCI_SERVICES
+static struct proc_dir_entry *proc_node_pci;
+#endif

int pci_proc_attach_device(struct pci_dev *dev)
{
@@ -318,6 +431,21 @@
return 0;
}

+#ifdef CONFIG_PCI_SERVICES
+int pci_proc_detach_bus(struct pci_bus *bus)
+{
+ struct proc_dir_entry *e;
+
+ if ((e = bus->procdir)) {
+ if (e->count)
+ return -EBUSY;
+ remove_proc_entry(e->name, proc_bus_pci_dir);
+ bus->procdir = NULL;
+ }
+ return 0;
+}
+#endif
+
__initfunc(void proc_bus_pci_add(struct pci_bus *bus))
{
while (bus) {
@@ -337,7 +465,13 @@
return;
proc_bus_pci_dir = create_proc_entry("pci", S_IFDIR, proc_bus);
proc_register(proc_bus_pci_dir, &proc_pci_devices);
+#ifndef CONFIG_PCI_SERVICES
proc_bus_pci_add(&pci_root);
+#else
+ proc_node_pci = create_proc_entry("node", S_IFREG | S_IRUGO | S_IWUSR, proc_bus_pci_dir);
+ proc_node_pci->ops = &proc_node_pci_inode_operations;
+ proc_node_pci->size = sizeof(struct pci_node);
+#endif

#ifdef CONFIG_PCI_OLD_PROC
proc_old_pci_init();
diff -u -r --new-file linux/include/linux/pci.h linux_mot/include/linux/pci.h
--- linux/include/linux/pci.h Wed Jun 9 16:59:34 1999
+++ linux_mot/include/linux/pci.h Fri Jul 9 13:01:40 1999
@@ -794,6 +794,9 @@
#define PCI_DEVICE_ID_EF_ATM_FPGA 0x0000
#define PCI_DEVICE_ID_EF_ATM_ASIC 0x0002

+#define PCI_VENDOR_ID_IDT 0x111d
+#define PCI_DEVICE_ID_IDT_NICSTAR 0x0001
+
#define PCI_VENDOR_ID_FORE 0x1127
#define PCI_DEVICE_ID_FORE_PCA200PC 0x0210
#define PCI_DEVICE_ID_FORE_PCA200E 0x0300
@@ -1132,10 +1134,39 @@
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
#define PCI_FUNC(devfn) ((devfn) & 0x07)

+#ifdef CONFIG_PCI_SERVICES
+/*
+ * This is the add/delete node structure passed with the ioctl().
+ */
+
+#define PCI_NODE_NOP 0 /* NOP ioctl command */
+#define PCI_NODE_ADD 1 /* Add node ioctl command */
+#define PCI_NODE_DEL 2 /* Delete node ioctl command */
+
+struct pci_node {
+ unsigned int cmd; /* command */
+ unsigned int number; /* bus number */
+ unsigned int devfn; /* encoded device & function index */
+};
+#endif
+
#ifdef __KERNEL__

#include <linux/types.h>
#include <linux/config.h>
+#ifdef CONFIG_PCI_SERVICES
+/*
+ * There is one pci_res structure for each device. This
+ * structure holds the alignment, type, and size.
+ */
+struct pci_res {
+ struct pci_res *next;
+ unsigned int type;
+ unsigned long align;
+ unsigned long size;
+ unsigned long baddr;
+};
+#endif

/*
* There is one pci_dev structure for each slot-number/function-number
@@ -1173,6 +1204,13 @@
*/
unsigned long base_address[6];
unsigned long rom_address;
+
+#ifdef CONFIG_PCI_SERVICES
+ /*
+ * Resources for each BAR.
+ */
+ struct pci_res resources[6];
+#endif
};

struct pci_bus {
@@ -1190,10 +1228,25 @@
unsigned char primary; /* number of primary bridge */
unsigned char secondary; /* number of secondary bridge */
unsigned char subordinate; /* max number of subordinate buses */
+
+#ifdef CONFIG_PCI_SERVICES
+ /*
+ * Resources for the node
+ */
+ struct pci_res resources[4];
+
+ struct pci_res *res_head_io; /* PCI I/O space */
+ struct pci_res *res_head_mem; /* PCI memory space */
+ struct pci_res *res_head_mem20; /* PCI 20-bit memory space */
+ struct pci_res *res_head_mempf; /* PCI prefetch memory space */
+#endif
};

extern struct pci_bus pci_root; /* root bus */
extern struct pci_dev *pci_devices; /* list of all devices */
+#ifdef CONFIG_PCI_SERVICES
+extern int pci_reverse;
+#endif

/*
* Error values that may be returned by the PCI bios.
@@ -1245,6 +1298,9 @@
int get_pci_list(char *buf);
int pci_proc_attach_device(struct pci_dev *dev);
int pci_proc_detach_device(struct pci_dev *dev);
+#ifdef CONFIG_PCI_SERVICES
+int pci_proc_detach_bus(struct pci_bus *bus);
+#endif

struct pci_dev *pci_find_device (unsigned int vendor, unsigned int device, struct pci_dev *from);
struct pci_dev *pci_find_class (unsigned int class, struct pci_dev *from);
diff -u -r --new-file linux/include/linux/pci_res.h linux_mot/include/linux/pci_res.h
--- linux/include/linux/pci_res.h Wed Dec 31 17:00:00 1969
+++ linux_mot/include/linux/pci_res.h Fri Jul 9 13:02:00 1999
@@ -0,0 +1,208 @@
+/*
+** PCI resource definitions and function prototypes
+*/
+
+#ifndef LINUX_PCI_RES_H
+#define LINUX_PCI_RES_H
+
+/*
+** PCI Bus Number/Level Definitions
+**
+** MAX_PCI_NODES - Maximum Number of Bus Nodes
+** MAX_PCI_LEVELS - Maximum Number of Bus Levels
+*/
+
+#define BUSLVL3_NODES CONFIG_PCI_BUSLVL3_NODES
+
+#define BUSLVL2_NODES ( CONFIG_PCI_BUSLVL2_NODES \
+ + ( CONFIG_PCI_BUSLVL2_NODES * BUSLVL3_NODES ) )
+
+#define BUSLVL1_NODES ( CONFIG_PCI_BUSLVL1_NODES \
+ + ( CONFIG_PCI_BUSLVL1_NODES * BUSLVL2_NODES ) )
+
+#define BUSLVL0_NODES ( CONFIG_PCI_BUSLVL0_NODES \
+ + ( CONFIG_PCI_BUSLVL0_NODES * BUSLVL1_NODES ) )
+
+#ifndef CONFIG_PCI_AGP_BRIDGE
+#define MAX_PCI_NODES BUSLVL0_NODES
+#else
+#define MAX_PCI_NODES ( BUSLVL0_NODES + 1 )
+#endif
+
+#define MAX_PCI_LEVELS 4
+
+/*
+** PCI IRQ Pin Definitions
+**
+*/
+
+#define PCI_INT_NONE 0
+#define PCI_INTA 1
+#define PCI_INTB 2
+#define PCI_INTC 3
+#define PCI_INTD 4
+
+/*
+** PCI Memory and I/O Space Alignment Definitions
+**
+** PCI_ALIGN_IO - PCI I/O Alignment
+** PCI_ALIGN_MEM - PCI Memory Alignment
+** PCI_ALIGN_MEM20 - PCI 20-bit Memory Alignment
+**
+** PCI_ALIGN_ADDR - Macro to Align PCI Memory or I/O Address
+*/
+
+#define PCI_ALIGN_IO 0x00001000
+#define PCI_ALIGN_MEM 0x00100000
+#define PCI_ALIGN_MEM20 0x00000010
+
+#define PCI_ALIGN_ADDR(addr,align) ((addr + (align - 1)) & ~(align - 1))
+
+/*
+** PCI Resource Array Indexes
+**
+** PCI_RES_INDX_IO - PCI I/O Resource Array Index
+** PCI_RES_INDX_MEM - PCI Memory Resource Array Index
+** PCI_RES_INDX_MEM20 - PCI 20-bit Memory Resource Array Index
+** PCI_RES_INDX_MEMPF - PCI Prefetch Memory Resource Array Index
+*/
+
+#define PCI_RES_INDX_IO 0
+#define PCI_RES_INDX_MEM 1
+#define PCI_RES_INDX_MEM20 2
+#define PCI_RES_INDX_MEMPF 3
+
+/*
+** PCI Resource Types
+**
+** PCI_RES_TYPE_NOTUSED - Unused PCI Resouce Type
+**
+** PCI_RES_TYPE_IO - PCI I/O Resource Type
+** PCI_RES_TYPE_MEM - PCI Memory Resource Type
+** PCI_RES_TYPE_MEM20 - PCI 20-bit Memory Resource Type
+** PCI_RES_TYPE_MEMPF - PCI Prefetch Memory Resource Type
+**
+** PCI_RES_ADDR_START - Starting Address
+** PCI_RES_ADDR_END - Ending Address
+*/
+
+#define PCI_RES_TYPE_NOTUSED 0
+#define PCI_RES_TYPE_IO 1
+#define PCI_RES_TYPE_MEM 2
+#define PCI_RES_TYPE_MEM20 3
+#define PCI_RES_TYPE_MEMPF 4
+
+#define PCI_RES_ADDR_START 0
+#define PCI_RES_ADDR_END 1
+
+/*
+** PCI Bus/Device/Function
+**
+** MAX_PCI_BUS - Maximum PCI Bus Number
+** MAX_PCI_DEV - Maximum PCI Device Number
+** MAX_PCI_FUNC - Maximum PCI Function Number
+*/
+
+#define MAX_PCI_BUS 255
+#define MAX_PCI_DEV 31
+#define MAX_PCI_FUNC 7
+
+/*
+** Miscellaneous Definitions
+**
+** PCI_OK - Function Return Code - OK
+** PCI_ERR - Function Return Code - Error
+**
+** PCI_BUS_NOT_ALLOC - PCI Bus Number Not Allocated
+** PCI_BUS_ALLOC - PCI Bus Number Allocated
+**
+** NUM_BARS - Number of Base Address Registers
+*/
+
+#define PCI_OK 0
+#define PCI_ERR -1
+
+#define PCI_BUS_NOT_ALLOC 0
+#define PCI_BUS_ALLOC 1
+
+#define NUM_BARS 6
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/*
+** PCI bus number/device resource allocation arrays
+** and functions.
+*/
+
+int pci_alloc_businit(void) __init;
+
+#if (CONFIG_PCI_BUSLVL0_NODES > 1)
+int pci_alloc_hosts(void) __init;
+#endif
+
+#ifdef CONFIG_PCI_AGP_BRIDGE
+int pci_agp_bridge(struct pci_bus *pbus, unsigned int devfn);
+#endif
+
+int pci_alloc_busnum(struct pci_bus *pbus, unsigned int devfn);
+int pci_alloc_busres(struct pci_bus *pbus);
+int pci_alloc_devres(struct pci_dev *pdev, struct pci_res *pres, int bar);
+
+int pci_free_busnum(struct pci_bus *pbus);
+int pci_free_busres(struct pci_bus *pbus);
+int pci_free_devres(struct pci_dev *pdev, struct pci_res *pres);
+
+/*
+** PCI bus/device node management functions.
+*/
+
+int pci_add_dev(struct pci_bus *pbus, unsigned int devfn, struct pci_dev **pdev);
+int pci_add_bus(struct pci_bus *pbus, struct pci_dev *pdev, struct pci_bus **child);
+int pci_add_node(unsigned int number, unsigned int devfn);
+
+int pci_del_dev(struct pci_dev *pdev);
+int pci_del_bus(struct pci_bus *pbus);
+int pci_del_node(unsigned int number, unsigned int devfn);
+
+/*
+** PCI bus/device configuration functions.
+*/
+
+unsigned int pci_pirqs[4];
+
+int pci_get_bars(struct pci_dev *pdev, int *num_bars);
+int pci_conf_dev(struct pci_dev *pdev);
+int pci_conf_bus(struct pci_bus *pbus);
+void pci_conf_display(void);
+
+/*
+** PCI bus scan/probe functions.
+*/
+int pci_find_host(unsigned int number, unsigned int *devfn) __init;
+int pci_kern_err(char *func, char *err_msg);
+int pci_valid_devid(unsigned int number, unsigned int devfn);
+int pci_multi_func(unsigned int number, unsigned int devfn);
+int pci_probe_bus(struct pci_bus *pbus, unsigned int devfn);
+
+unsigned int pci_scan_bus(struct pci_bus *pbus) __init;
+
+/*
+** PCI interrupt configuration function.
+*/
+
+#ifdef CONFIG_PCI_PIRQ_UPDATE
+int pci_hwints_update_pirqs(void) __init;
+#endif
+void pci_hwints_getirq(struct pci_dev *pdev);
+
+#endif /* LINUX_PCI_RES_H */
\
 
 \ /
  Last update: 2005-03-22 13:53    [W:0.291 / U:0.244 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site