Fixes for Tyan s2880

YhLu YhLu at tyan.com
Fri Jul 25 14:48:00 CEST 2003


Ron,

It seems that you roll back to the tree, because of Stefan's complain.

I want to give detail description on the coherent_ht.c and raminit.c
1. coherent_ht.c  add two function: notify_bsp_ap_is_stopped. And
wait_ap_stop.
2. raminit.c change csbase counting methods.

Any way you at least can put files on s2880 for me.

Also please send the Config.lb to me and I would to test the new config
tool.

Thanks.

Regards

Yinghai Lu
-----邮件原件-----
发件人: ron minnich [mailto:rminnich at lanl.gov] 
发送时间: 2003年7月24日 21:31
收件人: linuxbios at clustermatic.org
主题: Fixes for Tyan s2880

Yh Lu needed to add a mainboard-specific initialization code for the Tyan
s2880 board, and needed it called at a special place in hardwaremain(). In
V1, we would use defines and other such trickery to get this capability.
We're trying to avoid that in V2.

This problem turns out to be a perfect use for the static device
initialization support.

First, we apply patches that are tyan-only or are bug fixes to these files:

src/include/device/pci_ids.h
src/mainboard/tyan/s2880/auto.c
src/mainboard/tyan/s2880/Config
src/mainboard/tyan/s2880/debug.c
src/mainboard/tyan/s2880/failover.c
src/mainboard/tyan/s2880/static_devices.c
src/mainboard/tyan/s2880/tyan-fallback.config
src/mainboard/tyan/s2880/tyan-normal.config
src/mainboard/tyan/s2880/VERSION
src/mainboard/tyan/VERSION
src/northbridge/amd/amdk8/coherent_ht.c
src/northbridge/amd/amdk8/raminit.c
src/southbridge/amd/amd8111/Config
src/southbridge/amd/amd8111/Config.lb
src/southbridge/amd/amd8131/amd8131_bridge.c
targets/tyan/s2880/Config.lb

Now, we need to ensure that YhLu's "special code" is called for his
mainboard. 

As it happens, the mainboard is also a "chip" in the new scheme. The
config tool builds a tree based on this structure, from 
src/include/device/chip.h: 

struct chip {
  struct chip_control *control; /* for this device */
  char *path; /* can be 0, in which case the default is taken */
  char *configuration; /* can be 0. */
  int irq;
  struct chip *next, *children;
  /* there is one of these for each INSTANCE of a chip */
  void *chip_info; /* the dreaded "void *" */
};

The tree for the s2880 looks like this:

=====
#include <device/chip.h>
struct chip static_root, static_dev1, static_dev2, static_dev3, static_dev4,
sta
tic_dev5, static_dev6, static_dev7, static_dev8, static_dev9, static_dev10;
#include "/home/rminnich/src/bios/freebios2/src/mainboard/tyan/s2880/chip.h"

struct chip static_root = {
/* mainboard /home/rminnich/src/bios/freebios2/src/mainboard/tyan/s2880 */
  .children = &static_dev9,
};
struct chip static_dev9 = {
/* cpu /home/rminnich/src/bios/freebios2/src/cpu/k8 */
  .next = &static_dev8,
};

.
.
.

======

(the rest is removed for clearness)

Note that there are even "chips" for CPUs: it is possible to handle
CPU fixup in this system. 

Each entry in the above structures defines a static device. 

Please recall that static devices consist of a generic structure and then 
special-purpose (device specific) structures. 

The generic structure is this:
/* there is one of these for each TYPE of chip */
struct chip_control {
  void (*enable)(struct chip *, enum chip_pass);
  char *path;     /* the default path. Can be overridden
                   * by commands in config
                   */
  // This is the print name for debugging
  char *name;
};

Device-specific classes are defined by the attributes of the device, and
hence vary for each device. In the V1 days, we tried to have one 
generic structure, but that did not even work for the limited case
of superio's, so for V2 we are making the structure unique to 
each device. 

