git-svn-id: svn://svn.coreboot.org/coreboot/trunk@846 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
		
			
				
	
	
		
			267 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			TeX
		
	
	
	
	
	
			
		
		
	
	
			267 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			TeX
		
	
	
	
	
	
		RFC for the chip specification architecture
 | 
						|
 | 
						|
\begin{abstract}
 | 
						|
At the end of this document is the original message that motivated the
 | 
						|
change. 
 | 
						|
\end{abstract}
 | 
						|
 | 
						|
\section{Scope}
 | 
						|
This document defines how LinuxBIOS programmers can specify chips that
 | 
						|
are used, specified, and initalized. The current scope is for superio 
 | 
						|
chips, but the architecture should allow for specification of other chips such 
 | 
						|
as southbridges. Multiple chips of same or different type are supported. 
 | 
						|
 | 
						|
\section{Goals}
 | 
						|
The goals of the new chip architecture are these: 
 | 
						|
\begin{itemize}
 | 
						|
\item seperate implementation details from specification in the Config file
 | 
						|
(translation: no more C code in Config files)
 | 
						|
\item make the specification easier for people to use and understand
 | 
						|
\item remove private details of a given chip to the chip file as much
 | 
						|
as possible
 | 
						|
\item allow unique register-set-specifiers for each chip
 | 
						|
\end{itemize}
 | 
						|
 | 
						|
\section{Specification in the Config file}
 | 
						|
The specification looks like this:
 | 
						|
\begin{verbatim}
 | 
						|
chip <name> [path=<path>] ["<configuration>"]
 | 
						|
\end{verbatim}
 | 
						|
The name is in the standard LinuxBIOS form of type/vendor/name, e.g. 
 | 
						|
"southbridge/intel/piix4e" or "superio/ITE/it8671f". The class of the 
 | 
						|
chip is derived from the first pathname component of the name, and the chip 
 | 
						|
configuration is derived from the following components. 
 | 
						|
 | 
						|
The path defines the access mechanism to the chip. 
 | 
						|
It is optional. If present, it overrides the default path to the chip. 
 | 
						|
 | 
						|
The configuration defines chip-specific configuration details, and is also
 | 
						|
optional. Note that an empty configuration will leave the chip with 
 | 
						|
no enabled resources. This may be desirable in some cases. 
 | 
						|
 | 
						|
\section{Results of specifying a chip}
 | 
						|
 | 
						|
When one or more chips are specified, the data about the chips
 | 
						|
is saved until the entire file is parsed. At this point, the config tool
 | 
						|
creates a file in the build directory called chip.c This file contains
 | 
						|
a common struct containing information about 
 | 
						|
each individual chip and an array of pointers to these structures. 
 | 
						|
 | 
						|
For each chip, there are two structures. The structures contain control 
 | 
						|
information for the chip, and register initialization information. The 
 | 
						|
names of the structures are derived by ``flattening'' the chip name, 
 | 
						|
as in the current linuxbios. For example, superio/ITE/xyz uses 
 | 
						|
two structs, one called superio_ITE_xyz_control and one called
 | 
						|
superio_ITE_xyz_init. The control struct is initialized from the 
 | 
						|
chip name and path information, and has a pointer to the 
 | 
						|
config struct. The config struct is initialized from the quote string
 | 
						|
 | 
						|
\begin{verbatim}
 | 
						|
From rminnich@lanl.gov Fri May 16 10:34:13 2003
 | 
						|
Date: Tue, 13 May 2003 08:11:46 -0600 (MDT)
 | 
						|
From: ron minnich <rminnich@lanl.gov>
 | 
						|
To: linuxbios@clustermatic.org
 | 
						|
Subject: RFC:new superio proposal
 | 
						|
 | 
						|
Abstract:
 | 
						|
	The superio architecture for linuxbios has worked for the last 2 
 | 
						|
years but is being stretched to the limit by the changes in superio chips. 
 | 
						|
The architecture depended on superio resources being relatively constant 
 | 
						|
between chips, but this assumption no longer holds. In this document we 
 | 
						|
propose several alternatives and solicit comments. 
 | 
						|
 | 
						|
Overview:
 | 
						|
The superio architecture in linuxbios was developed over time, and 
 | 
						|
modified as circumstances required. In the beginning it was relatively 
 | 
						|
simple and assumed only one superio per mainboard. The latest version 
 | 
						|
allows an arbitrary number of superios per mainboard, and allows complete
 | 
						|
specification of the superio base I/O address along with the specification
 | 
						|
of reasonable default valures for both the base I/O address and the 
 | 
						|
