[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] PCI serial card support
From: |
Neo Jia |
Subject: |
Re: [PATCH] PCI serial card support |
Date: |
Fri, 21 Nov 2008 18:53:19 -0800 |
hi,
Will the current GRUB 2 trunk from SVN repository contain the PCI
searil port card support?
I would like to try it out as my mb doesn't have a onboad serial port.
Thanks,
Neo
On Fri, Nov 14, 2008 at 11:24 AM, <address@hidden> wrote:
> On Thu, Nov 13, 2008 at 08:05:37PM +0200, Vesa J??skel?inen wrote:
>> Hi Don,
>>
>> Thanks for the patch!
>>
>
> Here is a new patch incorporating your comments.
>
> (Still waiting on legal about the copyright assignment, I'm sure it'll
> happen - someday.)
>
> Signed-off-by: Donald D. Dugger <address@hidden>
>
> --
> Don Dugger
> "Censeo Toto nos in Kansa esse decisse." - D. Gale
> address@hidden
> Ph: 303/443-3786
>
> diffstat pci_serial-grub-1113.patch
> ChangeLog | 14 +
> include/grub/i386/pc/serial.h | 10 +
> include/grub/i386/pc/serial_table.h | 86 ++++++++++
> include/grub/i386/pci.h | 16 ++
> include/grub/pci.h | 6
> include/grub/pci_ids.h | 29 +++
> term/i386/pc/serial.c | 288
> +++++++++++++++++++++++++-----------
> 7 files changed, 368 insertions(+), 81 deletions(-)
>
> Index: include/grub/i386/pci.h
> ===================================================================
> --- include/grub/i386/pci.h (revision 1911)
> +++ include/grub/i386/pci.h (working copy)
> @@ -32,4 +32,20 @@
> return grub_inl (GRUB_PCI_DATA_REG);
> }
>
> +static inline grub_uint32_t
> +grub_pci_read_config(unsigned int bus, unsigned int dev, unsigned int func,
> unsigned int off)
> +{
> + grub_pci_address_t addr;
> +
> + addr = grub_pci_make_address (bus, dev, func, off);
> + return grub_pci_read (addr);
> +}
> +
> +static inline grub_uint32_t
> +grub_pci_get_bar(unsigned int bus, unsigned int dev, unsigned int func,
> unsigned int bar)
> +{
> +
> + return grub_pci_read_config(bus, dev, func, 4 + bar) & ~3;
> +}
> +
> #endif /* GRUB_CPU_PCI_H */
> Index: include/grub/i386/pc/serial.h
> ===================================================================
> --- include/grub/i386/pc/serial.h (revision 1911)
> +++ include/grub/i386/pc/serial.h (working copy)
> @@ -40,6 +40,9 @@
> #define UART_DATA_READY 0x01
> #define UART_EMPTY_TRANSMITTER 0x20
>
> +/* Default base baud */
> +#define UART_BASE_BAUD 115200
> +
> /* The type of parity. */
> #define UART_NO_PARITY 0x00
> #define UART_ODD_PARITY 0x08
> @@ -64,4 +67,11 @@
> /* Turn on DTR, RTS, and OUT2. */
> #define UART_ENABLE_MODEM 0x0B
>
> +/* Serial device types */
> +#define SERIAL_LEGACY 0
> +#define SERIAL_PCI 1
> +#define SERIAL_USB 2
> +
> +void grub_serial_add(int type, unsigned int id, unsigned int base, unsigned
> int port);
> +
> #endif /* ! GRUB_SERIAL_MACHINE_HEADER */
> Index: include/grub/i386/pc/serial_table.h
> ===================================================================
> --- include/grub/i386/pc/serial_table.h (revision 0)
> +++ include/grub/i386/pc/serial_table.h (revision 0)
> @@ -0,0 +1,86 @@
> +/*
> + * GRUB -- GRand Unified Bootloader
> + * Copyright (C) 2008 Free Software Foundation, Inc.
> + *
> + * GRUB is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 3 of the License, or
> + * (at your option) any later version.
> + *
> + * GRUB is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +static void
> +titan(unsigned int bus, unsigned int dev, unsigned int func, unsigned int
> bbaud)
> +{
> + unsigned int port;
> +
> + port = grub_pci_get_bar(bus, dev, func, 1);
> + grub_serial_add(SERIAL_PCI, GRUB_PCI_BDF(bus, dev, func), bbaud, port);
> + return;
> +}
> +
> +static void
> +netmos(unsigned int bus, unsigned int dev, unsigned int func, unsigned int
> bbaud)
> +{
> + unsigned int port;
> +
> + port = grub_pci_get_bar(bus, dev, func, 0);
> + grub_serial_add(SERIAL_PCI, GRUB_PCI_BDF(bus, dev, func), bbaud, port);
> + return;
> +}
> +
> +static void
> +generic(unsigned int bus, unsigned int dev, unsigned int func, unsigned int
> bbaud)
> +{
> +
> + grub_serial_add(SERIAL_PCI, GRUB_PCI_BDF(bus, dev, func), bbaud, 0);
> + return;
> +}
> +
> +/*
> + * Table to map PCI ID to config routine. Currently, the config routine
> + * only sets the base baud but, utltimately, it should identify which
> + * I/O port is associated with which serial port.
> + */
> +static struct pci_device_id {
> + unsigned int vendor_id;
> + unsigned int device_id;
> + unsigned int ss_vendor;
> + unsigned int ss_device;
> + unsigned int dev_class;
> + unsigned int dev_class_mask;
> + unsigned int base_baud;
> + void (*dev_config)(unsigned int bus, unsigned int dev,
> + unsigned int func, unsigned int bbaud);
> +} serial_pci_id[] = {
> + { PCI_VENDOR_ID_TITAN, PCI_ANY_ID,
> + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
> + 921600, titan },
> + { PCI_VENDOR_ID_NETMOS, PCI_ANY_ID,
> + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
> + 115200, netmos },
> + /*
> + * Generic entries that define the defaults
> + */
> + { PCI_ANY_ID, PCI_ANY_ID,
> + PCI_ANY_ID, PCI_ANY_ID,
> + PCI_CLASS_COMM_SERIAL << 8, 0xffff00,
> + 115200, generic },
> + { PCI_ANY_ID, PCI_ANY_ID,
> + PCI_ANY_ID, PCI_ANY_ID,
> + PCI_CLASS_COMM_SERIAL_16450 << 8, 0xffff00,
> + 115200, generic },
> + { PCI_ANY_ID, PCI_ANY_ID,
> + PCI_ANY_ID, PCI_ANY_ID,
> + PCI_CLASS_COMM_SERIAL_16550 << 8, 0xffff00,
> + 115200, generic },
> + {
> + 0, 0, 0, 0, 0, 0, 0, generic },
> +};
> Index: include/grub/pci_ids.h
> ===================================================================
> --- include/grub/pci_ids.h (revision 0)
> +++ include/grub/pci_ids.h (revision 0)
> @@ -0,0 +1,29 @@
> +/*
> + * GRUB -- GRand Unified Bootloader
> + * Copyright (C) 2008 Free Software Foundation, Inc.
> + *
> + * GRUB is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 3 of the License, or
> + * (at your option) any later version.
> + *
> + * GRUB is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#define PCI_ANY_ID ((unsigned int)(~0))
> +
> +#define PCI_CLASS_COMM_SERIAL 0x0700
> +#define PCI_CLASS_COMM_SERIAL_16450 0x0702
> +#define PCI_CLASS_COMM_SERIAL_16550 0x0703
> +
> +#define PCI_VENDOR_ID_TITAN 0x14D2
> +#define PCI_DEVICE_ID_TITAN_100L 0x8010
> +
> +#define PCI_VENDOR_ID_NETMOS 0x9710
> +#define PCI_DEVICE_ID_NETMOS_9835 0x9835
> Index: include/grub/pci.h
> ===================================================================
> --- include/grub/pci.h (revision 1911)
> +++ include/grub/pci.h (working copy)
> @@ -35,6 +35,12 @@
> #define GRUB_PCI_ADDR_MEM_MASK ~0xf
> #define GRUB_PCI_ADDR_IO_MASK ~0x03
>
> +#define GRUB_PCI_BDF(b,d,f) ((b << 8) | (d << 3) | f)
> +
> +#define GRUB_PCI_VENDOR(id) (id & 0xffff)
> +#define GRUB_PCI_DEVICE(id) ((id >> 16) & 0xffff)
> +#define GRUB_PCI_DEVICE_CLASS(c) ((c >> 16) | ((c >> 8) & 0xff))
> +
> typedef grub_uint32_t grub_pci_id_t;
> typedef int (*grub_pci_iteratefunc_t) (int bus, int device, int func,
> grub_pci_id_t pciid);
> Index: ChangeLog
> ===================================================================
> --- ChangeLog (revision 1911)
> +++ ChangeLog (working copy)
> @@ -1,3 +1,17 @@
> +2008-11-03 Don Dugger <address@hidden>
> +
> + * term/i386/pc/serial.c: major changes to support multiple serial
> + devices, also add `--base' parameter to serial command allowing
> + user to specify base baud for those UARTs that don't follow
> + the PC standard and are not recognized
> + * include/grub/i386/pc/serial.h: define default base baud value
> + of 115200 (default for PCs) and serial device types.
> + * include/grub/i386/pc/serial_table.h: define base bauds for known
> + serial devices
> + * include/grub/pci_ids.h: start at a PCI IDs table
> + * include/grub/pci.h: add some helper functions
> + * include/grub/i386/pci.h: add some helper functions
> +
> 2008-11-12 Robert Millan <address@hidden>
>
> * conf/i386-pc.rmk (kernel_img_SOURCES): Add `term/i386/vga_common.c'.
> Index: term/i386/pc/serial.c
> ===================================================================
> --- term/i386/pc/serial.c (revision 1911)
> +++ term/i386/pc/serial.c (working copy)
> @@ -27,6 +27,10 @@
> #include <grub/arg.h>
> #include <grub/terminfo.h>
> #include <grub/cpu/io.h>
> +#include <grub/mm.h>
> +#include <grub/pci.h>
> +#include <grub/pci_ids.h>
> +#include <grub/machine/serial_table.h>
>
> #define TEXT_WIDTH 80
> #define TEXT_HEIGHT 25
> @@ -48,22 +52,24 @@
> {"word", 'w', 0, "Set the serial port word length", 0, ARG_TYPE_INT},
> {"parity", 'r', 0, "Set the serial port parity", 0, ARG_TYPE_STRING},
> {"stop", 't', 0, "Set the serial port stop bits", 0, ARG_TYPE_INT},
> + {"base", 'b', 0, "Set the serial port base baud", 0, ARG_TYPE_INT},
> {0, 0, 0, 0, 0, 0}
> };
>
> -/* Serial port settings. */
> -struct serial_port
> -{
> +struct serial_dev {
> + int type;
> + int id;
> unsigned short port;
> - unsigned short divisor;
> + unsigned int speed;
> + unsigned int base;
> unsigned short word_len;
> unsigned int parity;
> unsigned short stop_bits;
> };
> +static struct serial_dev *serial_devices = (struct serial_dev *)0;
> +static struct serial_dev *serial_dev;
> +static int num_dev = 0;
>
> -/* Serial port settings. */
> -static struct serial_port serial_settings;
> -
> #ifdef GRUB_MACHINE_PCBIOS
> /* The BIOS data area. */
> static const unsigned short *serial_hw_io_addr = (const unsigned short *)
> 0x0400;
> @@ -73,6 +79,94 @@
> #define GRUB_SERIAL_PORT_NUM
> (sizeof(serial_hw_io_addr)/(serial_hw_io_addr[0]))
> #endif
>
> +static const char *serial_types[] = {
> + "legacy",
> + "pci",
> + "usb"
> +};
> +
> +static void
> +serial_pr_type(int i, struct serial_dev *p)
> +{
> +
> + grub_printf("%c%2d: %6.6s ", (p == serial_dev) ? '*' : ' ',
> + i, serial_types[p->type]);
> + switch (p->type) {
> +
> + case SERIAL_LEGACY:
> + grub_printf(" COM%d", p->id + 1);
> + break;
> +
> + case SERIAL_PCI:
> + {
> + unsigned int b, d, f;
> +
> + b = p->id >> 8;
> + d = (p->id >> 3) & 0x1f;
> + f = p->id & 7;
> + grub_printf("%d:%02x.%d", b, d, f);
> + break;
> + }
> +
> + case SERIAL_USB:
> + grub_printf(" %2d", p->id);
> + break;
> +
> + }
> +
> + return;
> +}
> +
> +static const char parity[] = {
> + 'N',
> + 'O',
> + '?',
> + 'E'
> +};
> +
> +static void
> +serial_pr(void)
> +{
> + int i;
> + struct serial_dev *p;
> +
> + grub_printf("Available serial units:\n");
> + p = serial_devices;
> + for (i = 0; i < num_dev; i++) {
> + serial_pr_type(i, p);
> + grub_printf(" 0x%04x %6d/%-7d %d%c%d\n", p->port, p->speed, p->base,
> + p->word_len + 5,
> + parity[p->parity >> 3],
> + (p->stop_bits >> 2) + 1);
> + p++;
> + }
> +}
> +
> +void
> +grub_serial_add(int type, unsigned int id, unsigned int base, unsigned int
> port)
> +{
> + int idx, unit;
> +
> + unit = serial_dev - serial_devices;
> + idx = num_dev++;
> + if ((serial_devices = grub_realloc(serial_devices, num_dev *
> (sizeof(*serial_devices)))) == (struct serial_dev *)0) {
> + grub_error (GRUB_ERR_OUT_OF_MEMORY, "realloc of %d bytes failed\n",
> num_dev * (sizeof(*serial_devices)));
> + return;
> + }
> +
> + serial_devices[idx].type = type;
> + serial_devices[idx].id = id;
> + serial_devices[idx].base = base;
> + serial_devices[idx].port = port;
> + serial_devices[idx].speed = 9600;
> + serial_devices[idx].word_len = UART_8BITS_WORD;
> + serial_devices[idx].parity = UART_NO_PARITY;
> + serial_devices[idx].stop_bits = UART_1_STOP_BIT;
> + serial_dev = &serial_devices[unit];
> +
> + return;
> +}
> +
> /* Return the port number for the UNITth serial device. */
> static inline unsigned short
> serial_hw_get_port (const unsigned int unit)
> @@ -87,8 +181,8 @@
> static int
> serial_hw_fetch (void)
> {
> - if (grub_inb (serial_settings.port + UART_LSR) & UART_DATA_READY)
> - return grub_inb (serial_settings.port + UART_RX);
> + if (grub_inb (serial_dev->port + UART_LSR) & UART_DATA_READY)
> + return grub_inb (serial_dev->port + UART_RX);
>
> return -1;
> }
> @@ -100,14 +194,14 @@
> unsigned int timeout = 100000;
>
> /* Wait until the transmitter holding register is empty. */
> - while ((grub_inb (serial_settings.port + UART_LSR) &
> UART_EMPTY_TRANSMITTER) == 0)
> + while ((grub_inb (serial_dev->port + UART_LSR) & UART_EMPTY_TRANSMITTER)
> == 0)
> {
> if (--timeout == 0)
> /* There is something wrong. But what can I do? */
> return;
> }
>
> - grub_outb (c, serial_settings.port + UART_TX);
> + grub_outb (c, serial_dev->port + UART_TX);
> }
>
> static void
> @@ -210,35 +304,9 @@
>
> /* Convert speed to divisor. */
> static unsigned short
> -serial_get_divisor (unsigned int speed)
> +serial_get_divisor (unsigned int speed, unsigned int base)
> {
> - unsigned int i;
> -
> - /* The structure for speed vs. divisor. */
> - struct divisor
> - {
> - unsigned int speed;
> - unsigned short div;
> - };
> -
> - /* The table which lists common configurations. */
> - /* 1843200 / (speed * 16) */
> - static struct divisor divisor_tab[] =
> - {
> - { 2400, 0x0030 },
> - { 4800, 0x0018 },
> - { 9600, 0x000C },
> - { 19200, 0x0006 },
> - { 38400, 0x0003 },
> - { 57600, 0x0002 },
> - { 115200, 0x0001 }
> - };
> -
> - /* Set the baud rate. */
> - for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++)
> - if (divisor_tab[i].speed == speed)
> - return divisor_tab[i].div;
> - return 0;
> + return ((base << 4) + (speed << 3)) / (speed << 4);
> }
>
> /* The serial version of checkkey. */
> @@ -274,31 +342,36 @@
> WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as
> macros. */
> static grub_err_t
> -serial_hw_init (void)
> +serial_hw_init (struct serial_dev *dev)
> {
> unsigned char status = 0;
> + unsigned short divisor;
>
> + if (dev->port == 0)
> + return GRUB_ERR_OUT_OF_RANGE;
> +
> /* Turn off the interrupt. */
> - grub_outb (0, serial_settings.port + UART_IER);
> + grub_outb (0, dev->port + UART_IER);
>
> /* Set DLAB. */
> - grub_outb (UART_DLAB, serial_settings.port + UART_LCR);
> + grub_outb (UART_DLAB, dev->port + UART_LCR);
>
> /* Set the baud rate. */
> - grub_outb (serial_settings.divisor & 0xFF, serial_settings.port +
> UART_DLL);
> - grub_outb (serial_settings.divisor >> 8, serial_settings.port + UART_DLH);
> + divisor = serial_get_divisor(dev->speed, dev->base);
> + grub_outb (divisor & 0xFF, dev->port + UART_DLL);
> + grub_outb (divisor >> 8, dev->port + UART_DLH);
>
> /* Set the line status. */
> - status |= (serial_settings.parity
> - | serial_settings.word_len
> - | serial_settings.stop_bits);
> - grub_outb (status, serial_settings.port + UART_LCR);
> + status |= (dev->parity
> + | dev->word_len
> + | dev->stop_bits);
> + grub_outb (status, dev->port + UART_LCR);
>
> /* Enable the FIFO. */
> - grub_outb (UART_ENABLE_FIFO, serial_settings.port + UART_FCR);
> + grub_outb (UART_ENABLE_FIFO, dev->port + UART_FCR);
>
> /* Turn on DTR, RTS, and OUT2. */
> - grub_outb (UART_ENABLE_MODEM, serial_settings.port + UART_MCR);
> + grub_outb (UART_ENABLE_MODEM, dev->port + UART_MCR);
>
> /* Drain the input buffer. */
> while (grub_serial_checkkey () != -1)
> @@ -495,31 +568,41 @@
> int argc __attribute__ ((unused)),
> char **args __attribute__ ((unused)))
> {
> - struct serial_port backup_settings = serial_settings;
> + int unit;
> + struct serial_dev dev;
> grub_err_t hwiniterr;
>
> + if ((state[0].set == 0) && (state[1].set == 0) && (state[2].set == 0) &&
> + (state[3].set == 0) && (state[4].set == 0) && (state[5].set == 0) &&
> + (state[6].set == 0)) {
> + serial_pr();
> + return GRUB_ERR_NONE;
> + }
> +
> + dev = *serial_dev;
> + unit = serial_dev - serial_devices;
> if (state[0].set)
> {
> - unsigned int unit;
>
> unit = grub_strtoul (state[0].arg, 0, 0);
> - serial_settings.port = serial_hw_get_port (unit);
> - if (!serial_settings.port)
> - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad unit number.");
> + if (unit >= num_dev)
> + {
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad unit number.");
> + }
> + dev = serial_devices[unit];
> }
>
> if (state[1].set)
> - serial_settings.port = (unsigned short) grub_strtoul (state[1].arg, 0,
> 0);
> + {
> + dev.port = (unsigned short) grub_strtoul (state[1].arg, 0, 0);
> + }
>
> if (state[2].set)
> {
> - unsigned long speed;
>
> - speed = grub_strtoul (state[2].arg, 0, 0);
> - serial_settings.divisor = serial_get_divisor ((unsigned int) speed);
> - if (serial_settings.divisor == 0)
> + dev.speed = (unsigned int )grub_strtoul (state[2].arg, 0, 0);
> + if (dev.speed == 0)
> {
> - serial_settings = backup_settings;
> return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed");
> }
> }
> @@ -527,16 +610,15 @@
> if (state[3].set)
> {
> if (! grub_strcmp (state[3].arg, "5"))
> - serial_settings.word_len = UART_5BITS_WORD;
> + dev.word_len = UART_5BITS_WORD;
> else if (! grub_strcmp (state[3].arg, "6"))
> - serial_settings.word_len = UART_6BITS_WORD;
> + dev.word_len = UART_6BITS_WORD;
> else if (! grub_strcmp (state[3].arg, "7"))
> - serial_settings.word_len = UART_7BITS_WORD;
> + dev.word_len = UART_7BITS_WORD;
> else if (! grub_strcmp (state[3].arg, "8"))
> - serial_settings.word_len = UART_8BITS_WORD;
> + dev.word_len = UART_8BITS_WORD;
> else
> {
> - serial_settings = backup_settings;
> return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad word length");
> }
> }
> @@ -544,14 +626,13 @@
> if (state[4].set)
> {
> if (! grub_strcmp (state[4].arg, "no"))
> - serial_settings.parity = UART_NO_PARITY;
> + dev.parity = UART_NO_PARITY;
> else if (! grub_strcmp (state[4].arg, "odd"))
> - serial_settings.parity = UART_ODD_PARITY;
> + dev.parity = UART_ODD_PARITY;
> else if (! grub_strcmp (state[4].arg, "even"))
> - serial_settings.parity = UART_EVEN_PARITY;
> + dev.parity = UART_EVEN_PARITY;
> else
> {
> - serial_settings = backup_settings;
> return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad parity");
> }
> }
> @@ -559,21 +640,32 @@
> if (state[5].set)
> {
> if (! grub_strcmp (state[5].arg, "1"))
> - serial_settings.stop_bits = UART_1_STOP_BIT;
> + dev.stop_bits = UART_1_STOP_BIT;
> else if (! grub_strcmp (state[5].arg, "2"))
> - serial_settings.stop_bits = UART_2_STOP_BITS;
> + dev.stop_bits = UART_2_STOP_BITS;
> else
> {
> - serial_settings = backup_settings;
> return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad number of stop bits");
> }
> }
>
> + if (state[6].set)
> + {
> +
> + dev.base = grub_strtoul (state[6].arg, 0, 0);
> + if (dev.base == 0)
> + {
> + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad base baud");
> + }
> + }
> +
> /* Initialize with new settings. */
> - hwiniterr = serial_hw_init ();
> + hwiniterr = serial_hw_init (&dev);
>
> if (hwiniterr == GRUB_ERR_NONE)
> {
> + serial_dev = &serial_devices[unit];
> + *serial_dev = dev;
> /* Register terminal if not yet registered. */
> if (registered == 0)
> {
> @@ -584,13 +676,13 @@
> }
> else
> {
> + grub_error(GRUB_ERR_BAD_ARGUMENT, "Bad settings, revert to prior
> device");
> /* Initialization with new settings failed. */
> if (registered == 1)
> {
> /* If the terminal is registered, attempt to restore previous
> settings. */
> - serial_settings = backup_settings;
> - if (serial_hw_init () != GRUB_ERR_NONE)
> + if (serial_hw_init (serial_dev) != GRUB_ERR_NONE)
> {
> /* If unable to restore settings, unregister terminal. */
> grub_term_unregister_input (&grub_serial_term_input);
> @@ -603,21 +695,55 @@
> return hwiniterr;
> }
>
> +static int
> +serial_pci_scan (int bus, int dev, int func, grub_pci_id_t pci_id)
> +{
> + struct pci_device_id *p;
> + unsigned int w, vid, did, ss_vid, ss_did, class;
> +
> + vid = GRUB_PCI_VENDOR(pci_id);
> + did = GRUB_PCI_DEVICE(pci_id);
> + class = GRUB_PCI_DEVICE_CLASS(grub_pci_read_config(bus, dev, func, 2));
> + w = grub_pci_read_config (bus, dev, func, 11);
> + ss_vid = GRUB_PCI_VENDOR(w);
> + ss_did = GRUB_PCI_DEVICE(w);
> + for (p = serial_pci_id; p->vendor_id; p++) {
> + if ((p->vendor_id == PCI_ANY_ID || p->vendor_id == vid) &&
> + (p->device_id == PCI_ANY_ID || p->device_id == did) &&
> + (p->ss_vendor == PCI_ANY_ID || p->ss_vendor == ss_vid) &&
> + (p->ss_device == PCI_ANY_ID || p->ss_device == ss_did) &&
> + !((p->dev_class ^ (class << 8)) & p->dev_class_mask)) {
> + (p->dev_config)(bus, dev, func, p->base_baud);
> + break;
> + }
> + }
> + return 0;
> +}
> +
> GRUB_MOD_INIT(serial)
> {
> + int i;
> + unsigned int port;
> +
> (void) mod; /* To stop warning. */
> + grub_errno = 0;
> grub_register_command ("serial", grub_cmd_serial, GRUB_COMMAND_FLAG_BOTH,
> "serial [OPTIONS...]", "Configure serial port.",
> options);
> /* Set default settings. */
> - serial_settings.port = serial_hw_get_port (0);
> - serial_settings.divisor = serial_get_divisor (9600);
> - serial_settings.word_len = UART_8BITS_WORD;
> - serial_settings.parity = UART_NO_PARITY;
> - serial_settings.stop_bits = UART_1_STOP_BIT;
> + for (i = 0; i < GRUB_SERIAL_PORT_NUM; i++)
> + if ((port = serial_hw_get_port(i)) != 0)
> + grub_serial_add(SERIAL_LEGACY, i, UART_BASE_BAUD, port);
> + serial_dev = &serial_devices[0];
> +
> + /*
> + * Check for PCI serial card, set defaults appropriately if one exists
> + */
> + grub_pci_iterate (serial_pci_scan);
> }
>
> GRUB_MOD_FINI(serial)
> {
> + grub_free (serial_devices);
> grub_unregister_command ("serial");
> if (registered == 1) /* Unregister terminal only if registered. */
> {
>
>
> _______________________________________________
> Grub-devel mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/grub-devel
>
--
I would remember that if researchers were not ambitious
probably today we haven't the technology we are using!
- Re: [PATCH] PCI serial card support, (continued)
- Re: [PATCH] PCI serial card support, Robert Millan, 2008/11/08
- Re: [PATCH] PCI serial card support, Vesa Jääskeläinen, 2008/11/08
- Re: [PATCH] PCI serial card support, n0ano, 2008/11/08
- Re: [PATCH] PCI serial card support, Robert Millan, 2008/11/09
- Re: [PATCH] PCI serial card support, Vesa Jääskeläinen, 2008/11/09
- Re: [PATCH] PCI serial card support, n0ano, 2008/11/09
- Re: [PATCH] PCI serial card support, n0ano, 2008/11/12
- Re: [PATCH] PCI serial card support, Vesa Jääskeläinen, 2008/11/13
- Re: [PATCH] PCI serial card support, n0ano, 2008/11/13
- Re: [PATCH] PCI serial card support, n0ano, 2008/11/14
- Re: [PATCH] PCI serial card support,
Neo Jia <=
- Re: [PATCH] PCI serial card support, Vesa Jääskeläinen, 2008/11/22
Re: [PATCH] PCI serial card support, Vesa Jääskeläinen, 2008/11/04