Skip to content

hjunkes/rtems-libbspext

 
 

Repository files navigation

NOTE ABOUT MEMORY PROBING AND PCI CONFIGURATION SPACE SCANNING
--------------------------------------------------------------

Memory probing installs an exception handler to 
catch machine check and data access exceptions
during a probe operation. Therefore, it runs
with the MCP interrupt enabled.

Note that this most likely raises exceptions
when trying to read from PCI configuration
space at unused slots (e.g. when scanning config
space for a particular device). Applications
which need both, memory probing (mostly used by
VME drivers) AND PCI config space scanning should
scan PCI once, prior to initializing libBspExt
and cache the vendor/deviceids found (e.g. as
done by my SVGM BSP).

PCI drivers loaded after initialization of memory
probing should then scan the cached info for
their device to avoid raising exceptions.

This is a better approach than using memory probing
on PCI config space due to the high overhead and
latency of memory probing.

Till Straumann, <[email protected]>, 2003/7

Here's more info -- answering a question (2004/11/3)

Eric Norum wrote:
> Here's a snippet of code from the SIS 3301 transient recorder driver:
> 
>     if(devReadProbe(4,a32+MODID,&probeValue)!=0) {
>         printf("sisfadcConfig: no card at %p\n",a32);
>         return(0);
>     }
> 
> MODID is defined to be 0x4.
> 
> When this is run with a32=0x21000000, but with no VME device at location 
> 0x21000000 I would expect the printf shown above to be executed.  
> Instead the devReadProbe returns 0 and sets probeValue to -1.
> 
> All this PCI/VME mapping

Boards with a tundra universe bridge usually access VME
from the CPU local bus (powerpc bus) traversing one or more PCI
busses. As each of these busses constitutes a separate address
space (VME itself featuring multiple address spaces..,), 
a VME address must be translated into a CPU address.

The address to be used with devReadProbe() is a CPU address, hence
given a VME address you need to compute the correct CPU address
first (which is what devRegisterAddress() does).

devLibOSD.c [RTEMS] relies on the BSP to provide a routine or
macro 'BSP_vme2local_adrs()' for this translation [since managing
address spaces across busses is clearly a BSP area].

Kate, can you confirm that 0x21000000 is within the CPU
address range your BSP assigns to VME ? [looks a little fishy
to me, since on a CHRP board, 0x21000000 is not in the
PCI range]

E.g., on the SVGM, I map VME A32 0x20000000..0x2f000000 to
0xc0000000..0xcf000000 on PCI and the host bridge translates
this 1:1 (CHRP) to CPU space. Hence, I'd address
0x21000000 [VME A32] at 0xc1000000 [CPU]. The respective
translation is performed by svgm's BSP_vme2local_adrs().

> and probing is a mystery to me so please let me 
> know if I'm doing something wrong.......

Probing an address is not quite trivial. This is also
why it is *NEVER* a good idea to use the 'probe' routine
for regular access to the device (as e.g., done by the
Hytec 'hotswap' drivers). In order to detect possible
misuse of the probe routines, libbspExt prints a warning
message about 'killing real-time performance'.

Write-probing an address is more difficult than read probing
because on some busses, writing data may be only loosely
coupled to the CPU side, i.e., an eventual bus error may
be raised long after the CPU posted the write operation
and is already executing in a different context.

Read-probing, OTOH must always wait for the read operation
to complete on the target bus and is therefore much more
predictable. libbspExt only implements read probing.

The actual probing algorithm has to deal with a variety of
scenarios that could go wrong when trying to read an address:

1) No mapping in MMU
2) Protection violation ["e.g., no read access in user mode"]
3) bus error [PPC, PCI, VME]

In 1 and 2, no address is ever generated by the CPU. Instead,
an exception is raised by the CPU and is properly handled
by libbspExt() itself.

3) is more involved: the CPU generates an address but the
   read operation can fail at different levels: at the
   host bridge, on the PCI bus or on the VME bus.

libbspExt() relies on the VME bridge somehow propagating
a bus error upstream to the host bridge where is can be
detected [this is a required BSP/board feature - the
universe VME master propagates a VME-BERR to a PCI target
abort which should be detected by the host bridge].

libbspExt() can handle two scenarios when a bus error is
encountered:

A) host bridge detects a bus error and pulls a hardware
   line at the CPU (so called MCP or TEA line) which in
   turn raises an exception that is properly handled by
   libbspExt.

B) host bridge detects a bus error and has status available
   in some register but does not generate any sort of interrupt.
   libbspExt polls the host bridge after performing the read
   operation to detect errors in B) [this requires disabling
   interupts and scheduling during the entire probing algorithm!!] 


For both scenarios, libbspExt needs a BSP provided routine
('_BSP_clear_hostbridge_errors()') which reports and resets
errors in the host bridge [this routine should catch ALL
errors: invalid address, PCI bus error].
The routine is also responsible for enabling the MCP and/or TEA
interrupts in the host bridge under scenario A.
In particular, the routine MUST report -1 (failure) when libbspExt
asks to enable the interrupts. This way, libbspExt knows
that it has to resort to scenario B.

A small fix to 'memProbe.c' is needed to properly handle
boards which don't support MCP/TEA interrupts (latest
version attached).

T.

> 
> The actual printout is:
> drvSISfadcConfigure(5,80,0x21000000,0x88,3,0)
> Warning: bspExtMemProbe kills real-time performance.
>          use only during driver initialization
> 
>          clear the 'bspExtVerbosity' variable to silence this warning
> Illegal sisType probeValue ffffffff
> 

About

RTEMS BSP Extensions Packaging

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 93.5%
  • Makefile 6.5%