Commit Graph

253 Commits

Author SHA1 Message Date
jhb
51bd96b572 Reimplement how PCI-PCI bridges manage their I/O windows. Previously the
driver would verify that requests for child devices were confined to any
existing I/O windows, but the driver relied on the firmware to initialize
the windows and would never grow the windows for new requests.  Now the
driver actively manages the I/O windows.

This is implemented by allocating a bus resource for each I/O window from
the parent PCI bus and suballocating that resource to child devices.  The
suballocations are managed by creating an rman for each I/O window.  The
suballocated resources are mapped by passing the bus_activate_resource()
call up to the parent PCI bus.  Windows are grown when needed by using
bus_adjust_resource() to adjust the resource allocated from the parent PCI
bus.  If the adjust request succeeds, the window is adjusted and the
suballocation request for the child device is retried.

When growing a window, the rman_first_free_region() and
rman_last_free_region() routines are used to determine if the front or
end of the existing I/O window is free.  From using that, the smallest
ranges that need to be added to either the front or back of the window
are computed.  The driver will first try to grow the window in whichever
direction requires the smallest growth first followed by the other
direction if that fails.

Subtractive bridges will first attempt to satisfy requests for child
resources from I/O windows (including attempts to grow the windows).  If
that fails, the request is passed up to the parent PCI bus directly
however.

The PCI-PCI bridge driver will try to use firmware-assigned ranges for
child BARs first and only allocate a "fresh" range if that specific range
cannot be accommodated in the I/O window.  This allows systems where the
firmware assigns resources during boot but later wipes the I/O windows
(some ACPI BIOSen are known to do this) to "rediscover" the original I/O
window ranges.

The ACPI Host-PCI bridge driver has been adjusted to correctly honor
hw.acpi.host_mem_start and the I/O port equivalent when a PCI-PCI bridge
makes a wildcard request for an I/O window range.

The new PCI-PCI bridge driver is only enabled if the NEW_PCIB kernel option
is enabled.  This is a transition aide to allow platforms that do not
yet support bus_activate_resource() and bus_adjust_resource() in their
Host-PCI bridge drivers (and possibly other drivers as needed) to use the
old driver for now.  Once all platforms support the new driver, the
kernel option and old driver will be removed.

PR:		kern/143874 kern/149306
Tested by:	mav
2011-05-03 17:37:24 +00:00
jhb
3e97a80649 Add implementations of BUS_ADJUST_RESOURCE() to the PCI bus driver,
generic PCI-PCI bridge driver, x86 nexus driver, and x86 Host to PCI bridge
drivers.
2011-05-02 14:13:12 +00:00
jhb
87c352ad14 Add device IDs for two more ServerWorks Host-PCI bridges so that we can
read their starting PCI bus number for older systems that do not support
ACPI (or have a broken _BBN method).

PR:		kern/148108
MFC after:	1 week
2010-11-25 15:42:33 +00:00
jhb
956b0b5c7f Change the MPTable and $PIR PCI-PCI bridge drivers to inherit from the
generic PCI-PCI bridge driver and only override specific methods.  This
should fix suspend/resume of PCI-PCI bridges using these drivers.
2010-08-05 17:48:37 +00:00
avg
96f7c01c8c number of cleanups in i386 and amd64 pci md code
o introduce PCIE_REGMAX and use it instead of ad-hoc constant
o where 'reg' parameter/variable is not already unsigned, cast it to
  unsigned before comparison with maximum value to cut off negative
  values
o use PCI_SLOTMAX in several places where 31 or 32 were explicitly used
o drop redundant check of 'bytes' in i386 pciereg_cfgread() - valid
  values are already checked in the subsequent switch

Reviewed by:	jhb
MFC after:	1 week
2009-09-24 07:11:23 +00:00
jkim
f54960f3a9 Match PCI Express root bridge _HID directly instead of
relying on _CID.

