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>
22 #include <grub/misc.h>
24 #include <grub/time.h>
25 #include <grub/i18n.h>
26 #include <grub/ieee1275/console.h>
28 #define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0)
30 struct ofserial_hash_ent
33 /* Pointer to shortest available name on nodes representing canonical names,
36 struct ofserial_hash_ent
*next
;
40 do_real_config (struct grub_serial_port
*port
)
45 if (grub_ieee1275_open (port
->elem
->devpath
, &port
->handle
)
46 || port
->handle
== (grub_ieee1275_ihandle_t
) -1)
47 port
->handle
= IEEE1275_IHANDLE_INVALID
;
54 serial_hw_fetch (struct grub_serial_port
*port
)
59 do_real_config (port
);
61 if (port
->handle
== IEEE1275_IHANDLE_INVALID
)
63 grub_ieee1275_read (port
->handle
, &c
, 1, &actual
);
70 /* Put a character. */
72 serial_hw_put (struct grub_serial_port
*port
, const int c
)
77 do_real_config (port
);
79 if (port
->handle
== IEEE1275_IHANDLE_INVALID
)
82 grub_ieee1275_write (port
->handle
, &c0
, 1, &actual
);
85 /* Initialize a serial device. PORT is the port number for a serial device.
86 SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600,
87 19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used
88 for the device. Likewise, PARITY is the type of the parity and
89 STOP_BIT_LEN is the length of the stop bit. The possible values for
90 WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
93 serial_hw_configure (struct grub_serial_port
*port
__attribute__ ((unused
)),
94 struct grub_serial_config
*config
__attribute__ ((unused
)))
96 /* FIXME: no IEEE1275 serial config available. */
101 struct grub_serial_driver grub_ofserial_driver
=
103 .configure
= serial_hw_configure
,
104 .fetch
= serial_hw_fetch
,
108 #define OFSERIAL_HASH_SZ 8
109 static struct ofserial_hash_ent
*ofserial_hash
[OFSERIAL_HASH_SZ
];
112 ofserial_hash_fn (const char *devpath
)
117 return (hash
& (OFSERIAL_HASH_SZ
- 1));
120 static struct ofserial_hash_ent
*
121 ofserial_hash_find (const char *devpath
)
123 struct ofserial_hash_ent
*p
= ofserial_hash
[ofserial_hash_fn(devpath
)];
127 if (!grub_strcmp (p
->devpath
, devpath
))
134 static struct ofserial_hash_ent
*
135 ofserial_hash_add_real (char *devpath
)
137 struct ofserial_hash_ent
*p
;
138 struct ofserial_hash_ent
**head
= &ofserial_hash
[ofserial_hash_fn(devpath
)];
140 p
= grub_malloc(sizeof (*p
));
144 p
->devpath
= devpath
;
151 static struct ofserial_hash_ent
*
152 ofserial_hash_add (char *devpath
, char *curcan
)
154 struct ofserial_hash_ent
*p
, *pcan
;
156 p
= ofserial_hash_add_real (devpath
);
158 grub_dprintf ("serial", "devpath = %s, canonical = %s\n", devpath
, curcan
);
162 p
->shortest
= devpath
;
166 pcan
= ofserial_hash_find (curcan
);
168 pcan
= ofserial_hash_add_real (curcan
);
173 grub_errno
= GRUB_ERR_NONE
;
177 || grub_strlen (pcan
->shortest
) > grub_strlen (devpath
))
178 pcan
->shortest
= devpath
;
185 dev_iterate_real (struct grub_ieee1275_devalias
*alias
,
188 struct ofserial_hash_ent
*op
;
190 if (grub_strcmp (alias
->type
, "serial") != 0)
193 grub_dprintf ("serial", "serial name = %s, path = %s\n", alias
->name
,
196 op
= ofserial_hash_find (alias
->path
);
199 char *name
= grub_strdup (use_name
? alias
->name
: alias
->path
);
200 char *can
= grub_strdup (alias
->path
);
203 grub_errno
= GRUB_ERR_NONE
;
208 op
= ofserial_hash_add (name
, can
);
214 dev_iterate (struct grub_ieee1275_devalias
*alias
)
216 dev_iterate_real (alias
, 0);
221 add_port (struct ofserial_hash_ent
*ent
)
223 struct grub_serial_port
*port
;
230 port
= grub_zalloc (sizeof (*port
));
233 port
->name
= grub_malloc (sizeof ("ieee1275/")
234 + grub_strlen (ent
->shortest
));
238 ptr
= grub_stpcpy (port
->name
, "ieee1275/");
239 grub_strcpy (ptr
, ent
->shortest
);
241 port
->driver
= &grub_ofserial_driver
;
242 err
= grub_serial_config_defaults (port
);
246 grub_serial_register (port
);
252 grub_ofserial_add_port (const char *path
)
254 struct ofserial_hash_ent
*ent
;
255 char *name
= grub_strdup (path
);
256 char *can
= grub_strdup (path
);
265 ent
= ofserial_hash_add (name
, can
);
266 return add_port (ent
);
270 grub_ofserial_init (void)
273 struct grub_ieee1275_devalias alias
;
275 FOR_IEEE1275_DEVALIASES(alias
)
276 dev_iterate_real (&alias
, 1);
278 grub_ieee1275_devices_iterate (dev_iterate
);
280 for (i
= 0; i
< ARRAY_SIZE (ofserial_hash
); i
++)
282 struct ofserial_hash_ent
*ent
;
283 for (ent
= ofserial_hash
[i
]; ent
; ent
= ent
->next
)