Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / term / ieee1275 / escc.c
blob6d7b636f4c1056993de837f6a68ef51a1e3792f7
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2012 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
19 #include <grub/serial.h>
20 #include <grub/types.h>
21 #include <grub/dl.h>
22 #include <grub/misc.h>
23 #include <grub/mm.h>
24 #include <grub/time.h>
25 #include <grub/i18n.h>
27 GRUB_MOD_LICENSE ("GPLv3+");
29 struct grub_escc_descriptor
31 volatile grub_uint8_t *escc_ctrl;
32 volatile grub_uint8_t *escc_data;
35 static void
36 do_real_config (struct grub_serial_port *port)
38 grub_uint8_t bitsspec;
39 grub_uint8_t parity_stop_spec;
40 if (port->configured)
41 return;
43 /* Make sure the port is waiting for address now. */
44 (void) *port->escc_desc->escc_ctrl;
45 switch (port->config.speed)
47 case 57600:
48 *port->escc_desc->escc_ctrl = 13;
49 *port->escc_desc->escc_ctrl = 0;
50 *port->escc_desc->escc_ctrl = 12;
51 *port->escc_desc->escc_ctrl = 0;
52 *port->escc_desc->escc_ctrl = 14;
53 *port->escc_desc->escc_ctrl = 1;
54 *port->escc_desc->escc_ctrl = 11;
55 *port->escc_desc->escc_ctrl = 0x50;
56 break;
57 case 38400:
58 *port->escc_desc->escc_ctrl = 13;
59 *port->escc_desc->escc_ctrl = 0;
60 *port->escc_desc->escc_ctrl = 12;
61 *port->escc_desc->escc_ctrl = 1;
62 *port->escc_desc->escc_ctrl = 14;
63 *port->escc_desc->escc_ctrl = 1;
64 *port->escc_desc->escc_ctrl = 11;
65 *port->escc_desc->escc_ctrl = 0x50;
66 break;
69 parity_stop_spec = 0;
70 switch (port->config.parity)
72 case GRUB_SERIAL_PARITY_NONE:
73 parity_stop_spec |= 0;
74 break;
75 case GRUB_SERIAL_PARITY_ODD:
76 parity_stop_spec |= 1;
77 break;
78 case GRUB_SERIAL_PARITY_EVEN:
79 parity_stop_spec |= 3;
80 break;
83 switch (port->config.stop_bits)
85 case GRUB_SERIAL_STOP_BITS_1:
86 parity_stop_spec |= 0x4;
87 break;
88 case GRUB_SERIAL_STOP_BITS_1_5:
89 parity_stop_spec |= 0x8;
90 break;
91 case GRUB_SERIAL_STOP_BITS_2:
92 parity_stop_spec |= 0xc;
93 break;
96 *port->escc_desc->escc_ctrl = 4;
97 *port->escc_desc->escc_ctrl = 0x40 | parity_stop_spec;
99 bitsspec = port->config.word_len - 5;
100 bitsspec = ((bitsspec >> 1) | (bitsspec << 1)) & 3;
102 *port->escc_desc->escc_ctrl = 3;
103 *port->escc_desc->escc_ctrl = (bitsspec << 6) | 0x1;
105 port->configured = 1;
107 return;
110 /* Fetch a key. */
111 static int
112 serial_hw_fetch (struct grub_serial_port *port)
114 do_real_config (port);
116 *port->escc_desc->escc_ctrl = 0;
117 if (*port->escc_desc->escc_ctrl & 1)
118 return *port->escc_desc->escc_data;
119 return -1;
122 /* Put a character. */
123 static void
124 serial_hw_put (struct grub_serial_port *port, const int c)
126 grub_uint64_t endtime;
128 do_real_config (port);
130 if (port->broken > 5)
131 endtime = grub_get_time_ms ();
132 else if (port->broken > 1)
133 endtime = grub_get_time_ms () + 50;
134 else
135 endtime = grub_get_time_ms () + 200;
136 /* Wait until the transmitter holding register is empty. */
137 while (1)
139 *port->escc_desc->escc_ctrl = 0;
140 if (*port->escc_desc->escc_ctrl & 4)
141 break;
142 if (grub_get_time_ms () > endtime)
144 port->broken++;
145 /* There is something wrong. But what can I do? */
146 return;
150 if (port->broken)
151 port->broken--;
153 *port->escc_desc->escc_data = c;
156 /* Initialize a serial device. PORT is the port number for a serial device.
157 SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
158 19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
159 for the device. Likewise, PARITY is the type of the parity and
160 STOP_BIT_LEN is the length of the stop bit. The possible values for
161 WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
162 macros. */
163 static grub_err_t
164 serial_hw_configure (struct grub_serial_port *port __attribute__ ((unused)),
165 struct grub_serial_config *config __attribute__ ((unused)))
167 if (config->speed != 38400 && config->speed != 57600)
168 return grub_error (GRUB_ERR_BAD_ARGUMENT,
169 N_("unsupported serial port speed"));
171 if (config->parity != GRUB_SERIAL_PARITY_NONE
172 && config->parity != GRUB_SERIAL_PARITY_ODD
173 && config->parity != GRUB_SERIAL_PARITY_EVEN)
174 return grub_error (GRUB_ERR_BAD_ARGUMENT,
175 N_("unsupported serial port parity"));
177 if (config->stop_bits != GRUB_SERIAL_STOP_BITS_1
178 && config->stop_bits != GRUB_SERIAL_STOP_BITS_1_5
179 && config->stop_bits != GRUB_SERIAL_STOP_BITS_2)
180 return grub_error (GRUB_ERR_BAD_ARGUMENT,
181 N_("unsupported serial port stop bits number"));
183 if (config->word_len < 5 || config->word_len > 8)
184 return grub_error (GRUB_ERR_BAD_ARGUMENT,
185 N_("unsupported serial port word length"));
187 port->config = *config;
188 port->configured = 0;
190 /* FIXME: should check if the serial terminal was found. */
192 return GRUB_ERR_NONE;
195 struct grub_serial_driver grub_escc_driver =
197 .configure = serial_hw_configure,
198 .fetch = serial_hw_fetch,
199 .put = serial_hw_put
202 static struct grub_escc_descriptor escc_descs[2];
204 static void
205 add_device (grub_addr_t addr, int channel)
207 struct grub_serial_port *port;
208 grub_err_t err;
209 struct grub_serial_config config =
211 .speed = 38400,
212 .word_len = 8,
213 .parity = GRUB_SERIAL_PARITY_NONE,
214 .stop_bits = GRUB_SERIAL_STOP_BITS_1
217 escc_descs[channel].escc_ctrl
218 = (volatile grub_uint8_t *) (grub_addr_t) addr;
219 escc_descs[channel].escc_data = escc_descs[channel].escc_ctrl + 16;
221 port = grub_zalloc (sizeof (*port));
222 if (!port)
224 grub_errno = 0;
225 return;
228 port->name = grub_xasprintf ("escc-ch-%c", channel + 'a');
229 if (!port->name)
231 grub_errno = 0;
232 return;
235 port->escc_desc = &escc_descs[channel];
237 port->driver = &grub_escc_driver;
239 err = port->driver->configure (port, &config);
240 if (err)
241 grub_print_error ();
243 grub_serial_register (port);
246 GRUB_MOD_INIT (escc)
248 char *macio = 0;
249 char *escc = 0;
250 grub_uint32_t macio_addr[4];
251 grub_uint32_t escc_addr[2];
252 grub_ieee1275_phandle_t dev;
254 auto int find_macio (struct grub_ieee1275_devalias *alias);
255 auto int find_escc (struct grub_ieee1275_devalias *alias);
257 int find_macio (struct grub_ieee1275_devalias *alias)
259 if (grub_strcmp (alias->type, "mac-io") != 0)
260 return 0;
261 macio = grub_strdup (alias->path);
262 return 1;
265 int find_escc (struct grub_ieee1275_devalias *alias)
267 if (grub_strcmp (alias->type, "escc") != 0)
268 return 0;
269 escc = grub_strdup (alias->path);
270 return 1;
273 grub_ieee1275_devices_iterate (find_macio);
274 if (!macio)
275 return;
277 grub_children_iterate (macio, find_escc);
278 if (!escc)
280 grub_free (macio);
281 return;
284 if (grub_ieee1275_finddevice (macio, &dev))
286 grub_free (macio);
287 grub_free (escc);
288 return;
290 if (grub_ieee1275_get_integer_property (dev, "assigned-addresses",
291 macio_addr, sizeof (macio_addr), 0))
293 grub_free (macio);
294 grub_free (escc);
295 return;
298 if (grub_ieee1275_finddevice (escc, &dev))
300 grub_free (macio);
301 grub_free (escc);
302 return;
305 if (grub_ieee1275_get_integer_property (dev, "reg",
306 escc_addr, sizeof (escc_addr), 0))
308 grub_free (macio);
309 grub_free (escc);
310 return;
313 add_device (macio_addr[2] + escc_addr[0] + 32, 1);
314 add_device (macio_addr[2] + escc_addr[0], 0);
316 grub_free (macio);
317 grub_free (escc);
320 GRUB_MOD_FINI (escc)