Reviewed by:	jhb
Approved by:	re (kib)
2009-07-13 21:36:31 +00:00
avg
2511f4d43b strict kobj signatures: fix legacy i386 pcib_write_config impl
Reviewed by:	imp, current@
Approved by:	jhb (mentor)
2009-06-11 17:06:31 +00:00
jhb
b80bf31073 Add a read-only sysctl hw.pci.mcfg to mirror the tunable by the same name.
MFC after:	1 week
2009-05-18 21:47:32 +00:00
jhb
ac5c4c1c38 Fall back to using configuration type 1 accesses for PCI config requests if
the requested PCI bus falls outside of the bus range given in the ACPI
MCFG table.  Several BIOSes seem to not include all of the PCI busses in
systems in their MCFG tables.  It maybe that the BIOS is simply buggy and
does support all the busses, but it is more conservative to just fall back
to the old method unless it is certain that memory accesses will work.
2009-03-24 18:10:22 +00:00
jhb
1d4a561a28 Add a 'hw.pci.mcfg' tunable. It can be set to 0 to disable memory-mapped
PCI config access.
2008-09-11 21:42:11 +00:00
jhb
ddef310111 Some K8 chipsets don't expose all of the PCI devices on bus 0 via PCIe
memory-mapped config access.  Add a workaround for these systems by
checking the first function of each slot on bus 0 using both the
memory-mapped config access and the older type 1 I/O port config access.
If we find a slot that is only visible via the type 1 I/O port config
access, we flag that slot.  Future PCI config transactions to flagged
slots on bus 0 use type 1 I/O port config access rather than memory mapped
config access.
2008-09-10 18:06:08 +00:00
jhb
2a48176eba Extend the support for PCI-e memory mapped configuration space access:
- Rename pciereg_cfgopen() to pcie_cfgregopen() and expose it to the
  rest of the kernel.  It now also accepts parameters via function
  arguments rather than global variables.
- Add a notion of minimum and maximum bus numbers and reject requests for
  an out of range bus.
- Add more range checks on slot/func/reg/bytes parameters to the cfg reg
  read/write routines.  Don't panic on any invalid parameters, just fail
  the request (writes do nothing, reads return -1).  This matches the
  behavior of the other cfg mechanisms.
- Port the memory mapped configuration space access to amd64.  On amd64
  we simply use the direct map (via pmap_mapdev()) for the memory mapped
  window.
- During acpi_attach() just after loading the ACPI tables, check for a
  MCFG table.  If it exists, call pciereg_cfgopen() on each subtable
  (memory mapped window).  For now we only support windows for domain 0
  that start with bus 0.  This removes the need for more chipset-specific
  quirks in the MD code.
- Remove the chipset-specific quirks for the Intel 5000P/V/Z chipsets
  since these machines should all have MCFG tables via ACPI.
- Updated pci_cfgregopen() to DTRT if ACPI had invoked pcie_cfgregopen()
  earlier.

MFC after:	2 weeks
2008-08-22 02:14:23 +00:00
jhb
c2eea24c16 - Add support for memory mapped PCI config space access on Intel 915GM
and 5000P/V/Z chipsets.
- If the base address of the config space BAR is above 4GB for some reason
  and this isn't a PAE kernel, then warn about this (under bootverbose)
  and don't use the BAR.

PR:		kern/126525
Submitted by:	Arthur Hartwig @ Nokia
MFC after:	2 weeks
2008-08-20 18:18:17 +00:00
jhb
28d363a7a2 Use switch statements instead of if-else for enabling PCI-express config
space support.

MFC after:	1 week
2008-08-20 17:50:59 +00:00
kmacy
8c05b8ec89 Integrate support for xen in to i386 common code.
MFC after:	1 month
2008-08-15 20:51:31 +00:00
jhb
ca17618420 More properly handle links who only have 1 valid IRQ in their bitmask. The
old code special cased them too early which caused a few differences for
these sort of links relative to other PCI links:

- They were always re-routed via the BIOS call instead of assuming that
  they were already routed if the BIOS had programmed the IRQ into a
  matching device during POST.
- If the BIOS did route that link to a different IRQ that was marked as
  invalid, we trusted the $PIR table rather than the BIOS IRQ.

This change moves the special casing for "unique IRQ" links to only take
that into account when picking an IRQ for an unrouted link so that these
links will now not be routed if the BIOS appears to have routed it already
(some BIOSen have problems with that) and so that if the BIOS uses a
different IRQ than the $PIR, we trust the BIOS routing instead (this is
what we do for all other links as well).

Reported by:	Bruce Walter  walter of fortean com
MFC after:	1 week
2007-12-21 16:53:27 +00:00
jhb
4a39f29f1b MFamd64: 1.109 of pci_cfgreg.c which changes pci_cfgdisable() into a nop
for type #1 similar to what other OS's do.

