Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 1 | The U-Boot Driver Model Project |
| 2 | =============================== |
| 3 | I/O system analysis |
| 4 | =================== |
| 5 | Marek Vasut <marek.vasut@gmail.com> |
| 6 | 2012-02-20 |
| 7 | |
| 8 | I) Overview |
| 9 | ----------- |
| 10 | |
| 11 | The console input and output is currently done using the STDIO subsystem in |
| 12 | U-Boot. The design of this subsystem is already flexible enough to be easily |
| 13 | converted to new driver model approach. Minor changes will need to be done |
| 14 | though. |
| 15 | |
| 16 | Each device that wants to register with STDIO subsystem has to define struct |
| 17 | stdio_dev, defined in include/stdio_dev.h and containing the following fields: |
| 18 | |
| 19 | struct stdio_dev { |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 20 | int flags; /* Device flags: input/output/system */ |
| 21 | int ext; /* Supported extensions */ |
| 22 | char name[16]; /* Device name */ |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 23 | |
| 24 | /* GENERAL functions */ |
| 25 | |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 26 | int (*start) (void); /* To start the device */ |
| 27 | int (*stop) (void); /* To stop the device */ |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 28 | |
| 29 | /* OUTPUT functions */ |
| 30 | |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 31 | void (*putc) (const char c); /* To put a char */ |
| 32 | void (*puts) (const char *s); /* To put a string (accelerator) */ |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 33 | |
| 34 | /* INPUT functions */ |
| 35 | |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 36 | int (*tstc) (void); /* To test if a char is ready... */ |
| 37 | int (*getc) (void); /* To get that char */ |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 38 | |
| 39 | /* Other functions */ |
| 40 | |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 41 | void *priv; /* Private extensions */ |
| 42 | struct list_head list; |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 43 | }; |
| 44 | |
| 45 | Currently used flags are DEV_FLAGS_INPUT, DEV_FLAGS_OUTPUT and DEV_FLAGS_SYSTEM, |
| 46 | extensions being only one, the DEV_EXT_VIDEO. |
| 47 | |
| 48 | The private extensions are now used as a per-device carrier of private data and |
| 49 | finally list allows this structure to be a member of linked list of STDIO |
| 50 | devices. |
| 51 | |
| 52 | The STDIN, STDOUT and STDERR routing is handled by environment variables |
| 53 | "stdin", "stdout" and "stderr". By configuring the variable to the name of a |
| 54 | driver, functions of such driver are called to execute that particular |
| 55 | operation. |
| 56 | |
| 57 | II) Approach |
| 58 | ------------ |
| 59 | |
| 60 | 1) Similarity of serial, video and keyboard drivers |
| 61 | --------------------------------------------------- |
| 62 | |
| 63 | All of these drivers can be unified under the STDIO subsystem if modified |
| 64 | slightly. The serial drivers basically define both input and output functions |
| 65 | and need function to configure baudrate. The keyboard drivers provide only |
| 66 | input. On the other hand, video drivers provide output, but need to be |
| 67 | configured in certain way. This configuration might be dynamic, therefore the |
| 68 | STDIO has to be modified to provide such flexibility. |
| 69 | |
| 70 | 2) Unification of serial, video and keyboard drivers |
| 71 | ---------------------------------------------------- |
| 72 | |
| 73 | Every STDIO device would register a structure containing operation it supports |
| 74 | with the STDIO core by calling: |
| 75 | |
| 76 | int stdio_device_register(struct instance *i, struct stdio_device_ops *o); |
| 77 | |
| 78 | The structure being defined as follows: |
| 79 | |
| 80 | struct stdio_device_ops { |
| 81 | void (*putc)(struct instance *i, const char c); |
| 82 | void (*puts)(struct instance *i, const char *s); /* OPTIONAL */ |
| 83 | |
| 84 | int (*tstc)(struct instance *i); |
| 85 | int (*getc)(struct instance *i); |
| 86 | |
| 87 | int (*init)(struct instance *i); |
| 88 | int (*exit)(struct instance *i); |
| 89 | int (*conf)(struct instance *i, enum stdio_config c, const void *data); |
| 90 | }; |
| 91 | |
| 92 | The "putc()" function will emit a character, the "puts()" function will emit a |
| 93 | string. If both of these are set to NULL, the device is considered STDIN only, |
| 94 | aka input only device. |
| 95 | |
| 96 | The "getc()" retrieves a character from a STDIN device, while "tstc()" tests |
| 97 | if there is a character in the buffer of STDIN device. In case these two are |
| 98 | set to NULL, this device is STDOUT / STDERR device. |
| 99 | |
| 100 | Setting all "putc()", "puts()", "getc()" and "tstc()" calls to NULL isn't an |
| 101 | error condition, though such device does nothing. By instroducing tests for |
| 102 | these functions being NULL, the "flags" and "ext" fields from original struct |
| 103 | stdio_dev can be eliminated. |
| 104 | |
| 105 | The "init()" and "exit()" calls are replacement for "start()" and "exit()" |
| 106 | calls in the old approach. The "priv" part of the old struct stdio_dev will be |
| 107 | replaced by common private data in the driver model and the struct list_head |
| 108 | list will be eliminated by introducing common STDIO core, that tracks all the |
| 109 | STDIO devices. |
| 110 | |
| 111 | Lastly, the "conf()" call will allow the user to configure various options of |
| 112 | the driver. The enum stdio_config contains all possible configuration options |
| 113 | available to the STDIO devices, const void *data being the argument to be |
| 114 | configured. Currently, the enum stdio_config will contain at least the |
| 115 | following options: |
| 116 | |
| 117 | enum stdio_config { |
| 118 | STDIO_CONFIG_SERIAL_BAUDRATE, |
| 119 | }; |
| 120 | |
| 121 | 3) Transformation of stdio routing |
| 122 | ---------------------------------- |
| 123 | |
| 124 | By allowing multiple instances of drivers, the environment variables "stdin", |
| 125 | "stdout" and "stderr" can no longer be set to the name of the driver. |
| 126 | Therefore the STDIO core, tracking all of the STDIO devices in the system will |
| 127 | need to have a small amount of internal data for each device: |
| 128 | |
| 129 | struct stdio_device_node { |
| 130 | struct instance *i; |
| 131 | struct stdio_device_ops *ops; |
| 132 | uint8_t id; |
| 133 | uint8_t flags; |
| 134 | struct list_head list; |
| 135 | } |
| 136 | |
| 137 | The "id" is the order of the instance of the same driver. The "flags" variable |
| 138 | allows multiple drivers to be used at the same time and even for different |
| 139 | purpose. The following flags will be defined: |
| 140 | |
| 141 | STDIO_FLG_STDIN ..... This device will be used as an input device. All input |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 142 | from all devices with this flag set will be received |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 143 | and passed to the upper layers. |
| 144 | STDIO_FLG_STDOUT .... This device will be used as an output device. All |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 145 | output sent to stdout will be routed to all devices |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 146 | with this flag set. |
| 147 | STDIO_FLG_STDERR .... This device will be used as an standard error output |
Wolfgang Denk | ec7fbf5 | 2013-10-04 17:43:24 +0200 | [diff] [blame] | 148 | device. All output sent to stderr will be routed to |
Marek Vasut | 909bbcc | 2012-08-08 01:42:17 +0000 | [diff] [blame] | 149 | all devices with this flag set. |
| 150 | |
| 151 | The "list" member of this structure allows to have a linked list of all |
| 152 | registered STDIO devices. |
| 153 | |
| 154 | III) Analysis of in-tree drivers |
| 155 | -------------------------------- |
| 156 | |
| 157 | For in-depth analysis of serial port drivers, refer to [ UDM-serial.txt ]. |
| 158 | For in-depth analysis of keyboard drivers, refer to [ UDM-keyboard.txt ]. |
| 159 | For in-depth analysis of video drivers, refer to [ UDM-video.txt ]. |
| 160 | |
| 161 | 1) arch/blackfin/cpu/jtag-console.c |
| 162 | ----------------------------------- |
| 163 | This driver is a classic STDIO driver, no problem with conversion is expected. |
| 164 | |
| 165 | 2) board/mpl/pati/pati.c |
| 166 | ------------------------ |
| 167 | This driver registers with the STDIO framework, though it uses a lot of ad-hoc |
| 168 | stuff which will need to be sorted out. |
| 169 | |
| 170 | 3) board/netphone/phone_console.c |
| 171 | --------------------------------- |
| 172 | This driver is a classic STDIO driver, no problem with conversion is expected. |
| 173 | |
| 174 | 4) drivers/net/netconsole.c |
| 175 | --------------------------- |
| 176 | This driver is a classic STDIO driver, no problem with conversion is expected. |
| 177 | |
| 178 | IV) Other involved files (To be removed) |
| 179 | ---------------------------------------- |
| 180 | |
| 181 | common/cmd_console.c |
| 182 | common/cmd_log.c |
| 183 | common/cmd_terminal.c |
| 184 | common/console.c |
| 185 | common/fdt_support.c |
| 186 | common/iomux.c |
| 187 | common/lcd.c |
| 188 | common/serial.c |
| 189 | common/stdio.c |
| 190 | common/usb_kbd.c |
| 191 | doc/README.iomux |