Indentation fix, cleanup.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / term / ieee1275 / escc.c
blobe605ff25e625386042beef7bef45819fff4ddbd2
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];
203 static char *macio = 0;
205 static void
206 add_device (grub_addr_t addr, int channel)
208 struct grub_serial_port *port;
209 grub_err_t err;
210 struct grub_serial_config config =
212 .speed = 38400,
213 .word_len = 8,
214 .parity = GRUB_SERIAL_PARITY_NONE,
215 .stop_bits = GRUB_SERIAL_STOP_BITS_1
218 escc_descs[channel].escc_ctrl
219 = (volatile grub_uint8_t *) (grub_addr_t) addr;
220 escc_descs[channel].escc_data = escc_descs[channel].escc_ctrl + 16;
222 port = grub_zalloc (sizeof (*port));
223 if (!port)
225 grub_errno = 0;
226 return;
229 port->name = grub_xasprintf ("escc-ch-%c", channel + 'a');
230 if (!port->name)
232 grub_errno = 0;
233 return;
236 port->escc_desc = &escc_descs[channel];
238 port->driver = &grub_escc_driver;
240 err = port->driver->configure (port, &config);
241 if (err)
242 grub_print_error ();
244 grub_serial_register (port);
247 static int
248 find_macio (struct grub_ieee1275_devalias *alias)
250 if (grub_strcmp (alias->type, "mac-io") != 0)
251 return 0;
252 macio = grub_strdup (alias->path);
253 return 1;
256 GRUB_MOD_INIT (escc)
258 grub_uint32_t macio_addr[4];
259 grub_uint32_t escc_addr[2];
260 grub_ieee1275_phandle_t dev;
261 struct grub_ieee1275_devalias alias;
262 char *escc = 0;
264 grub_ieee1275_devices_iterate (find_macio);
265 if (!macio)
266 return;
268 FOR_IEEE1275_DEVCHILDREN(macio, alias)
269 if (grub_strcmp (alias.type, "escc") == 0)
271 escc = grub_strdup (alias.path);
272 break;
274 grub_ieee1275_devalias_free (&alias);
275 if (!escc)
277 grub_free (macio);
278 return;
281 if (grub_ieee1275_finddevice (macio, &dev))
283 grub_free (macio);
284 grub_free (escc);
285 return;
287 if (grub_ieee1275_get_integer_property (dev, "assigned-addresses",
288 macio_addr, sizeof (macio_addr), 0))
290 grub_free (macio);
291 grub_free (escc);
292 return;
295 if (grub_ieee1275_finddevice (escc, &dev))
297 grub_free (macio);
298 grub_free (escc);
299 return;
302 if (grub_ieee1275_get_integer_property (dev, "reg",
303 escc_addr, sizeof (escc_addr), 0))
305 grub_free (macio);
306 grub_free (escc);
307 return;
310 add_device (macio_addr[2] + escc_addr[0] + 32, 0);
311 add_device (macio_addr[2] + escc_addr[0], 1);
313 grub_free (macio);
314 grub_free (escc);
317 GRUB_MOD_FINI (escc)