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, <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> > > -- > Don Dugger > "Censeo Toto nos in Kansa esse decisse." - D. Gale > [EMAIL PROTECTED] > 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 <[EMAIL PROTECTED]> > + > + * 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 <[EMAIL PROTECTED]> > > * 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 > Grub-devel@gnu.org > 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! _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel