mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-12 14:23:00 +00:00
192 lines
7.2 KiB
Text
192 lines
7.2 KiB
Text
|
The U-Boot Driver Model Project
|
||
|
===============================
|
||
|
I/O system analysis
|
||
|
===================
|
||
|
Marek Vasut <marek.vasut@gmail.com>
|
||
|
2012-02-20
|
||
|
|
||
|
I) Overview
|
||
|
-----------
|
||
|
|
||
|
The console input and output is currently done using the STDIO subsystem in
|
||
|
U-Boot. The design of this subsystem is already flexible enough to be easily
|
||
|
converted to new driver model approach. Minor changes will need to be done
|
||
|
though.
|
||
|
|
||
|
Each device that wants to register with STDIO subsystem has to define struct
|
||
|
stdio_dev, defined in include/stdio_dev.h and containing the following fields:
|
||
|
|
||
|
struct stdio_dev {
|
||
|
int flags; /* Device flags: input/output/system */
|
||
|
int ext; /* Supported extensions */
|
||
|
char name[16]; /* Device name */
|
||
|
|
||
|
/* GENERAL functions */
|
||
|
|
||
|
int (*start) (void); /* To start the device */
|
||
|
int (*stop) (void); /* To stop the device */
|
||
|
|
||
|
/* OUTPUT functions */
|
||
|
|
||
|
void (*putc) (const char c); /* To put a char */
|
||
|
void (*puts) (const char *s); /* To put a string (accelerator) */
|
||
|
|
||
|
/* INPUT functions */
|
||
|
|
||
|
int (*tstc) (void); /* To test if a char is ready... */
|
||
|
int (*getc) (void); /* To get that char */
|
||
|
|
||
|
/* Other functions */
|
||
|
|
||
|
void *priv; /* Private extensions */
|
||
|
struct list_head list;
|
||
|
};
|
||
|
|
||
|
Currently used flags are DEV_FLAGS_INPUT, DEV_FLAGS_OUTPUT and DEV_FLAGS_SYSTEM,
|
||
|
extensions being only one, the DEV_EXT_VIDEO.
|
||
|
|
||
|
The private extensions are now used as a per-device carrier of private data and
|
||
|
finally list allows this structure to be a member of linked list of STDIO
|
||
|
devices.
|
||
|
|
||
|
The STDIN, STDOUT and STDERR routing is handled by environment variables
|
||
|
"stdin", "stdout" and "stderr". By configuring the variable to the name of a
|
||
|
driver, functions of such driver are called to execute that particular
|
||
|
operation.
|
||
|
|
||
|
II) Approach
|
||
|
------------
|
||
|
|
||
|
1) Similarity of serial, video and keyboard drivers
|
||
|
---------------------------------------------------
|
||
|
|
||
|
All of these drivers can be unified under the STDIO subsystem if modified
|
||
|
slightly. The serial drivers basically define both input and output functions
|
||
|
and need function to configure baudrate. The keyboard drivers provide only
|
||
|
input. On the other hand, video drivers provide output, but need to be
|
||
|
configured in certain way. This configuration might be dynamic, therefore the
|
||
|
STDIO has to be modified to provide such flexibility.
|
||
|
|
||
|
2) Unification of serial, video and keyboard drivers
|
||
|
----------------------------------------------------
|
||
|
|
||
|
Every STDIO device would register a structure containing operation it supports
|
||
|
with the STDIO core by calling:
|
||
|
|
||
|
int stdio_device_register(struct instance *i, struct stdio_device_ops *o);
|
||
|
|
||
|
The structure being defined as follows:
|
||
|
|
||
|
struct stdio_device_ops {
|
||
|
void (*putc)(struct instance *i, const char c);
|
||
|
void (*puts)(struct instance *i, const char *s); /* OPTIONAL */
|
||
|
|
||
|
int (*tstc)(struct instance *i);
|
||
|
int (*getc)(struct instance *i);
|
||
|
|
||
|
int (*init)(struct instance *i);
|
||
|
int (*exit)(struct instance *i);
|
||
|
int (*conf)(struct instance *i, enum stdio_config c, const void *data);
|
||
|
};
|
||
|
|
||
|
The "putc()" function will emit a character, the "puts()" function will emit a
|
||
|
string. If both of these are set to NULL, the device is considered STDIN only,
|
||
|
aka input only device.
|
||
|
|
||
|
The "getc()" retrieves a character from a STDIN device, while "tstc()" tests
|
||
|
if there is a character in the buffer of STDIN device. In case these two are
|
||
|
set to NULL, this device is STDOUT / STDERR device.
|
||
|
|
||
|
Setting all "putc()", "puts()", "getc()" and "tstc()" calls to NULL isn't an
|
||
|
error condition, though such device does nothing. By instroducing tests for
|
||
|
these functions being NULL, the "flags" and "ext" fields from original struct
|
||
|
stdio_dev can be eliminated.
|
||
|
|
||
|
The "init()" and "exit()" calls are replacement for "start()" and "exit()"
|
||
|
calls in the old approach. The "priv" part of the old struct stdio_dev will be
|
||
|
replaced by common private data in the driver model and the struct list_head
|
||
|
list will be eliminated by introducing common STDIO core, that tracks all the
|
||
|
STDIO devices.
|
||
|
|
||
|
Lastly, the "conf()" call will allow the user to configure various options of
|
||
|
the driver. The enum stdio_config contains all possible configuration options
|
||
|
available to the STDIO devices, const void *data being the argument to be
|
||
|
configured. Currently, the enum stdio_config will contain at least the
|
||
|
following options:
|
||
|
|
||
|
enum stdio_config {
|
||
|
STDIO_CONFIG_SERIAL_BAUDRATE,
|
||
|
};
|
||
|
|
||
|
3) Transformation of stdio routing
|
||
|
----------------------------------
|
||
|
|
||
|
By allowing multiple instances of drivers, the environment variables "stdin",
|
||
|
"stdout" and "stderr" can no longer be set to the name of the driver.
|
||
|
Therefore the STDIO core, tracking all of the STDIO devices in the system will
|
||
|
need to have a small amount of internal data for each device:
|
||
|
|
||
|
struct stdio_device_node {
|
||
|
struct instance *i;
|
||
|
struct stdio_device_ops *ops;
|
||
|
uint8_t id;
|
||
|
uint8_t flags;
|
||
|
struct list_head list;
|
||
|
}
|
||
|
|
||
|
The "id" is the order of the instance of the same driver. The "flags" variable
|
||
|
allows multiple drivers to be used at the same time and even for different
|
||
|
purpose. The following flags will be defined:
|
||
|
|
||
|
STDIO_FLG_STDIN ..... This device will be used as an input device. All input
|
||
|
from all devices with this flag set will be received
|
||
|
and passed to the upper layers.
|
||
|
STDIO_FLG_STDOUT .... This device will be used as an output device. All
|
||
|
output sent to stdout will be routed to all devices
|
||
|
with this flag set.
|
||
|
STDIO_FLG_STDERR .... This device will be used as an standard error output
|
||
|
device. All output sent to stderr will be routed to
|
||
|
all devices with this flag set.
|
||
|
|
||
|
The "list" member of this structure allows to have a linked list of all
|
||
|
registered STDIO devices.
|
||
|
|
||
|
III) Analysis of in-tree drivers
|
||
|
--------------------------------
|
||
|
|
||
|
For in-depth analysis of serial port drivers, refer to [ UDM-serial.txt ].
|
||
|
For in-depth analysis of keyboard drivers, refer to [ UDM-keyboard.txt ].
|
||
|
For in-depth analysis of video drivers, refer to [ UDM-video.txt ].
|
||
|
|
||
|
1) arch/blackfin/cpu/jtag-console.c
|
||
|
-----------------------------------
|
||
|
This driver is a classic STDIO driver, no problem with conversion is expected.
|
||
|
|
||
|
2) board/mpl/pati/pati.c
|
||
|
------------------------
|
||
|
This driver registers with the STDIO framework, though it uses a lot of ad-hoc
|
||
|
stuff which will need to be sorted out.
|
||
|
|
||
|
3) board/netphone/phone_console.c
|
||
|
---------------------------------
|
||
|
This driver is a classic STDIO driver, no problem with conversion is expected.
|
||
|
|
||
|
4) drivers/net/netconsole.c
|
||
|
---------------------------
|
||
|
This driver is a classic STDIO driver, no problem with conversion is expected.
|
||
|
|
||
|
IV) Other involved files (To be removed)
|
||
|
----------------------------------------
|
||
|
|
||
|
common/cmd_console.c
|
||
|
common/cmd_log.c
|
||
|
common/cmd_terminal.c
|
||
|
common/console.c
|
||
|
common/fdt_support.c
|
||
|
common/iomux.c
|
||
|
common/lcd.c
|
||
|
common/serial.c
|
||
|
common/stdio.c
|
||
|
common/usb_kbd.c
|
||
|
doc/README.iomux
|