superio parameters such as serial enable, baud rate, and so on. 
 | 
						|
 | 
						|
Specification of superio control parameters is done by a configuration 
 | 
						|
line such as:
 | 
						|
 | 
						|
nsuperio sis/950 com1={1} floppy=1  lpt=1
 | 
						|
 | 
						|
This fragment sets the superio type to sis/950; sets com1, floppy, and lpt 
 | 
						|
to enabled; and leaves the defaults to com1 (baud rate, etc.) to the 
 | 
						|
default values. 
 | 
						|
 | 
						|
While it is not obvious, these configuration parameters are fragments of a
 | 
						|
C initializer. The initializers are used to build a statically initialized
 | 
						|
structure of this type:
 | 
						|
 | 
						|
struct superio {
 | 
						|
        struct superio_control *super; // the ops for the device.
 | 
						|
        unsigned int port; // if non-zero, overrides the default port
 | 
						|
        // com ports. This is not done as an array (yet).
 | 
						|
        // We think it's easier to set up from python if it is not an 
 | 
						|
	// array.
 | 
						|
        struct com_ports com1, com2, com3, com4;
 | 
						|
        // DMA, if it exists.
 | 
						|
        struct lpt_ports lpt1, lpt2;
 | 
						|
        /* flags for each device type. Unsigned int. */
 | 
						|
        // low order bit ALWAYS means enable. Next bit means to enable
 | 
						|
        // LPT is in transition, so we leave this here for the moment.
 | 
						|
        // The winbond chips really stretched the way this works.
 | 
						|
        // so many functions!
 | 
						|
        unsigned int ide, floppy, lpt;
 | 
						|
        unsigned int keyboard, cir, game;
 | 
						|
        unsigned int gpio1, gpio2, gpio3;
 | 
						|
        unsigned int acpi,hwmonitor;
 | 
						|
};
 | 
						|
 | 
						|
These structures are, in turn, created and statically initialized by a
 | 
						|
config-tool-generated structure that defines all the superios. This file
 | 
						|
is called nsuperio.c, is created for each mainboard you build, only 
 | 
						|
appears in the build directory, and looks like this:
 | 
						|
 | 
						|
===
 | 
						|
extern struct superio_control superio_winbond_w83627hf_control; 
 | 
						|
 | 
						|
struct superio superio_winbond_w83627hf= { 
 | 
						|
  &superio_winbond_w83627hf_control, 
 | 
						|
  .com1={1}, .com2={1}, .floppy=1, .lpt=1, .keyboard=1, .hwmonitor=1};
 | 
						|
 | 
						|
struct superio *all_superio[] = {&superio_winbond_w83627hf,
 | 
						|
};
 | 
						|
 | 
						|
unsigned long nsuperio = 1;
 | 
						|
===
 | 
						|
 | 
						|
This example shows a board with one superio (nsuperio). The superio
 | 
						|
consists of a winbond w83627hf, with com1, com2, floppy, lpt, keyboard, 
 | 
						|
and hwmonitor enabled. Note that this structure also allows for 
 | 
						|
over-riding the default superio base, although that capability is rarely 
 | 
						|
used. 
 | 
						|
 | 
						|
The control structure is used to define how to access the superio for 
 | 
						|
purposes of control. It looks like this:
 | 
						|
===
 | 
						|
struct superio_control {
 | 
						|
  void (*pre_pci_init)(struct superio *s);
 | 
						|
  void (*init)(struct superio *s);
 | 
						|
  void (*finishup)(struct superio *s);
 | 
						|
  unsigned int defaultport;     /* the defaultport. Can be overridden
 | 
						|
                                 * by commands in config
 | 
						|
                                 */
 | 
						|
  // This is the print name for debugging
 | 
						|
  char *name;
 | 
						|
};
 | 
						|
===
 | 
						|
 | 
						|
There are three methods for stages of hardwaremain. First is pre_pci_init 
 | 
						|
(for chips like the acer southbridge that require you to enable some 
 | 
						|
resources BEFORE pci scan); init, called during the 'middle' phase of 
 | 
						|
hardwaremain; and finishup, called before the payload is loaded. 
 | 
						|
 | 
						|
This approach was inspired by and borrows heavily on the Plan 9 kernel 
 | 
						|
configuration tools. 
 | 
						|
 | 
						|
The problem:
 | 
						|
 | 
						|
When the first version of the superio structure came out it was much
 | 
						|
smaller. It has grown and in the limit this structure is the union of all
 | 
						|
possibly superio chips. Obviously, in the long term, this is not
 | 
						|
practical: we can not anticipate all possible superio chips for all time.
 | 
						|
 | 
						|
