source: grub-pc/trunk/fuentes/grub-core/term/ieee1275/escc.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 7.9 KB
Line 
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.
4 *
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.
9 *
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.
14 *
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/>.
17 */
18
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>
26
27GRUB_MOD_LICENSE ("GPLv3+");
28
29struct grub_escc_descriptor
30{
31  volatile grub_uint8_t *escc_ctrl;
32  volatile grub_uint8_t *escc_data;
33};
34
35static void
36do_real_config (struct grub_serial_port *port)
37{
38  grub_uint8_t bitsspec;
39  grub_uint8_t parity_stop_spec;
40  if (port->configured)
41    return;
42
43  /* Make sure the port is waiting for address now.  */
44  (void) *port->escc_desc->escc_ctrl;
45  switch (port->config.speed)
46    {
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;
67    }
68
69  parity_stop_spec = 0;
70  switch (port->config.parity)
71    {
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;
81    }
82
83  switch (port->config.stop_bits)
84    {
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;     
94    }
95
96  *port->escc_desc->escc_ctrl = 4;
97  *port->escc_desc->escc_ctrl = 0x40 | parity_stop_spec;
98
99  bitsspec = port->config.word_len - 5;
100  bitsspec = ((bitsspec >> 1) | (bitsspec << 1)) & 3;
101
102  *port->escc_desc->escc_ctrl = 3;
103  *port->escc_desc->escc_ctrl = (bitsspec << 6) | 0x1;
104
105  port->configured = 1;
106
107  return;
108}
109
110/* Fetch a key.  */
111static int
112serial_hw_fetch (struct grub_serial_port *port)
113{
114  do_real_config (port);
115
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;
120}
121
122/* Put a character.  */
123static void
124serial_hw_put (struct grub_serial_port *port, const int c)
125{
126  grub_uint64_t endtime;
127
128  do_real_config (port);
129
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)
138    {
139      *port->escc_desc->escc_ctrl = 0;
140      if (*port->escc_desc->escc_ctrl & 4)
141        break;
142      if (grub_get_time_ms () > endtime)
143        {
144          port->broken++;
145          /* There is something wrong. But what can I do?  */
146          return;
147        }
148    }
149
150  if (port->broken)
151    port->broken--;
152
153  *port->escc_desc->escc_data = c;
154}
155
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.  */
163static grub_err_t
164serial_hw_configure (struct grub_serial_port *port __attribute__ ((unused)),
165                     struct grub_serial_config *config __attribute__ ((unused)))
166{
167  if (config->speed != 38400 && config->speed != 57600)
168    return grub_error (GRUB_ERR_BAD_ARGUMENT,
169                       N_("unsupported serial port speed"));
170
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"));
176
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"));
182
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"));
186
187  port->config = *config;
188  port->configured = 0;
189
190  /*  FIXME: should check if the serial terminal was found.  */
191
192  return GRUB_ERR_NONE;
193}
194
195struct grub_serial_driver grub_escc_driver =
196  {
197    .configure = serial_hw_configure,
198    .fetch = serial_hw_fetch,
199    .put = serial_hw_put
200  };
201
202static struct grub_escc_descriptor escc_descs[2];
203static char *macio = 0;
204
205static void
206add_device (grub_addr_t addr, int channel)
207{
208  struct grub_serial_port *port;
209  grub_err_t err;
210  struct grub_serial_config config =
211    {
212      .speed = 38400,
213      .word_len = 8,
214      .parity = GRUB_SERIAL_PARITY_NONE,
215      .stop_bits = GRUB_SERIAL_STOP_BITS_1
216    };
217
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;
221
222  port = grub_zalloc (sizeof (*port));
223  if (!port)
224    {
225      grub_errno = 0;
226      return;
227    }
228
229  port->name = grub_xasprintf ("escc-ch-%c", channel + 'a');
230  if (!port->name)
231    {
232      grub_errno = 0;
233      return;
234    }
235
236  port->escc_desc = &escc_descs[channel];
237
238  port->driver = &grub_escc_driver;
239
240  err = port->driver->configure (port, &config);
241  if (err)
242    grub_print_error ();
243
244  grub_serial_register (port);
245}
246
247static int
248find_macio (struct grub_ieee1275_devalias *alias)
249{
250  if (grub_strcmp (alias->type, "mac-io") != 0)
251    return 0;
252  macio = grub_strdup (alias->path);
253  return 1;
254}
255
256GRUB_MOD_INIT (escc)
257{
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;
263
264  grub_ieee1275_devices_iterate (find_macio);
265  if (!macio)
266    return;
267
268  FOR_IEEE1275_DEVCHILDREN(macio, alias)
269    if (grub_strcmp (alias.type, "escc") == 0)
270      {
271        escc = grub_strdup (alias.path);
272        break;
273      }
274  grub_ieee1275_devalias_free (&alias);
275  if (!escc)
276    {
277      grub_free (macio);
278      return;
279    }
280
281  if (grub_ieee1275_finddevice (macio, &dev))
282    {
283      grub_free (macio);
284      grub_free (escc);
285      return;
286    }
287  if (grub_ieee1275_get_integer_property (dev, "assigned-addresses",
288                                          macio_addr, sizeof (macio_addr), 0))
289    {
290      grub_free (macio);
291      grub_free (escc);
292      return;
293    }
294
295  if (grub_ieee1275_finddevice (escc, &dev))
296    {
297      grub_free (macio);
298      grub_free (escc);
299      return;
300    }
301
302  if (grub_ieee1275_get_integer_property (dev, "reg",
303                                          escc_addr, sizeof (escc_addr), 0))
304    {
305      grub_free (macio);
306      grub_free (escc);
307      return;
308    }
309
310  add_device (macio_addr[2] + escc_addr[0] + 32, 0);
311  add_device (macio_addr[2] + escc_addr[0], 1);
312
313  grub_free (macio);
314  grub_free (escc);
315}
316
317GRUB_MOD_FINI (escc)
318{
319}
Note: See TracBrowser for help on using the repository browser.