MFC after:	3 days
2007-11-28 22:22:05 +00:00
jhb
2a71fa9467 Adjust the code to probe for the PCI config mechanism to use.
- On amd64, just assume type #1 is always used.  PCI 2.0 mandated
  deprecated type #2 and required type #1 for all future bridges which
  was well before amd64 existed.
- For i386, ignore whatever value was in 0xcf8 before testing for type #1
  and instead rely on the other tests to determine if type #1 works.  Some
  newer machines leave garbage in 0xcf8 during boot and as a result the
  kernel doesn't find PCI at all (which greatly confuses ACPI which expects
  PCI to exist when PCI busses are in the namespace).

MFC after:	3 days
Discussed with:	scottl
2007-11-28 22:20:08 +00:00
marius
d60b8a3096 Make the PCI code aware of PCI domains (aka PCI segments) so we can
support machines having multiple independently numbered PCI domains
and don't support reenumeration without ambiguity amongst the
devices as seen by the OS and represented by PCI location strings.
This includes introducing a function pci_find_dbsf(9) which works
like pci_find_bsf(9) but additionally takes a domain number argument
and limiting pci_find_bsf(9) to only search devices in domain 0 (the
only domain in single-domain systems). Bge(4) and ofw_pcibus(4) are
changed to use pci_find_dbsf(9) instead of pci_find_bsf(9) in order
to no longer report false positives when searching for siblings and
dupe devices in the same domain respectively.
Along with this change the sole host-PCI bridge driver converted to
actually make use of PCI domain support is uninorth(4), the others
continue to use domain 0 only for now and need to be converted as
appropriate later on.
Note that this means that the format of the location strings as used
by pciconf(8) has been changed and that consumers of <sys/pciio.h>
potentially need to be recompiled.

Suggested by:	jhb
Reviewed by:	grehan, jhb, marcel
Approved by:	re (kensmith), jhb (PCI maintainer hat)
2007-09-30 11:05:18 +00:00
jhb
ef27a04299 Revamp the MSI/MSI-X code a bit to achieve two main goals:
- Simplify the amount of work that has be done for each architecture by
  pushing more of the truly MI code down into the PCI bus driver.
- Don't bind MSI-X indicies to IRQs so that we can allow a driver to map
  multiple MSI-X messages into a single IRQ when handling a message
  shortage.

The changes include:
- Add a new pcib_if method: PCIB_MAP_MSI() which is called by the PCI bus
  to calculate the address and data values for a given MSI/MSI-X IRQ.
  The x86 nexus drivers map this into a call to a new 'msi_map()' function
  in msi.c that does the mapping.
- Retire the pcib_if method PCIB_REMAP_MSIX() and remove the 'index'
  parameter from PCIB_ALLOC_MSIX().  MD code no longer has any knowledge
  of the MSI-X index for a given MSI-X IRQ.
- The PCI bus driver now stores more MSI-X state in a child's ivars.
  Specifically, it now stores an array of IRQs (called "message vectors" in
  the code) that have associated address and data values, and a small
  virtual version of the MSI-X table that specifies the message vector
  that a given MSI-X table entry uses.  Sparse mappings are permitted in
  the virtual table.
- The PCI bus driver now configures the MSI and MSI-X address/data
  registers directly via custom bus_setup_intr() and bus_teardown_intr()
  methods.  pci_setup_intr() invokes PCIB_MAP_MSI() to determine the
  address and data values for a given message as needed.  The MD code
  no longer has to call back down into the PCI bus code to set these
  values from the nexus' bus_setup_intr() handler.
- The PCI bus code provides a callout (pci_remap_msi_irq()) that the MD
  code can call to force the PCI bus to re-invoke PCIB_MAP_MSI() to get
  new values of the address and data fields for a given IRQ.  The x86
  MSI code uses this when an MSI IRQ is moved to a different CPU, requiring
  a new value of the 'address' field.
- The x86 MSI psuedo-driver loses a lot of code, and in fact the separate
  MSI/MSI-X pseudo-PICs are collapsed down into a single MSI PIC driver
  since the only remaining diff between the two is a substring in a
  bootverbose printf.
- The PCI bus driver will now restore MSI-X state (including programming
  entries in the MSI-X table) on device resume.
- The interface for pci_remap_msix() has changed.  Instead of accepting
  indices for the allocated vectors, it accepts a mini-virtual table
  (with a new length parameter).  This table is an array of u_ints, where
  each value specifies which allocated message vector to use for the
  corresponding MSI-X message.  A vector of 0 forces a message to not
  have an associated IRQ.  The device may choose to only use some of the
  IRQs assigned, in which case the unused IRQs must be at the "end" and
  will be released back to the system.  This allows a driver to use the
  same remap table for different shortage values.  For example, if a driver
  wants 4 messages, it can use the same remap table (which only uses the
  first two messages) for the cases when it only gets 2 or 3 messages and
  in the latter case the PCI bus will release the 3rd IRQ back to the
  system.

MFC after:	1 month
2007-05-02 17:50:36 +00:00
jhb
3624354c54 Expand the MSI/MSI-X API to address some deficiencies in the MSI-X support.
- First off, device drivers really do need to know if they are allocating
  MSI or MSI-X messages.  MSI requires allocating powerof2() messages for
  example where MSI-X does not.  To address this, split out the MSI-X
  support from pci_msi_count() and pci_alloc_msi() into new driver-visible
  functions pci_msix_count() and pci_alloc_msix().  As a result,
  pci_msi_count() now just returns a count of the max supported MSI
  messages for the device, and pci_alloc_msi() only tries to allocate MSI
  messages.  To get a count of the max supported MSI-X messages, use
  pci_msix_count().  To allocate MSI-X messages, use pci_alloc_msix().
  pci_release_msi() still handles both MSI and MSI-X messages, however.
  As a result of this change, drivers using the existing API will only
  use MSI messages and will no longer try to use MSI-X messages.
- Because MSI-X allows for each message to have its own data and address
  values (and thus does not require all of the messages to have their
  MD vectors allocated as a group), some devices allow for "sparse" use
  of MSI-X message slots.  For example, if a device supports 8 messages
  but the OS is only able to allocate 2 messages, the device may make the
  best use of 2 IRQs if it enables the messages at slots 1 and 4 rather
  than default of using the first N slots (or indicies) at 1 and 2.  To
  support this, add a new pci_remap_msix() function that a driver may call
  after a successful pci_alloc_msix() (but before allocating any of the
  SYS_RES_IRQ resources) to allow the allocated IRQ resources to be
  assigned to different message indices.  For example, from the earlier
  example, after pci_alloc_msix() returned a value of 2, the driver would
  call pci_remap_msix() passing in array of integers { 1, 4 } as the
  new message indices to use.  The rid's for the SYS_RES_IRQ resources
  will always match the message indices.  Thus, after the call to
  pci_remap_msix() the driver would be able to access the first message
  in slot 1 at SYS_RES_IRQ rid 1, and the second message at slot 4 at
  SYS_RES_IRQ rid 4.  Note that the message slots/indices are 1-based
  rather than 0-based so that they will always correspond to the rid
  values (SYS_RES_IRQ rid 0 is reserved for the legacy INTx interrupt).
  To support this API, a new PCIB_REMAP_MSIX() method was added to the
  pcib interface to change the message index for a single IRQ.

Tested by:	scottl
2007-01-22 21:48:44 +00:00
jhb
dfb2d953f1 Give Host-PCI bridge drivers their own pcib_alloc_msi() and
pcib_alloc_msix() methods instead of using the method from the generic
PCI-PCI bridge driver as the PCI-PCI methods will be gaining some PCI-PCI
specific logic soon.
2006-12-12 19:27:01 +00:00
jhb
ea27014d6f Replace a few magic numbers. 2006-12-12 19:23:52 +00:00
jhb
fa70d01397 MD support for PCI Message Signalled Interrupts on amd64 and i386:
- Add a new apic_alloc_vectors() method to the local APIC support code
  to allocate N contiguous IDT vectors (aligned on a M >= N boundary).
  This function is used to allocate IDT vectors for a group of MSI
  messages.
- Add MSI and MSI-X PICs.  The PIC code here provides methods to manage
  edge-triggered MSI messages as x86 interrupt sources.  In addition to
  the PIC methods, msi.c also includes methods to allocate and release
  MSI and MSI-X messages.  For x86, we allow for up to 128 different
  MSI IRQs starting at IRQ 256 (IRQs 0-15 are reserved for ISA IRQs,
  16-254 for APIC PCI IRQs, and IRQ 255 is reserved).