The common PC BIOS solution to this type of problem is to continue with 
 | 
						|
binary structures but add version numbers to them, so that all code that 
 | 
						|
uses a given structure has to check the version number. Personally, I find 
 | 
						|
this grotesque and would rather not work this way. 
 | 
						|
 | 
						|
Using textual strings for configuration is something I find far more 
 | 
						|
attractive. Plan 9 has shown that this approach has no real limits and 
 | 
						|
suffices for configuration tasks. The Linux kernel does more limited use 
 | 
						|
of strings for configuration, but still depends on them. Strings are 
 | 
						|
easier to read and work with than binary structures, and more important, a 
 | 
						|
lot easier to deal with when things start going wrong. 
 | 
						|
 | 
						|
The proposed solution:
 | 
						|
 | 
						|
What follows are three possible ideas for specifying superio resources and 
 | 
						|
their settings. 
 | 
						|
 | 
						|
A common part of the new idea is to eliminate the common superio
 | 
						|
structure, due to the many variations in chips, and make it invisible
 | 
						|
outside a given superio source file -- the superio structure is now
 | 
						|
private to a given superio. Thus, sis/950/superio.c would contain its own
 | 
						|
superio structure definitions, and also might contain more than once
 | 
						|
instance of these structures (consider a board with 2 sis 950 chips).
 | 
						|
 | 
						|
The control structure would change as follows:
 | 
						|
struct superio_control {
 | 
						|
  int (*create)(struct superio *s);
 | 
						|
  void (*pre_pci_init)(struct superio *s);
 | 
						|
  void (*init)(struct superio *s);
 | 
						|
  void (*finishup)(struct superio *s);
 | 
						|
  unsigned int defaultport;     /* the defaultport. Can be overridden
 | 
						|
                                 * by commands in config
 | 
						|
                                 */
 | 
						|
  // This is the print name for debugging
 | 
						|
  char *name;
 | 
						|
};
 | 
						|
 | 
						|
I.e. we add a new function for creating the superio. 
 | 
						|
 | 
						|
Communication of superio settings from linuxbios to the superio would be 
 | 
						|
via textual strings. The superio structure becomes this:
 | 
						|
 | 
						|
struct superio {
 | 
						|
        struct superio_control *super; // the ops for the device.
 | 
						|
        unsigned int port; // if non-zero, overrides the default port
 | 
						|
	struct configuration *config;
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
So now the question becomes, what is the configuration structure? 
 | 
						|
There are several choices. The simplest, from my point of view, are
 | 
						|
keyword-value pairs:
 | 
						|
struct configuration {
 | 
						|
	const char *keyword;
 | 
						|
	const char *value;
 | 
						|
};
 | 
						|
 | 
						|
These get filled in by the config tool as before. The linuxbios libary can 
 | 
						|
then provide a generic parsing function for the superios to use. 
 | 
						|
 | 
						|
The remaining question is how should the superio command look in 
 | 
						|
freebios2? 
 | 
						|
 | 
						|
superio sis/950 "com1=115200,8n1 lpt=1 com2=9600"
 | 
						|
 | 
						|
or
 | 
						|
 | 
						|
superio sis/950 "com1baud=115200 lpt=1 com1chars=8n1"
 | 
						|
 | 
						|
or
 | 
						|
 | 
						|
superio sis/950 ((com1 115200 8n1) (lpt 1))
 | 
						|
 | 
						|
So,  my questions:
 | 
						|
 | 
						|
1. Does this new scheme look workable. If not, what needs to change?
 | 
						|
2. What should the 'struct configuration' be? does keyword/value work? 
 | 
						|
3. what should the superio command look like? 
 | 
						|
 | 
						|
Comments welcome.
 | 
						|
 | 
						|
I'd like to adopt this "RFC" approach for freebios2 as much as we can.  
 | 
						|
There was a lot of give-and-take in the early days of linuxbios about
 | 
						|
structure and it proved useful. There's a lot that will start happening in
 | 
						|
freebios2 now, and we need to try to make sure it will work for everyone.
 | 
						|
 | 
						|
Those of you who are doing mainboards, please look at freebios2 and see
 | 
						|
how it looks for you. There's a lot of good work that has been done (not
 | 
						|
by me so far, thanks Eric and Stefan), and more that needs to be done. 
 | 
						|
Consider trying out romcc as an "assembly code killer". See how it fits 
 | 
						|
together and if you can work with it or need changes. Bring comments back 
 | 
						|
to this list. 
 | 
						|
 | 
						|
thanks
 | 
						|
 | 
						|
ron
 | 
						|
 | 
						|
\end{verbatim}
 |