| 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 |