Encapsulate serial config in dedicated structure

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-07-18 13:40:48 +02:00
parent 34364df689
commit 8c8e269906
5 changed files with 62 additions and 50 deletions

View file

@ -26,27 +26,30 @@
#include <grub/list.h> #include <grub/list.h>
struct grub_serial_port; struct grub_serial_port;
struct grub_serial_config;
struct grub_serial_driver struct grub_serial_driver
{ {
grub_err_t (*configure) (struct grub_serial_port *port, grub_err_t (*configure) (struct grub_serial_port *port,
unsigned speed, struct grub_serial_config *config);
unsigned short word_len,
unsigned int parity,
unsigned short stop_bits);
int (*fetch) (struct grub_serial_port *port); int (*fetch) (struct grub_serial_port *port);
void (*put) (struct grub_serial_port *port, const int c); void (*put) (struct grub_serial_port *port, const int c);
}; };
struct grub_serial_config
{
unsigned speed;
unsigned short word_len;
unsigned int parity;
unsigned short stop_bits;
};
struct grub_serial_port struct grub_serial_port
{ {
struct grub_serial_port *next; struct grub_serial_port *next;
char *name; char *name;
unsigned speed;
unsigned short word_len;
unsigned int parity;
unsigned short stop_bits;
struct grub_serial_driver *driver; struct grub_serial_driver *driver;
struct grub_serial_config config;
int configured; int configured;
/* This should be void *data but since serial is useful as an early console /* This should be void *data but since serial is useful as an early console
when malloc isn't available it's a union. when malloc isn't available it's a union.
@ -86,15 +89,19 @@ void grub_serial_unregister (struct grub_serial_port *port);
static inline grub_err_t static inline grub_err_t
grub_serial_config_defaults (struct grub_serial_port *port) grub_serial_config_defaults (struct grub_serial_port *port)
{ {
return port->driver->configure (port, struct grub_serial_config config =
{
#ifdef GRUB_MACHINE_MIPS_YEELOONG #ifdef GRUB_MACHINE_MIPS_YEELOONG
115200, .speed = 115200,
#else #else
9600, .speed = 9600,
#endif #endif
UART_8BITS_WORD, UART_NO_PARITY, .word_len = UART_8BITS_WORD,
UART_1_STOP_BIT); .parity = UART_NO_PARITY,
.stop_bits = UART_1_STOP_BIT
};
return port->driver->configure (port, &config);
} }
void grub_ns8250_init (void); void grub_ns8250_init (void);

View file

@ -48,6 +48,11 @@ typedef enum
GRUB_USB_SPEED_HIGH GRUB_USB_SPEED_HIGH
} grub_usb_speed_t; } grub_usb_speed_t;
enum
{
GRUB_USB_REQTYPE_VENDOR_OUT = 0x40
};
/* Call HOOK with each device, until HOOK returns non-zero. */ /* Call HOOK with each device, until HOOK returns non-zero. */
int grub_usb_iterate (int (*hook) (grub_usb_device_t dev)); int grub_usb_iterate (int (*hook) (grub_usb_device_t dev));

View file

@ -81,7 +81,7 @@ do_real_config (struct grub_serial_port *port)
if (port->configured) if (port->configured)
return; return;
divisor = serial_get_divisor (port->speed); divisor = serial_get_divisor (port->config.speed);
/* Shouldn't happen. */ /* Shouldn't happen. */
if (divisor == 0) if (divisor == 0)
return; return;
@ -97,7 +97,8 @@ do_real_config (struct grub_serial_port *port)
grub_outb (divisor >> 8, port->port + UART_DLH); grub_outb (divisor >> 8, port->port + UART_DLH);
/* Set the line status. */ /* Set the line status. */
status |= (port->parity | port->word_len | port->stop_bits); status |= (port->config.parity | port->config.word_len
| port->config.stop_bits);
grub_outb (status, port->port + UART_LCR); grub_outb (status, port->port + UART_LCR);
/* In Yeeloong serial port has only 3 wires. */ /* In Yeeloong serial port has only 3 wires. */
@ -161,20 +162,15 @@ serial_hw_put (struct grub_serial_port *port, const int c)
macros. */ macros. */
static grub_err_t static grub_err_t
serial_hw_configure (struct grub_serial_port *port, serial_hw_configure (struct grub_serial_port *port,
unsigned speed, unsigned short word_len, struct grub_serial_config *config)
unsigned int parity, unsigned short stop_bits)
{ {
unsigned short divisor; unsigned short divisor;
divisor = serial_get_divisor (speed); divisor = serial_get_divisor (config->speed);
if (divisor == 0) if (divisor == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed");
port->speed = speed; port->config = *config;
port->word_len = word_len;
port->parity = parity;
port->stop_bits = stop_bits;
port->configured = 0; port->configured = 0;
/* FIXME: should check if the serial terminal was found. */ /* FIXME: should check if the serial terminal was found. */

View file

@ -154,10 +154,7 @@ grub_cmd_serial (grub_extcmd_t cmd, int argc, char **args)
char pname[40]; char pname[40];
char *name = NULL; char *name = NULL;
struct grub_serial_port *port; struct grub_serial_port *port;
signed speed = -1; struct grub_serial_config config;
signed short word_len = -1;
signed int parity = -1;
signed short stop_bits = -1;
grub_err_t err; grub_err_t err;
if (state[0].set) if (state[0].set)
@ -184,24 +181,21 @@ grub_cmd_serial (grub_extcmd_t cmd, int argc, char **args)
if (!port) if (!port)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown serial port"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown serial port");
speed = port->speed; config = port->config;
word_len = port->word_len;
parity = port->parity;
stop_bits = port->stop_bits;
if (state[2].set) if (state[2].set)
speed = grub_strtoul (state[2].arg, 0, 0); config.speed = grub_strtoul (state[2].arg, 0, 0);
if (state[3].set) if (state[3].set)
{ {
if (! grub_strcmp (state[3].arg, "5")) if (! grub_strcmp (state[3].arg, "5"))
word_len = UART_5BITS_WORD; config.word_len = UART_5BITS_WORD;
else if (! grub_strcmp (state[3].arg, "6")) else if (! grub_strcmp (state[3].arg, "6"))
word_len = UART_6BITS_WORD; config.word_len = UART_6BITS_WORD;
else if (! grub_strcmp (state[3].arg, "7")) else if (! grub_strcmp (state[3].arg, "7"))
word_len = UART_7BITS_WORD; config.word_len = UART_7BITS_WORD;
else if (! grub_strcmp (state[3].arg, "8")) else if (! grub_strcmp (state[3].arg, "8"))
word_len = UART_8BITS_WORD; config.word_len = UART_8BITS_WORD;
else else
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad word length"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad word length");
} }
@ -209,11 +203,11 @@ grub_cmd_serial (grub_extcmd_t cmd, int argc, char **args)
if (state[4].set) if (state[4].set)
{ {
if (! grub_strcmp (state[4].arg, "no")) if (! grub_strcmp (state[4].arg, "no"))
parity = UART_NO_PARITY; config.parity = UART_NO_PARITY;
else if (! grub_strcmp (state[4].arg, "odd")) else if (! grub_strcmp (state[4].arg, "odd"))
parity = UART_ODD_PARITY; config.parity = UART_ODD_PARITY;
else if (! grub_strcmp (state[4].arg, "even")) else if (! grub_strcmp (state[4].arg, "even"))
parity = UART_EVEN_PARITY; config.parity = UART_EVEN_PARITY;
else else
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad parity"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad parity");
} }
@ -221,15 +215,15 @@ grub_cmd_serial (grub_extcmd_t cmd, int argc, char **args)
if (state[5].set) if (state[5].set)
{ {
if (! grub_strcmp (state[5].arg, "1")) if (! grub_strcmp (state[5].arg, "1"))
stop_bits = UART_1_STOP_BIT; config.stop_bits = UART_1_STOP_BIT;
else if (! grub_strcmp (state[5].arg, "2")) else if (! grub_strcmp (state[5].arg, "2"))
stop_bits = UART_2_STOP_BITS; config.stop_bits = UART_2_STOP_BITS;
else else
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad number of stop bits"); return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad number of stop bits");
} }
/* Initialize with new settings. */ /* Initialize with new settings. */
err = port->driver->configure (port, speed, word_len, parity, stop_bits); err = port->driver->configure (port, &config);
if (err) if (err)
return err; return err;
if (!registered) if (!registered)

View file

@ -23,12 +23,24 @@
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/usb.h> #include <grub/usb.h>
static void
real_config (struct grub_serial_port *port)
{
if (port->configured)
return;
port->configured = 1;
}
/* Fetch a key. */ /* Fetch a key. */
static int static int
usbserial_hw_fetch (struct grub_serial_port *port) usbserial_hw_fetch (struct grub_serial_port *port)
{ {
char cc[3]; char cc[3];
grub_usb_err_t err; grub_usb_err_t err;
real_config (port);
err = grub_usb_bulk_read (port->usbdev, port->in_endp->endp_addr, 2, cc); err = grub_usb_bulk_read (port->usbdev, port->in_endp->endp_addr, 2, cc);
if (err != GRUB_USB_ERR_NAK) if (err != GRUB_USB_ERR_NAK)
return -1; return -1;
@ -45,20 +57,18 @@ static void
usbserial_hw_put (struct grub_serial_port *port, const int c) usbserial_hw_put (struct grub_serial_port *port, const int c)
{ {
char cc = c; char cc = c;
real_config (port);
grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc);
} }
/* FIXME */ /* FIXME */
static grub_err_t static grub_err_t
usbserial_hw_configure (struct grub_serial_port *port, usbserial_hw_configure (struct grub_serial_port *port,
unsigned speed, unsigned short word_len, struct grub_serial_config *config)
unsigned int parity, unsigned short stop_bits)
{ {
port->speed = speed; port->config = *config;
port->word_len = word_len;
port->parity = parity;
port->stop_bits = stop_bits;
port->configured = 0; port->configured = 0;
return GRUB_ERR_NONE; return GRUB_ERR_NONE;