diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index ea3f6bedf239bc40421df0d924d07e156e374954..ba16a21a7a051c52510f1fb48063b43a0b9569d3 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -122,13 +122,13 @@ struct uart_8250_port { struct uart_port port; struct timer_list timer; /* "no irq" timer */ struct list_head list; /* ports on this IRQ */ + unsigned short rev; unsigned char acr; unsigned char ier; - unsigned char rev; unsigned char lcr; unsigned char mcr_mask; /* mask of user bits */ unsigned char mcr_force; /* mask of forced bits */ - unsigned int lsr_break_flag; + unsigned char lsr_break_flag; /* * We provide a per-port pm hook. diff --git a/drivers/serial/8250_cs.c b/drivers/serial/8250_cs.c index 135699e8fad275f65cfb2a4e574ab00132150e6a..c10b031bc0aea4b923758a3f1ef7e695439993a5 100644 --- a/drivers/serial/8250_cs.c +++ b/drivers/serial/8250_cs.c @@ -2,7 +2,7 @@ A driver for PCMCIA serial devices - serial_cs.c 1.123 2000/08/24 18:46:38 + serial_cs.c 1.134 2002/05/04 05:48:53 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -43,7 +43,6 @@ #include <linux/serial.h> #include <linux/serial_core.h> #include <linux/major.h> -#include <linux/workqueue.h> #include <asm/io.h> #include <asm/system.h> @@ -59,7 +58,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = "serial_cs.c 1.123 2000/08/24 18:46:38 (David Hinds)"; +static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -74,10 +73,13 @@ static int irq_list[4] = { -1 }; /* Enable the speaker? */ static int do_sound = 1; +/* Skip strict UART tests? */ +static int buggy_uart; MODULE_PARM(irq_mask, "i"); MODULE_PARM(irq_list, "1-4i"); MODULE_PARM(do_sound, "i"); +MODULE_PARM(buggy_uart, "i"); /*====================================================================*/ @@ -100,7 +102,7 @@ static struct multi_id multi_id[] = { }; #define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id)) -typedef struct serial_info { +struct serial_info { dev_link_t link; int ndev; int multi; @@ -108,8 +110,7 @@ typedef struct serial_info { int manfid; dev_node_t node[4]; int line[4]; - struct work_struct remove; -} serial_info_t; +}; static void serial_config(dev_link_t * link); static int serial_event(event_t event, int priority, @@ -124,20 +125,19 @@ static dev_link_t *dev_list = NULL; /*====================================================================== - After a card is removed, do_serial_release() will unregister + After a card is removed, serial_remove() will unregister the serial device(s), and release the PCMCIA configuration. ======================================================================*/ -/* - * This always runs in process context. - */ -static void do_serial_release(void *arg) +static void serial_remove(dev_link_t *link) { - struct serial_info *info = arg; - int i; + struct serial_info *info = link->priv; + int i, ret; - DEBUG(0, "serial_release(0x%p)\n", &info->link); + link->state &= ~DEV_PRESENT; + + DEBUG(0, "serial_release(0x%p)\n", link); /* * Recheck to see if the device is still configured. @@ -158,25 +158,6 @@ static void do_serial_release(void *arg) } } -/* - * This may be called from IRQ context. - */ -static void serial_remove(dev_link_t *link) -{ - struct serial_info *info = link->priv; - - link->state &= ~DEV_PRESENT; - - /* - * FIXME: Since the card has probably been removed, - * we should call into the serial layer and hang up - * the ports on the card immediately. - */ - - if (link->state & DEV_CONFIG) - schedule_work(&info->remove); -} - /*====================================================================== serial_attach() creates an "instance" of the driver, allocating @@ -187,7 +168,7 @@ static void serial_remove(dev_link_t *link) static dev_link_t *serial_attach(void) { - serial_info_t *info; + struct serial_info *info; client_reg_t client_reg; dev_link_t *link; int i, ret; @@ -202,8 +183,6 @@ static dev_link_t *serial_attach(void) link = &info->link; link->priv = info; - INIT_WORK(&info->remove, do_serial_release, info); - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; @@ -214,7 +193,6 @@ static dev_link_t *serial_attach(void) for (i = 0; i < 4; i++) link->irq.IRQInfo2 |= 1 << irq_list[i]; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; if (do_sound) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; @@ -254,7 +232,7 @@ static dev_link_t *serial_attach(void) static void serial_detach(dev_link_t * link) { - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; dev_link_t **linkp; int ret; @@ -275,7 +253,7 @@ static void serial_detach(dev_link_t * link) /* * Ensure that the ports have been released. */ - do_serial_release(info); + serial_remove(link); if (link->handle) { ret = CardServices(DeregisterClient, link->handle); @@ -290,7 +268,7 @@ static void serial_detach(dev_link_t * link) /*====================================================================*/ -static int setup_serial(serial_info_t * info, ioaddr_t port, int irq) +static int setup_serial(struct serial_info * info, ioaddr_t port, int irq) { struct serial_struct serial; int line; @@ -299,11 +277,13 @@ static int setup_serial(serial_info_t * info, ioaddr_t port, int irq) serial.port = port; serial.irq = irq; serial.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ; + if (buggy_uart) + serial.flags |= UPF_BUGGY_UART; line = register_serial(&serial); if (line < 0) { printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx," " irq %d failed\n", (u_long) serial.port, serial.irq); - return -1; + return -EINVAL; } info->line[info->ndev] = line; @@ -341,7 +321,7 @@ static int simple_config(dev_link_t * link) { static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; client_handle_t handle = link->handle; - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; tuple_t tuple; u_char buf[256]; cisparse_t parse; @@ -445,13 +425,21 @@ static int simple_config(dev_link_t * link) static int multi_config(dev_link_t * link) { client_handle_t handle = link->handle; - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; tuple_t tuple; u_char buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; int i, base2 = 0; + i = CardServices(GetConfigurationInfo, handle, &config); + if (i != CS_SUCCESS) { + cs_error(handle, GetConfiguration, i); + return -1; + } + link->conf.Vcc = config.Vcc; + tuple.TupleData = (cisdata_t *) buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; @@ -524,6 +512,19 @@ static int multi_config(dev_link_t * link) return -1; } + /* The Oxford Semiconductor OXCF950 cards are in fact single-port: + 8 registers are for the UART, the others are extra registers */ + if (info->manfid == MANFID_OXSEMI) { + if (cf->index == 1 || cf->index == 3) { + setup_serial(info, base2, link->irq.AssignedIRQ); + outb(12, link->io.BasePort1 + 1); + } else { + setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); + outb(12, base2 + 1); + } + return 0; + } + setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); /* The Nokia cards are not really multiport cards */ if (info->manfid == MANFID_NOKIA) @@ -548,7 +549,7 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed void serial_config(dev_link_t * link) { client_handle_t handle = link->handle; - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; tuple_t tuple; u_short buf[128]; cisparse_t parse; @@ -631,7 +632,8 @@ void serial_config(dev_link_t * link) cs_failed: cs_error(link->handle, last_fn, last_ret); failed: - do_serial_release(info); + serial_remove(link); + link->state &= ~DEV_CONFIG_PENDING; } /*====================================================================== @@ -647,7 +649,7 @@ static int serial_event(event_t event, int priority, event_callback_args_t * args) { dev_link_t *link = args->client_data; - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; DEBUG(1, "serial_event(0x%06x)\n", event); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index ab19af68c41b2d485c117c659619647741552b33..98bb4fc127dcf5f6e2921e17f858a9f09c0a6fb3 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -80,14 +80,14 @@ config SERIAL_8250_CS config SERIAL_8250_ACPI bool "8250/16550 device discovery via ACPI namespace" default y if IA64 - depends on ACPI_BUS + depends on ACPI_BUS && SERIAL_8250 ---help--- If you wish to enable serial port discovery via the ACPI namespace, say Y here. If unsure, say N. config SERIAL_8250_HCDP bool "8250/16550 device discovery support via EFI HCDP table" - depends on IA64 + depends on IA64 && SERIAL_8250 ---help--- If you wish to make the serial console port described by the EFI HCDP table available for use as serial console or general