- Add pcib_(alloc|release)_msi[x]() methods to the MD x86 PCI bridge
  drivers to bubble the request up to the nexus driver.
- Add pcib_(alloc|release)_msi[x]() methods to the x86 nexus drivers that
  ask the MSI PIC code to allocate resources and IDT vectors.

MFC after:	2 months
2006-11-13 22:23:34 +00:00
jhb
fe20b44cca Don't dump the $PIR table under bootverbose. The pirtool program in
src/tools/tools works fine, and dumping this table can add a lot of noise.

MFC after:	1 week
2006-11-09 18:03:36 +00:00
jhb
170b22254d - Make pcib_devclass private to sys/dev/pci/pci_pci.c and change all the
various pcib drivers to use their own private devclass_t variables for
  their modules.
- Use the DEFINE_CLASS_0() macro to declare drivers for the various pcib
  drivers while I'm here.
2006-01-06 19:22:19 +00:00
jhb
fde66b5a2e Move the hostb driver out of the i386 and amd64 PCI code (where it was
duplicated anyways) and into a single MI driver.  Extend the driver a bit
to implement the bus and PCI kobj interfaces such that other drivers can
attach to it and transparently act as if their parent device is the PCI
bus (for the most part).
2005-12-20 21:09:45 +00:00
rodrigc
82f361258c Add support for 7320 and 915 PCIe chipsets.
Submitted by:	Gavin Atkinson <gavin.atkinson at ury dot york dot ac dot uk>
PR:		kern/79139
Reviewed by:	scottl
2005-12-08 18:55:15 +00:00
imp
a37dc6aa6e Provide a dummy NO_XBOX option that lives in opt_xbox.h for pc98.
This allows us to eliminate a three ifdef PC98 instances.
2005-11-14 00:43:44 +00:00
nyan
ca9c26ef89 Fix pc98 build. 2005-11-09 12:22:26 +00:00
imp
c8edc59b40 Add support for XBOX to the FreeBSD port. The xbox architecture is
nearly identical to wintel/ia32, with a couple of tweaks.  Since it is
so similar to ia32, it is optionally added to a i386 kernel.  This
port is preliminary, but seems to work well.  Further improvements
will improve the interaction with syscons(4), port Linux nforce driver
and future versions of the xbox.

This supports the 64MB and 128MB boxes.  You'll need the most recent
CVS version of Cromwell (the Linux BIOS for the XBOX) to boot.

Rink will be maintaining this port, and is interested in feedback.
He's setup a website http://xbox-bsd.nl to report the latest
developments.

Any silly mistakes are my fault.

Submitted by: Rink P.W. Springer rink at stack dot nl and
	Ed Schouten ed at fxq dot nl
2005-11-09 03:55:40 +00:00
peter
cb1ff14efe MFamd64: indent with tabs instead of spaces. 2005-11-04 22:53:44 +00:00
wpaul
97e27d7231 Undo the change to pci_cfgdisable() on i386 for now. It seems to fix
the amd64 case, but makes the i386 case fail even more often.
2005-10-25 05:32:44 +00:00
wpaul
a413021644 Modify the pci_cfgdisable() routine to bring it more in line with
other OSes (Solaris, Linux, VxWorks). It's not necessary to write a 0
to the config address register when using config mechanism 1 to turn
off config access. In fact, it can be downright troublesome, since it
seems to confuse the PCI-PCI bridge in the AMD8111 chipset and cause
it to sporadically botch reads from some devices. This is the cause
of the missing USP ports problem I was experiencing with my Sun Opteron
system.

Also correct the case for mechanism 2: it's only necessary to write
a 0 to the ENABLE port.
2005-10-25 04:53:29 +00:00
imp
d01ccbd79e Expose legacy_pcib_alloc_resource, and use it in the mptable pci bus
implementation, like other routines in the legacy bus.

This should fix problems with resource allocation on MP systems without
ACPI enabled.
2005-09-17 23:57:53 +00:00
imp
c1f3701ab8 Commit a workaround to a problem with resource allocation. This helps
with some Dell servers that booted w/o a problem[*] on 5.4, but failed
with 6.0-BETA.