We have to define one device structure for the Tyan s2880. 
The structure has to be defined in an include file that is in the 
directory that contains the code for the device. So, for the 
tyan s2880 mainboard, we need to have a definition file in 
src/mainboard/tyan/s2880. We'll call it src/mainboard/tyan/s2880/chip.h. 

In this case, it is rather simple:

struct mainboard_tyan_s2880_config {
        int fixup_scsi;
};

This is the only thing we're controlling at present. Note that the name of 
the struct is a 'flattened' version of the device name.

We need to tell the config tool where to find the file containing the 
structure, and how to initialize the struct in the file.
Add these lines to src/tyan/s2880/Config.lb. They will define the name of
the 
file to use, and the code to initialize the static device. 

config chip.h 
register "fixup_scsi" = "1"

We need to create the structure that defines the generic structure for the 
mainboard, so linuxbios can hook into it. So add these lines to the end
of src/mainboard/tyan/s2880/mainboard.c:

struct chip_control mainboard_tyan_s2880_control = {
                enable: enable,
                name:   "Tyan s2880 mainboard "
};

Then add the enable function (BEFORE the struct chip_control declaration).
Note that it is declared 'static', and has only one entry in the 
switch. 

static void
enable(struct chip *chip, enum chip_pass pass)
{

        struct mainboard_tyan_s2880_config *conf =
                (struct mainboard_tyan_s2880_config *)chip->chip_info;

        switch (pass) {
                default: break;
                case CONF_PASS_PRE_BOOT:
                         if (conf->fixup_scsi)
                                onboard_scsi_fixup();
                        printk_debug("mainboard fixup pass %d done\r\n",
                                        pass);
                        break;
        }

}

That's pretty much it. total changes are 170 lines.
The static device tree (which is generated by the config tool, you 
don't have to write this code) now looks like this:

==========
#include <device/chip.h>
struct chip static_root, static_dev1, static_dev2, static_dev3, static_dev4,
sta
tic_dev5, static_dev6, static_dev7, static_dev8, static_dev9, static_dev10;
#include "/home/rminnich/src/bios/freebios2/src/mainboard/tyan/s2880/chip.h"
extern struct chip_control mainboard_tyan_s2880_control;
struct mainboard_tyan_s2880_config mainboard_tyan_s2880_config_0        = {
  .fixup_scsi = 1,
};

struct chip static_root = {
/* mainboard /home/rminnich/src/bios/freebios2/src/mainboard/tyan/s2880 */
  .children = &static_dev9,
  .control= &mainboard_tyan_s2880_control,
  .chip_info = (void *) &mainboard_tyan_s2880_config_0,
};
struct chip static_dev9 = {
/* cpu /home/rminnich/src/bios/freebios2/src/cpu/k8 */
  .next = &static_dev8,
};
=====

Note that the mainboard now has several new entries, and there
is a new struct for controlling the mainboard, along with an 
initializer. The enable function for the mainboard will be called at several

places in hardwaremain with a different pass #, and since there is 
only one case defined, only one action is taken. 


So to add this capability for this mainbard, we had to:
- define a file containing the device-specific structure which 
  we called chip.h, and placed in src/mainboard/tyan/s2880
- add two lines to src/mainboard/tyan/s2880/Config.lb, which 
  define the file we need (chip.h) and the initialization of 
  the structure. 
- add the "base class" structure to src/mainboard/tyan/s2880/mainboard.c,
  along with the enable function. 

I've built this mainboard and hexdump of the romimage looks pretty good.
Yh Lu, can you please verify this? The config.lb is in
targets/tyan/s2880/Config.lb.  I can send the context diffs if that will
help.

Note that this technique will work for anything that the config tool 
considers a 'device': mainboard, cpu, north and south bridge, superio, 
etc.

Thanks

ron

_______________________________________________
Linuxbios mailing list
Linuxbios at clustermatic.org
http://www.clustermatic.org/mailman/listinfo/linuxbios



More information about the coreboot mailing list