|
Please post any updates, additions, or questions on the developer forums at http://forum.sun.com
1. Why does the amount of dictionary
space vary with each version of OpenBoot?
2. Is there a method of calculating
exactly how much dictionary space is available per bus or plug-in slot?
3. My
fcode driver incorrectly specifies the devices "reg" property or is missing
some of the values of the "reg" property. In SunOS 4.x, I used to be able
to work around this by manipulating the data in the dev_info structure.
How can I fix this in SunOS 5.x?
4. My
fcode driver only creates a "name" property and doesn't create any "reg"
property at all. Can I use "registers" wildcarding?
1. Why does the
amount of dictionary space vary with each version of OpenBoot?
This happens because the amount of dictionary
space must be fixed at compile time, and OBP necessarily uses that resource.
The "user available" dictionary space will vary for each new release because
OBP may implement some new functionality, thus leaving *less* space for
plug-in devices, but new releases may also employ more efficient methods
of implementing some function than in previous releases, thus leaving *more*
space for plug-in cards.
2.
Is there a method
of calculating exactly how much dictionary space is available per bus or
plug-in slot?
Dictionary space is not allocated per bus or slot,
it is one large pool which is consumed on a "as probed" basis. If
your card is the only one in the system and you are running out of dictionary
space then there is a major problem with the board/FCode. However,
if your card is one of the last to be probed, then it's possible that other
cards are consuming "normal" amounts of the dictionary and that your card
is just trying to get a little more than is left over. It is also
possible that the FCode on your card could be written inefficiently such
that you could reduce its dictionary space requirements by some margin.
Below are a few suggestions on how you might reduce your dictionary usage;
-
Reduce your use of 'external' or 'headered' words
wherever possible. (Instead use 'headerless'.) Note that by default
you will get 'headered' words. If you think you'd like to keep a
word for debug purposes only, but it's not normally needed, make it 'headered',
thus you can see it when you need it if you set the "fcode-debug?" nvram
var to 'true'.
-
Use instance definitions wherever possible.
It's probable that some of the definitions may have to be left
global, but judicious use of instance definitions of 'variable',
'constant', 'value' and other defining words will help.
-
Remove "frivolous" definitions. For example,
if there were many places in your code where you are adding 2 to another
number, and you decided to create a word like : 2+ ( n1 -- sum ) 2 + ;
, that might make sections of your code appear more compact, but the defined
word may be using dictionary space.
-
Don't create properties that are unneeded.
-
Don't change properties after they're created, unless
necessary.
-
If a property is to be created once, and never changed
later, it's better to create it "in-line", rather than creating a word
like "create-props" which is called later to create the properties.
3. My fcode driver incorrectly
specifies the device's "reg" property or is missing some of the values
of the "reg" property. In SunOS 4.x, I used to be able to work around this
by manipulating the data in the dev_info structure. How can I fix this
in SunOS 5.x?
As long as the fcode
driver specifies at least one "reg" property, correctly or incorrectly
for the device, you can use the "registers" property in the drivers hw.conf
file to specify wildcarded values for any incorrectly specified "reg" properties.
Here's how to do this in the driver.conf(4) file.
Example 1:
Device has registers
at offset 2000 for 100 bytes and a second set of registers at offset 10000
for 200 bytes. Device is an sbus device whose parent node is always an
sbus. The fcode driver "forgot" to export the second set of registers.
name="foo" class="sbus" registers=-1,2000,100,-1,10000,200;
Example 2:
Device has registers
at offset 3000 for 256 bytes. The fcode driver only specifies that the
registers have 32 bytes. The device is an sbus device whose parent node
is always an sbus.
name="foo" class="sbus" registers=-1,3000,256;
In both of these
examples, when the framework is creating internal data structures, the
wildcarding will apply to all self-identifying devices with the same name,
and the correct "sbus slot number" will be filled in to the "reg" property
by the framework. The information specified in these examples *augments*
the information provided by the fcode driver and overrides the fcode drivers
specification of the "reg" property.
When using "registers",
note that the external name of the device in the /devices tree will be
the name as exported by the fcode drivers "reg" property. (So we can correctly
mount root or use the device as a console, for example.)
4. My fcode driver only creates
a "name" property and doesn't create a "reg" property at all. Can I use
"registers" wildcarding?
No, you must be able
to fill in the correct slot number. If your device's fcode driver does
not export even an incorrect "reg" property, Solaris cannot figure this
information out and cannot complete the information.
In this case, the
only thing you can do is to provide site specific driver.conf(4)
files
using the "reg" property with one line (one entry) for each instance of
your card at that particular site. In this case, you will not be able to
access other properties that may be correctly specified by the fcode driver,
so you must include all of them (including interrupts and any other properties
you might need defined) in the driver.conf(4)
file.
PCI FCode FAQs
The following questions deal primarily with PCI FCode PROMs, even
though some questions are generic and their answers may also be applicable
to SBus FCode PROMs.
1. Can you describe the PCI FCode
PROM Header Format?
2. Can you describe the PCI expansion
PROM Header Format?
3. Can you describe the PCI expansion
PROM data structure format?
4. I am using the tokenizer from
DDK 2.5.1 CD. How do I add a PCI header to my PROM?
5. What is the format of a physical
address in the reg property?
6. When I load my FCode, do I need
to do anything special to access the configuration space registers of my
device?
7. What address do I use to access
the configuration registers on my PCI device?
8. When I load my FCode, I can't
access memory space locations. How can I enable access to memory space
locations on my PCI device?
9. I can't access my expansion
FCode PROM. How can I enable access to my expansion FCode PROM?
10. I don't know who sets various base
address registers (in configuration space) for the PCI device, the FCode
PROM or the Operating System? Some software needs to set them up before
the driver takes over...
11. Can you determine the cache line
size of the machine from the FCode, to write into the cache-line-size configuration
space register of my PCI device?
12. When I try to test a new version of my
FCode program, I create a new package - How do I get rid of or override
the original package so that the downloaded code is executed?
13. How can I access device registers or memory
on my plug-in PCI card from OpenBoot?
14. I am trying to load FCode from ethernet.
The code seems to load ok, but when I try to build the package I get an
error:
15. Are there any debugging flags on Sun systems
to debug FCode?
16. On my Sun Ultra-30 UPA/PCI, system there
are two nodes related to PCI; /pci@1f,4000 and /pci@1f,2000 . I need to
know which of these paths represents pcia and pcib, so that I can establish
their relationship to the NVRAM configuration variables "pcia-probe-list"
and "pcib-probe-list".
17. If the FCode PROM is not present in a
PCI device, some properties are created by the motherboard CPU PROM from
the information given in its configuration space registers. What are the
names of those properties?
18. How can I find and use physical addresses
to access, say, configuration space registers on Sun Ultra-30 UPA/PCI systems?
19. I am still testing my FCode, but when
I use "select-dev" on my device I get errors. How do I debug my FCode/device
in this case?
20. How can I control probing of pci slots
on my Sun Ultra-30 UPA/PCI system?
21. What should I keep in mind when using
3.x tokenizer and 3.x CPU PROMs?
22. What is the required set of properties
for the expansion ROM?
23. When the configuration software probes
my PC I slot, does it read my PROM 32-bits at a time, or one byte at a
time?
24. Beside the header, what is the minimum
amount of FCode which is required?
25. In the past I've used tokenizer version
2.3 for SBus FCODE development - is it OK to use that same tokenizer for
PCI FCode PROM development, or do I need new tokenizer?
26. I am writing FCode for a bootable device.
It appears to me that there are 3 kinds of software that come into play
during a boot: kernel, FCode and OS-driver. Can someone briefly explain
what each does and the order in which they kick in?
27. What conventions should I follow in naming
my devices using FCode proms?
28. Where can I find additional documentation?
1. Can you describe the
PCI FCode PROM Header Format?
PCI FCode PROM Header Format is as follows:
---------------------------------------------------
a.out header
32 bytes (Needed by some utilities)
---------------------------------------------------
PCI expansion PROM Header
28 bytes
---------------------------------------------------
PCI data struct.
24 bytes
---------------------------------------------------
FCode (8 Byte FCode header + FCode code bytes)
---------------------------------------------------
The above a.out header is also needed if
you want to download your FCode image (e.g. during test/development of
your FCode driver you may not want to use a physical PROM) using "dload"
or "boot" on a Solaris 1.x (SunOS 4.x) system. In case you are "dload"ing
or "boot"ing your FCode image on a Solaris 2.x system, you need to replace
the a.out header with an ELF header. The fakeboot utility can add
either an a.out or an ELF header, based on parameters you pass to fakeboot.
The add_hdr utility can also add either an a.out or an ELF header,
in addition to adding the PCI header and the PCI data structure.
2. Can you describe the
PCI expansion PROM Header Format ?
PCI expansion PROM Header Format (28 bytes) is
as follows:
Byte offset value
description
-----------------------------------------------
00 55(h)
PROM signature byte one.
-----------------------------------------------
01 aa(h)
PROM signature byte two.
-----------------------------------------------
02-03 34 00 (h) SPARC reserved
value
-----------------------------------------------
04-17 00 00 ... reserved
for processor
architecture unique data.
-----------------------------------------------
18-19 1c 00
Pointer to PCI data str.
(assuming PCI data str. follows
immediately after PCI expansion PROM Header)
-----------------------------------------------
1a-1b 00 00
pad bytes
-----------------------------------------------
3. Can you describe PCI
expansion PROM data structure format?
PCI expansion PROM data struct. (24 bytes) looks
as follows:
Byte offset description
/(Hex. value)
--------------------------------------------
00-03 signature : P C I R (50 43 49 52)
--------------------------------------------
04-05 vendor id
--------------------------------------------
06-07 device id
--------------------------------------------
08-09 ptr to Vital Product Data
--------------------------------------------
0A-0B PCI data str. length (18 00)
--------------------------------------------
0C PCI data str.rev.
(0)
--------------------------------------------
0D-0F class,subclass code
--------------------------------------------
10-11 image length in 512 bytes
--------------------------------------------
12-13 rev. level of code/data
--------------------------------------------
14 code type (01)
--------------------------------------------
15 indicator byte. For last image (80)
--------------------------------------------
16-17 reserved (00 00)
--------------------------------------------
Following is a dump of initial bytes in a PCI
FCode PROM, with the a.out header in the first 32 bytes.
hex
addr
hex value
-----------------------------------------------------
00000
01 03 01 07 00 00 46 98 00 00 00 00 00 00 00 00
00010
00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00
00020
55 aa 34 00 00 00 00 00 00 00 00 00 00 00 00 00
00030
00 00 00 00 00 00 00 00 1c 00 00 00 50 43 49 52
00040
8e 10 01 10 00 c0 18 00 00 00 00 02 7e 00 00 01
00050
01 80 00 00 f1 03 18 6e 00 00 46 64 vv xx yy zz
For above PROM, Vendor Id is 0x108e, Device Id
is 0x1001,
Pointer to Vital Data Product is 0xc000, class/subclass
code is 0x020000, image length (in 512 bytes)
is 0x7e,
FCode length is 0x4664 bytes, vv ... are FCode
data.
4. I am using the tokenizer
from DDK 2.5.1 CD. How do I add a PCI header to my PROM?
You can put PCI vendor-id, device-id, class code,
vpd-offset, code-revision in your PCI ROM data structure as follows:
tokenizer[
h# 108e h# 1001 h# 020000 pci-header
( vendor-id device-id class-code -- )
h# c000
pci-vpd-offset ( w -- )
0
pci-code-revision ( w -- )
]tokenizer
FCode-version3
....
....
end0
Above code, after tokenizing, will generate header
as follows: (first 32 bytes shown are a.out header's bytes)
hex
addr
hex value
----------------------------------------------------------
00000
01 03 01 07 00 00 46 98 00 00 00 00 00 00 00 00
00010
00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00
00020
55 aa 34 00 00 00 00 00 00 00 00 00 00 00 00 00
00030
00 00 00 00 00 00 00 00 1c 00 00 00 50 43 49 52
00040
8e 10 01 10 00 c0 18 00 00 00 00 02 7e 00 00 01
00050
01 80 00 00 f1 03 18 6e 00 00 46 64 vv xx yy zz
----------------------------------------------------------
If you don't have tokenizer 3.1 , you can obtain
it from the tools page on this site.
5. What is the format of
a physical address in the reg property?
For PCI, the reg property value has 5 32bit
nos. - phys.hi, phys.mid, phys.low, size.hi and size.low. size.hi
and size.low are values for size of register whose address and type
are defined by phys.hi,phys.mid and phys.low.
Format of Physical address in reg property
is as follows:
phys.hi
cell: npt000ss bbbbbbbb dddddfff rrrrrrrr
phys.mid cell: hhhhhhhh hhhhhhhh
hhhhhhhh hhhhhhhh
phys.low cell: LLLLLLLL LLLLLLLL
LLLLLLLL LLLLLLLL
where
n is 0 if the address is relocatable,
1 otherwise
p is 1 if the addressable region
is "prefetchable", 0 otherwise
t is 1 if the address is aliased
(for non-relocatable I/O), below
1MB (for Memory), or below 64KB (for relocatable I/O)
ss=00 ==> Configuration space
ss=01 ==> I/O space
ss=10 ==> 32 bit Memory space
ss=11 ==> 64 bit Memory space
bbbbbbbb is 8 bit bus no. (assigned
by CPU PROM at probe time)
ddddd is 5 bit device no.
fff is 3 bit function no.
rrrrrrrr is 8 bit reg. no.
hh..hh is a 32 bit unsigned
number, most significant portion
LL..LL is a 32 bit unsigned
number, least significant portion
6. When I load my FCode,
do I need to do anything special to access the configuration space registers
of my device?
No, access to configuration space registers can
not be disabled on PCI devices. Configuration space registers are always
accessible.
7. What address do I use
to access the configuration registers on my PCI device?
Look in the format for physical address of reg
property. You can use the phys.hi cell of the first entry in the
reg
property, as base address for configuration space. The first entry
in the
reg property must be the config space entry (bbbb.bbbb.dddd.dfff.0000.0000
binary). Using that (or any other method) obtain values of bbbb.bbbb,
ddddd and fff for your device. Then use
ok " <parent-pci-bus-node>"
select-dev
ok <bbbb.bbbb.dddd.dfff>XX
config-l@
(XX is offset
for that particular configuration register)
e.g. if bus no. is 1000.0001
(0x81)
device no. is 0.0000 and function no. is 001 (0x01) then, you will use
ok " /pci@1f,2000" select-dev
ok 81.0100 config-l@ ( to read device id and vendor id)
ok 81.0104 config-w@ ( to read command register )
ok 81.0110 config-l@ ( to read Base Address Register0, at 0x10 )
ok 81.0130 config-l@ ( to read Expansion PROM base address register
)
8. When I load my FCode,
I can't access memory space locations. How can I enable access to memory
space locations on my PCI device?
Look in the format for physical address of reg
property. Using that (or any other method) obtain values of bbbb.bbbb,
ddddd and fff for your device. Then use
ok " <parent-pci-bus-node>" select-dev
ok <bbbb.bbbb.dddd.dfff>04 dup config-w@ 3 or swap config-w!
Above will write 3 to the command register in
configuration space and thus will enable access to memory and I/O space.
This sets bit[0] and bit[1] of the command register. You may similarly
set other bits in the command register, if needed by your application.
e.g. if bus no. is 1000.0001
(0x81)
device no. is 0.0000 and function no. is 001 (0x01) then, you will use
ok " /pci@1f,2000" select-dev
ok 81.0104 dup config-w@ 3 or swap config-w!
Normally the "open" routine of your FCode driver
should enable such access. FCode can use the value returned by "my-space"
and add offset of 4 to get the address of the command register and then
set various bits in the command register to enable a particular access.
The "close" routine should disable that access.
9. I can't access my expansion
FCode PROM. How can I enable access to my expansion FCode PROM?
Look in the format for physical address of reg
property. Using that (or any other) method, obtain values of bbbb.bbbb,
ddddd and fff for your device. Then use
ok " parent-pci-bus-node" select-dev
ok <bbbb.bbbb.dddd.dfff>04 config-w@ 3
or
<bbbb.bbbb.dddd.dfff>04 config-w!
ok <bbbb.bbbb.dddd.dfff>30 config-l@ 1
or
<bbbb.bbbb.dddd.dfff>30 config-l!
The above will first enable memory and I/O space
access and then will read a value from the expansion PROM base address
register in configuration space (at offset 0x30) "or" 1 to it, and
write this new value in the Expansion PROM base address register to enable
access to your FCode PROM. This sets bit[0] of the Expansion PROM
base address register.
e.g. if bus no. is 1000.0001
(0x81)
device no. is 00000 and function no. is 001 (0x01) then, you will use
ok " /pci@1f,2000" select-dev
ok 81.0104 config-w@ 3 or 81.0104 config-w!
ok 81.0130 config-l@ 1 or 81.0130 config-l!
If for any reason, (e.g. to access Vital Product
Data stored in PROM) FCode needs to access PROM data, then FCode
should enable access to PROM by using value returned by "my-space"
and adding an offset of 0x30 to it as address of register. FCode
should read value from that address, "or" 1 and write it to that
address. Also since FCode would have been copied in memory, devices' memory
and I/O space may not be enabled. So FCode needs to enable them as
well. using FCode:
ok my-space h# 30 + dup config-l@ 1 or swap config-l!
( enable PROM access )
ok my-space h# 4 + dup config-w@ 3 or swap config-w!
( enable I/O, memory access )
Using above example, one can disable Expansion
PROM access as:
ok my-space h# 30 + dup config-l@ 1 invert and swap config-l!
( disable PROM access )
10. I don't know who sets
various base address registers (in configuration space) for the PCI
device, the FCode PROM or the Operating System? Some software needs to
set them up before the driver takes over...
The CPU PROM (not the PCI card's FCode PROM) allocates
base address for memory and/or I/O space on your PCI device and for
the FCode PROM itself. So the CPU boot PROM of the main system will
initialize these base addresses.
11. Can you determine
the cache line size of the machine from the FCode, to write into the cache-line-size
configuration space register of my PCI device?
The cache-line-size register in configuration
space refers to the cache line size supported by the PCI device.
12. When I try to test
a new version of my FCode program, I create a new package as follows :
ok 4000 dload /stand/mydev.fcode
ok 0 0 " 4,0" " /pci@1f,2000" begin-package
ok 4020 1 byte-load
ok end-package
However, when I do an "ls", I find that I now
have TWO packages corresponding to my card:
ok ls
ffd70c00 pci108e,1001@4,0
ffd6e860 pci108e,1001@4,0
ok
How do I get rid of or override the original
package so that the downloaded code is executed? Should I just remove
the PROM from the card?
Remove the PROM for PCI card. CPU PROM will still
create a device node for the card, but the "name" property will have
a value of the form "pci<DDDD>,<VVVV>". Create a name property
for your device in your downloaded code with a value different than
the one created by CPU PROM. And then refer to your device by full
device path.
13. How can I access device
registers or memory on my plug-in PCI card from OpenBoot?
FAQ #7 showed how to access configuration
space registers of a plug-in PCI device. Also, you will need to enable
access to memory space (FAQ #8).
To access device registers or memory, which is
on PCI memory space, find out which Base Address Register corresponds
to the memory space. You can get this info. either from device hardware
manual or by looking at "reg" property for that device and seeing which
entry starts with 02cc.ccxx, where cccc refers to its
config address. (Base Addresses are at 0x10, 0x14, 0x18, 0x1c,
0x20, 0x24 in config. space, so xx will be one of above values.)
Assuming memory space is controlled by the base address at offset 0x10,
map that space as follows:
ok " <device-path>"
begin-select-dev
( now to map 0x3000 bytes and
store its virtual address in mem-vaddr
ok 0 value mem-vaddr
ok 0 0 02cc.cc10 3000 " map-in"
$call-parent to mem-vaddr
ok mem-vaddr l@ .
( will fetch and display 32 bit quantity at
offset 0 in memory space).
ok mem-vaddr 30 + w@ .
( will fetch and display 16 bit quantity at
offset 0x30 in memory space).
If memory space is accessible contiguously, one
can dump its content as follows:
ok mem-vaddr 40 + 70 dump
( will dump 0x70 bytes from memory space
starting at offset 0x40)
14. I am trying to load
FCode from ethernet. The code seems to load ok, but when I try to
build the package I get an error:
ok 4000 dload /stand/cheerio.o
Boot device: /pci@1f,4000/network@1,1:,|stand|cheerio.o
File and args:
ok 0 0 " 0,1" " /pci@1f,2000" begin-package
ok 4000 1 byte-load
Unimplemented FCode token before address
4004
<----- message
Warning: FCode sequence resulted in
a net stack depth change of 1 <----- message
ok
An error is possibly occurring due to:
1) PCI header attached to PROM image
or
2) my-address is two 32 bit nos. for PCI and
only one 32 bit no. for Sbus.
To determine if #1 is the problem, dump the downloaded
image, starting from 4000, e.g. "4000 60 dump", and see where "f1", (or
"fd") starts. These
byte-codes indicate the beginning of the PROM
image for byte-load, so use the address of the byte code in the byte-load
command, e.g. "ok X 1 byte-load". "f1" indicates the beginning of
the FCode header, which is 8 bytes long, as:
f1;tokenizer-version;2
reserved bytes/checksum;4bytes of FCode length;
If #2 is the problem, change your FCode to handle
two numbers returned from "my-address". One way to do is:
my-address constant
my-bus-addr-mid constant my-bus-addr-low
: my-bus-addr ( -- paddr.low
paddr.mid )
my-bus-addr-low my-bus-addr-mid
;
and then using "my-bus-addr" in creation of the
reg
property etc.
15. Are there any
debugging flags on Sun systems to debug FCode?
You can set NVRAM variable fcode-debug? to true
for keeping the headers for those words which are preceded with headers
in your source.
Also, some CPU PROMS have a variable named "fcode-verbose?"
to display each FCode as it is being read by token interpreter at
probe time of your FCode PROM. To turn it on do: (before you probe your
FCode)
ok true to fcode-verbose?
<probe-your-card>
To set it from NVRAMRC, do
ok nvedit
0: true to fcode-verbose?
^C
ok nvstore
ok setenv use-nvramrc? true
ok reset-all
Some CPU PROMs have pcimsg? and probemsg?
variables to give additional PCI related info. You can turn them
ON in a way similar to above way. "pcimsg?" controls display of all accesses
to PCI configuration space. "probemsg?" controls display of probing status
information including physical allocation.
Note that not all CPU PROMs have pcimsg? and probemsg?.
Also, in future PROMs, behavior of pcimsg?, probemsg?
and fcode-verbose? may change including complete disappearance of
above variables.
16. On my Sun Ultra-30
UPA/PCI, system there are two nodes related to PCI; /pci@1f,4000
and /pci@1f,2000 . I need to know which of these paths represents
pcia and pcib, so that I can establish their relationship to the NVRAM
configuration variables "pcia-probe-list" and "pcib-probe-list".
Each PCI bus has a property, slot-name,
which gives some information about slots on that PCI bus, and which may
sometimes give a clue as to which NVRAM variable corresponds to it. To
get a human readable value for slot-name, do following:
ok " /pci-bus-node" select-dev
ok " slot-name" get-my-property drop decode-int .h cr type
e.g. for pci bus at /pci@1f,2000:
ok " /pci@1f,2000" select-dev
ok " slot-name" get-my-property drop decode-int .h cr type
will display something like:
6
pcia slot 1pcia slot 2
This is an indication that devices under /pci@1f,2000
relate to "pcia".
In Sun Ultra-30 UPA/PCI with 4 plug in PCI slots,
only slot# is physically present for pci@1f,2000 and it can also
support 66 Mhz., 64 bit PCI devices.
ok " /pci@1f,4000" select-dev
ok " slot-name" get-my-property drop decode-int .h cr type
34
pcib slot 2pcib slot 4pcib slot 5
This is an indication that devices under /pci@1f,4000
relate to "pcib". In Sun Ultra-30 UPA/PCI with 4 plug in PCI slots:
a) slots
2, 4 and 5, under /pci@1f,4000 support 33 Mhz., 32 bit PCI devices.
b) Slot 3 under /pci@1f,4000
is for on-board scsi device.
Note that the value contained in slot-name
is different for different systems. For some systems, the contents
of slot-name may not indicate a relationship between the device
paths ad PCI busses "pcia" and "pcib". Also, in different releases of a
PROM for the same system, the value of slot-name may change.
You may need to refer to system documentation to determine details about
the PCI busses on a particular system.
Alternatively, by setting nvram variables to different
values and/or by plugging pci card(s) in different slot(s), one can determine
which nvram configuration variable refers to which pci bus.
17. If the FCode PROM
is not present in a PCI device, some properties are created by the
motherboard CPU PROM from the information given in its configuration space
registers. What are the names of those properties?
If the FCode PROM is not present on a PCI plug-in
card, the CPU PROM will generate the following properties in the device
node for the PCI device; vendor-id, device-id, revision-id,
class-code,
name,
reg,
compatible
and devsel-speed from information in configuration space registers.
The interrupts property is present if the Interrupt Pin register
is non-zero.
The following properties will be present only
if the corresponding capability is available from the device or that corresponding
value was non-zero, as indicated in configuration space registers:
66mhz-capable, udf-supported,
cache-line-size,
fast-back-to-back,
subsystem-id and subsystem-vendor-id.
The CPU PROM also creates min-grant and
max-latency
properties, unless the header type is 01. The CPU PROM also creates
the assigned-addresses property, with entries for each base address
register for which an address was assigned.
18. How can I find and
use physical addresses to access, say, configuration space registers on
Sun Ultra-30 UPA/PCI systems?
It is probably easiest to use physical addressing
if you simply do MMU bypassing with the choice of the correct ASI space.
The arguments for the space{c,d,w,l,x} command includes an address and
ASI code (and data for a write operation.)
On Sun Ultra-30 UPA/PCI systems, config registers
of a pci device are viewed using the following addr: 1fe.0100.0000
+ X
where the 32bit value of X represented in bit
format is as:
bbbb.bbbb.dddd.dfff.rrrr.rrrr
where bbbb.bbbb is eight bit
bus no.
dddd.d is five bit device no.
fff is three bit function no.
rrrr.rrrr is register no.
So, if bus no. is 81, device no. is 0 and function
no. is 1, then X will be 81.0100, giving you the base of the configuration
registers. You'd then access the 0th config register at 1f0.0181.0100
(physical address).
On Sun Ultra-30 UPA/PCI systems, you can use ASI
0x15 for non-cacheable address being accessed via MMU bypass. If
you are accessing a little endian device use ASI 0x1d.
You can get bus no., device no. and function no.
from "my-space" after selecting that device, or from value of the
reg
property for that device. Look in IEEE 1275/PCI binding for the format
of reg.
In general for any system, to get the physical
addresses for registers in any space (config space, 32 bit memory space,
etc.) use the "map-in" command, which requires the phys.lo,phys.mid,phys.hi
and length arguments. Phys.lo,phys.mid,phys.hi numbers can be taken right
from the corresponding
reg property. For configuration space
it is easy to get the physical address since phys.lo and phys.mid are always
zero. Phys.hi is just the config space address.
We'll use onboard ethernet on a Sun Ultra-30 UPA/PCI
system as an example for getting the physical address of configuration
space registers.
ok "
/pci@1f,4000/network@1,1" begin-select-dev
ok pwd
/pci@1f,4000/network@1,1
ok .properties
.
.
reg (Config Space ---->)
00000900 00000000 00000000 00000000 00000000
(32bit memory space ---->) 02000910 00000000 00000000 00000000 00007020
.
.
.
.
ok 0 0 900 100 " map-in" $call-parent
constant my-cfg-vaddr
ok my-cfg-vaddr .
fff80900
ok my-cfg-vaddr map?
VA:fff80900
G:0 W:1 P:1 E:1 CV:0 CP:0 L:0
Soft1:1 PA[40:13]:ff00800 PA:1fe01000000
Diag:0 Soft2:0 IE:0 NFO:0 Size:0
V:1
PA:1fe01000900
Hence the physical address for the base of the
configuration registers is 1fe.0100.0900 for this device. For
plug in PCI devices, the physical address of registers may vary if the
device is plugged into a different slot or if other devices are present.
Similarly, using the reg entry for memory or I/O space, one can
find the physical addresses for those spaces.
To map and examine the contents of the expansion
ROM of the above PCI device, use the following:
ok 0 0 900 200.0030 or 1.0000
" map-in" $call-parent constant my-rom-vaddr
ok my-rom-vaddr map?
VA:fef7a000
G:0 W:1 P:1 E:1 CV:0 CP:0 L:0 Soft1:1 PA[40:13]:ff80800 PA:1ff01000000
Diag:0 Soft2:0 IE:0 NFO:0 Size:0 V:1
PA:1ff01000000
19. I am still testing
my FCode, but when I use "select-dev" on my device I get errors. How do
I debug my FCode/device in this case?
Add a dummy "open" method to your device node's
FCode if you want to be able to select (open) the device, so you can map
the device in at the ok prompt and look at the device registers etc.:
ok cd /pci..../<device-node>
ok : open
true ; ( this may give a message about "open" not being unique)
ok device-end
Now you can use "select-dev" to open/select your
device. Then use " map-in" $call-parent to map in the device registers
etc, and examine them. (Remember that endianness may not be what you think,
so look at how the device is mapped (with "map?"), and how rl@, etc, are
defined.)
20. How can I control
probing of pci slots on my Sun Ultra-30 UPA/PCI system?
On Sun Ultra-30 UPA/PCI system, there are NVRAM
variables which indicate to CPU PROM which slots to probe and in
what order during normal system initialization. On Sun Ultra-30 UPA/PCI
system they are: pcia-probe-list and pcib-probe-list.
The default value for pcia-probe-list is 1,2 and
the default value for pcib-probe-list is 5,4,3,2 .
If you don't want slot 4 on pcib probed during
normal initialization (which occurs after a reset), change pcib-probe-list
as follows:
ok
setenv pcib-probe-list 5,3,2
Then later, after a reset, if you wanted to probe
slot 4 on pcib manually, you could run the following command:
ok 4 probe-pci-slot /pci@1f,4000
Note that not all CPU PROMs have the above command.
Also, in future PROMs, the behavior of the above command may change, including
complete disappearance of the command.
21. What should I keep
in mind when using 3.x tokenizer and 3.x CPU PROMs?
Here are some points to be aware of while using
3.x tokenizer;
While testing FCode under 3.x versions of CPU
OpenBoot PROMs, make sure that you have OpenBoot version 3.1 or later PROMs.
pre 3.1 PROMs will need the following nvram patch:
ok nvedit
0: : nl-move ( src dst len -- ) rot n->l rot n->l rot n->l
(move) ;
1: ['] nl-move is move
2: ['] l>>a 2 la+ dup
l@ h# 1000 invert and swap l!
3: ['] lrshift 2 la+ dup l@
h# 1000 invert and swap l!
4: ^C
ok nvstore
ok setenv use-nvramrc? true
ok reset-all
Another thing to note is:
(While using 2.x or 3.x tokenizer),
literals / numbers that have bit 31 set to 1 will have the bit (1) extended
all the way through bit 63 when
running on systems with 3.x CPU
PROMs. For example,
8000.0000
constant xxx will be really giving a value as: ffff.ffff.8000.0000
(on 3.x CPU PROMs)
It is best that when such words/constants are
used, especially in address manipulation, that your code clips them
to a 32 bit value as:
Get a real 8000.0000 by:
ff ff ff ff bljoin constant x-num
: clip-num ( n -- l ) x-num and ;
8000.0000 clip-num constant xxx
or
use
" xxx clip-num " wherever " xxx " is being used.
22. What is the required
set of properties for the expansion ROM?
Strictly speaking, nothing is "required".
But the practical minimum is name and reg. Several
other PCI Config reg properties will be created by the OBP during probe
time.
23. When the configuration
software probes my PCI slot, does it read my PROM 32-bits at a time, or
one byte at a time?
The configuration space is read 32 bits at a time,
but it is the option of the target to read it as 8-bit chunks. OBP reads
the PCI ROM one byte-at-a-time on byte offsets. This is done partly to
avoid any endianness issue. Note that on SBus, it was possible for
the ROM to be wired for byte, halfword or word (32 bit) access (i.e. one
valid byte per 32 bits).
The card's FCode would use the start0, start1,
start2 or start4 FCode to signal to the host OBP how to address successive
bytes when interpreting FCode. On PCI, the Expansion ROM is expected
to be wired for byte access. The PCI ROM Header is accessed that way.
Thus, when you get to the FCode image, the OBP pulls in the FCode one byte
at a time, on byte boundaries.
24: Beside the header,
what is the minimum amount of FCode which is required?
Currently, all
I have is this:
tokenizer[
h#
108e h# 1001 h# 020000 pci-header ( vendor-id device-id
class-code -- )
h#
c000
pci-vpd-offset ( w -- )
0
pci-code-revision ( w -- )
]tokenizer
FCode-version3
\ My FCode starts from here.
hex
"
test,pci" xdrstring " name" attribute
end0
The PCI ROM Header resides in locations 0 - 19
hex.
Usually, the first image will be aligned to start
at 1c. The PCI data structure (starting at 1c) then takes up next
17 hex locations. (See PCI System Architecture - Pages 366-367 - Third
Edition - Feb printing)
In the code above, code fragment tokenizer[
..... ]tokenizer produces PCI ROM Header and PCI data structure.
Note that "[" and "]" above are required.
Finally, the FCode image starts. Technically,
the minimum FCode image is 9 bytes:
- FCode
Header (8 bytes including start code, checksum (2 bytes), and
image length (4 bytes).
-
FCode Body (can be length 0)
-
End byte-code (1 byte)
Usually, the minimum you will want is a
body program including the
name and reg properties.
Without the reg entry, the OBP will not assign any base address
regs nor will you get a unit address. Without a name, you will find
it more difficult to reference the node in the device tree.
So, the minimum
FCode might be:
FCode-version3
" test,pci" encode-string " name" property
my-address my-space encode-phys
0 encode-int encode+
0 encode-int encode+ " reg" property
end0
With comments:
FCode-version3 \ My FCode
starts from here.
" test,pci" encode-string " name" property
my-address
( phys.lo phys.mid )
my-space
( phys.lo phys.mid phys.hi )
encode-phys
( adr len )
0
( adr len size.hi )
encode-int encode+ ( adr' len' )
0
( adr' len' size.lo )
encode-int encode+ ( adr' len' )
" reg" property
end0
25. In the past I've used
tokenizer version 2.3 for SBus FCODE development - is it OK to use that
same tokenizer for PCI FCode PROM development, or do I need new tokenizer?
Tokenizer Version 2.3 will work, but if you need
to write 1275 source compatible FCode for PCI, you'll need version 3.1
or later. Also, for pre 3.1 versions of tokenizer, you'll need to
use some utility to add the PCI header. Use the Tokenizer (version
3.1) from this site's Tools page. See /opt/SUNWddk/ddk_3.1/tokenizer/README.
26. I am writing FCode
for a bootable device. It appears to me that there are 3 kinds of
software that come into play during a boot: kernel, FCode and OS-driver.
Can someone briefly explain what each does and the order in which they
kick in?
At power-on the CPU PROM begins execution. It
probes all on-board devices and plug-in cards and thus interprets
the code in all FCode PROMs. During the FCode probing process, some
FCode PROMs will execute some commands like resetting the device, and so
on. But generally, FCode PROMs will generate device properties for their
respective devices.
When the actual boot begins, the CPU PROM boots
over the specified boot-device (and uses the device's FCode boot driver).
The CPU PROM loads the bootblk (or
inetboot for network booting) and passes control
to the bootblk code. The bootblk code in turn loads kernel modules and
passes control to the kernel. Somewhere afterwards the kernel starts using
the OS-device driver. This then is the scenario for a normal Solaris boot.
In summary, the order is: CPU PROM, FCode PROM,
bootblk, kernel and then the OS-driver.
27. What conventions should
I follow in naming my devices using FCode proms?
Refer to "Generic Naming Recommended Practices"
available on the webpage of the Open Firmware (1275) Working group for
details.
Open Firmware (1275) Homepage is
at http://playground.sun.com/1275/
Look under http://playground.sun.com/1275/practice/#gnames
based on working group proposal #251.
28. Where can I find additional
documentation?
For writing PCI FCode, you need to have IEEE
1275/PCI bindings. The Open Firmware (1275) Homepage is at http://playground.sun.com/1275/
. The IEEE 1275/PCI bindings are at http://playground.sun.com/1275/bindings/pci/
.
"Writing FCode 3.x Programs"
manual is available on the Publications page of this site.
IEEE 1275 Standard for Boot
Firmware is available from IEEE.
Phone: 1-800-701-4333
"PCI Local Bus specification rev 2.2"
and other specifications are available from the
PCI
Special Interest Group.
In the OpenBoot
Collection
OpenBoot 3.x Command Reference
manual
OpenBoot 3.x Quick Reference
OpenBoot 2.x Command Reference
manual
OpenBoot 2.x Quick Reference
Writing FCode 3.x Programs
Back to Top
|