Since
@CircuitBored was interested in playing with OF in the S900 to try to get unsupported cards working there, I'm going to put here an expanded version of the commentary I posted in the crash-dead thread on what I think the Sonnet patch is up to, and (now) what I did to patch the patch.
Note, please, that I am not an OF guru, nor am I particularly good at Forth, so this is to an extent the opinions of a moderately educated onlooker, rather than an expert in the field.
Let's start. To begin with, this isn't really a "patch", it's an nvramrc, which is a script that's run early in the boot sequence. You can think of it as the Open Firmware equivalent of rc.local or AUTOEXEC.BAT. In this script you can do anything you can do at the OF command line. Now, this patch exists to work around PCI enumeration behind bridges not working; and the way it does this is to add "fake" device nodes to the tree that mirror what PCI enumeration would find. So, we can hack this by changing what card it is looking for, and what the fake devices it adds are.
Here's some code.
Code:
probe-all install-console banner
: config-l! " config-l!" $call-parent ;
: config-l@ " config-l@" $call-parent ;
We start off with some boilerplate. The colon defines a procedure, and the procedure is terminated with a semicolon. confg-l! and config-l@ are words which write and read, respectively, from the PCI configuration. I assume the shims we're putting on these here are so that our fake devices have them defined, but I'm not sure. (Not being sure will be a recurring theme).
Code:
: check-node
my-space " config-l@" $call-parent dup d# 16 >> swap h# 0000FFFF and
my-space d# 8 + " config-l@" $call-parent d# 8 >> h# 60400 =
swap h# 1668 = and swap h# 100 = and ;
check-node is the first routine in the patch proper. It checks whether the current device is one we care about. It does this by grabbing the vendor and device ID numbers out of the configuration space for that device (my-space returns the configuration address for the device; config-l@, as noted above, reads from it) and checking them. The two numeric constants in the last line are the ones you want to change here. For the "new" Tango2.0 and Kalea patches, I changed these to 3388 and 21, respectively.
Code:
: my-make-properties
make-properties 0 alloc-here 0 " pci" encode-cat
my-space h# 2c + config-l@ -rot 2 pick h# FFFF and (u.) encode-cat
" ," encode-cat rot d# 16 >> (u.) encode-cat
2dup swap 3 + swap bounds
do i c@ h# 40 > if i c@ h# 20 + i c! then loop
device-name 0 0 encode-2ints " power-consumption" property
0 0 my-space encode-3ints
0 0 encode-2ints encode+
0 0 my-space 2 d# 24 << or h# 10 + encode-3ints
1000 0 encode-2ints
encode+ encode+ " reg" property ;
my-make-properties sets up the properties for one of our fake PCI devices, especially its "reg" property. It does this based on its position in the PCI configuration space (note our friend my-space turning up again). I do not know enough deep PCI magic to understand totally what this is doing; fortunately, for the patches I've had to do so far, we don't need to poke it. So let's not.
Now we get onto the meat of the patch: make-nodes. make-nodes actually does three things, only one of which is making new nodes. First
Code:
: make-nodes
" assigned-addresses" delete-property
my-space dup 18 + 10100 swap config-l!
4 + dup config-l@ h# FFFFFFF4 and 2 or swap config-l!
This first bit of code sets up the PCI bridge chip to have the right options. You can leave it alone.
Code:
new-device 0 0 " 0,0" set-args
my-make-properties 0 100000 20 claim-real
swap drop dup dup 100000 " map-range" $call-parent
dup my-space h# 10 + config-l!
dup 0 my-space h# 82 d# 24 << or h# 10 + encode-3ints
1000 0 encode-2ints encode+ " assigned-addresses" property
finish-device
new-device 0 0 " 1,0" set-args
my-make-properties dup 1000 + my-space h# 10 + config-l!
dup 1000 + 0 my-space h# 82 d# 24 << or h# 10 + encode-3ints
1000 0 encode-2ints encode+ " assigned-addresses" property
finish-device
These two bits set up the two device nodes, one for USB and one for Firewire. The things to note here are the "0,0" and "1,0" strings. These need to be adjusted to fit what the card expects. I'll post another comment below this one with how to find out what the card expects. You can add more devices here, but some challenges start emerging.
Code:
dup dup h# 10 >> or my-space h# 20 + config-l!
my-space h# 3c + dup config-l@ h# 800000 or swap config-l!
" ranges" delete-property
dup 0 h# 82000000 encode-3ints
rot 0 h# 82000000 encode-3ints
h# 100000 0 encode-2ints encode+ encode+ " ranges" property
my-space h# 18 + config-l@ dup 8 >> h# ff and swap d# 16 >> h# ff and
encode-2ints " bus-range" property ;
This last chunk of make-nodes sets up some more global properties of the bridge that one doesn't need to poke to patch the patches.
We're on the final stretch now: the remaining code glues the above together.
Code:
: x
['] select-dev
catch if 2drop else
check-node if make-nodes then then ;
" pci1/@d" x " pci1/@e" x
This defines a procedure "x" that selects a device, checks whether it exists and is the right one, and if so, it runs make-nodes on it. This procedure is then invoked twice for the PCI card at D and the PCI card at E.
Ta daa.