On the PCI bus, when we do lazy resource allocation, we narrow the
range requested as we pass through bridges to reflect how the bridges
are programmed and what addresses they pass.  However, when we're
doing an allocation on a bus that's directly connected to a host
bridge, no such translation can take place.  We already had a fallback
range for memory requests, but none for ioports.  As such, provide a
fallback for I/O ports so we don't allocate location 0, which will
have undesired side effects when the resources are actually used.

This fixes a problem with booting a Dell server with usb in the
kernel.  However, it is an unsatisfying solution.  I don't like the
hard coded value, and I think we should start narrowing the resources
returned to not be in the so-called isa alias area (where the ranage &
0x0300 must be 0 iirc).  Doing such filtering will have to wait for
another day.

This may be a good 6 candidate, maybe after its had a chance to be
refined.

Tested by: glebius@
2005-09-16 07:02:29 +00:00
imp
a67de82883 Note that pc98 specific defines maybe would be better in a header file. 2005-09-08 17:07:12 +00:00
jhb
373a6e31c9 - Ignore BIOS IRQs (that is, IRQ settings left by the BIOS or a previous OS
in the PCI config registers) that are > 15 as $PIR can only route PCI
  interrupts to ISA IRQs which are limited to the 0 to 15 range.
- Remove an extra word from a printf.

Reported by:	othermark atkin901 at yahoo dot com
MFC after:	3 days
2005-07-13 15:41:16 +00:00
jhb
d6a800e592 Trust the settings programmed by the BIOS over what the $PIR says.
Specifically, if the BIOS has programmed an IRQ for a device that doesn't
match the list of valid IRQs for the link, use it anyway as some BIOSes
don't correctly list the valid IRQs in the $PIR.  Also, allow the user
to specify an IRQ that $PIR claims is invalid as an override, but emit a
warning in that case.
2005-04-14 18:25:09 +00:00
jhb
4057d2fbc5 Add code to read the primary PCI bus number out of the Compaq/HP 6010
hotplug Host to PCI bridge.  This is only needed for the non-ACPI case
as the BIOS includes a proper _BBN method in ACPI.
2005-03-25 14:18:50 +00:00
phk
13100c3699 Make a bunch of malloc types static.
Found by:	src/tools/tools/kernxref
2005-02-10 12:02:37 +00:00
imp
8d58b9df12 /* -> /*- for copyright notices, minor format tweaks as necessary 2005-01-06 22:18:23 +00:00
scottl
071f99a397 Remove a stray critical_exit().
Submitted by: johan
2004-12-13 07:08:44 +00:00
scottl
a014627e19 Expand the scope of the critical section in the PCIe read and write methods
on the advice of Alan Cox.
2004-12-10 15:44:12 +00:00
scottl
f98e4c8a08 Due to a significant addition of code, add my copyright to this file. Also
note that the PCIe work was made possible due to hardware donations from
the FreeBSD Foundation and Intel.  Thanks!
2004-12-06 18:19:32 +00:00
scottl
b62f254b42 Add support for the memory-mapped PCI Express configuration mechanism. This
actually is a property of the northbridge and applies to all PCI/PCI-X/PCIe
devices in the system, though only PCIe devices will respond to registers
higher than 256.  This uses per-CPU pools of temporary mappings so that
the whole 256MB of configuration space doesn't have to be mapped all at
once.  While the sf_buf API was considered for this, the fact that it
requires sleep locks and can return failure made it unsuitable for this use.

For now only the Intel Grantsdale and Lindenhurst (925 and 752x) chipsets are
supported.  Since there doesn't appear to be a compatible way to determine
northbridge support, new chipsets will have to be explicitely added in the
future.
2004-12-06 08:27:10 +00:00
des
22d75b597a Add TUNABLE_LONG and TUNABLE_ULONG, and use the latter for the
hw.pci.host_mem_start tunable.  Add comments to TUNABLE_INT and
TUNABLE_QUAD recommending against their use.

MFC after:	3 weeks
2004-10-31 15:50:33 +00:00
des
871722fc59 Whitespace cleanup 2004-10-31 15:02:53 +00:00
imp
a5e0614f34 Make the lower range of the memory area 0x80000000 again. Also
introduce hw.{pci,acpi}.host_mem_start tunable to change this.

MFC: ASAP
2004-10-11 21:10:23 +00:00
imp
f3f59ffab7 Add missing 'static' 2004-10-06 15:18:12 +00:00