diff -urN -X dontdiff.txt linux-2.4.18-pre9/drivers/char/serial.c pre9-ml/drivers/char/serial.c --- linux-2.4.18-pre9/drivers/char/serial.c Mon Feb 11 12:23:00 2002 +++ pre9-ml/drivers/char/serial.c Mon Feb 11 16:12:08 2002 @@ -57,10 +57,13 @@ * 10/00: add in optional software flow control for serial console. * Kanoj Sarcar (Modified by Theodore Ts'o) * + * 11/01: add basic support for Macrolink MCCR and MCCS cards. + * Ed Vance + * */ -static char *serial_version = "5.05c"; -static char *serial_revdate = "2001-07-08"; +static char *serial_version = "5.05c-ml"; +static char *serial_revdate = "2001-11-27"; /* * Serial driver configuration section. Here are the various options: @@ -1391,6 +1394,8 @@ if (state->irq != 0) info->MCR |= UART_MCR_OUT2; } + if (info->flags & ASYNC_FORCE_OUT2) + info->MCR |= UART_MCR_OUT2; info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ serial_outp(info, UART_MCR, info->MCR); @@ -1529,6 +1534,9 @@ } else #endif info->MCR &= ~UART_MCR_OUT2; + + if (info->flags & ASYNC_FORCE_OUT2) + info->MCR |= UART_MCR_OUT2; info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ /* disable break condition */ @@ -2342,6 +2350,8 @@ return -EINVAL; } save_flags(flags); cli(); + if (info->flags & ASYNC_FORCE_OUT2) + info->MCR |= UART_MCR_OUT2; info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ serial_out(info, UART_MCR, info->MCR); restore_flags(flags); @@ -3249,10 +3259,12 @@ ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d", state->line, uart_config[state->type].name, - state->port, state->irq); + (state->port ? state->port : (long)state->iomem_base), + state->irq); - if (!state->port || (state->type == PORT_UNKNOWN)) { - ret += sprintf(buf+ret, "\n"); + if ((!state->port && !state->iomem_base) || + (state->type == PORT_UNKNOWN)) { + ret += sprintf(buf+ret, " \n"); return ret; } @@ -3914,8 +3926,11 @@ port = pci_resource_start(dev, base_idx) + offset; + if (board->uart_offset == 0) + board->uart_offset = 8; + if ((board->flags & SPCI_FL_BASE_TABLE) == 0) - port += idx * (board->uart_offset ? board->uart_offset : 8); + port += idx * board->uart_offset; if (IS_PCI_REGION_IOPORT(dev, base_idx)) { req->port = port; @@ -3925,6 +3940,13 @@ req->port_high = 0; return 0; } + + /* MCCR io_mem: only 4 ports mapped into each 1K block */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_MACROLINK && + dev->subsystem_device >> 8 == PCI_DEVICE_ID_MACROLINK_MCCR >> 8) { + port -= (idx / 4) * (board->uart_offset * 4); + port += (idx / 4) * 1024; + } req->io_type = SERIAL_IO_MEM; req->iomem_base = ioremap(port, board->uart_offset); req->iomem_reg_shift = board->reg_shift; @@ -4006,6 +4028,12 @@ printk("Setup PCI/PNP port: port %x, irq %d, type %d\n", serial_req.port, serial_req.irq, serial_req.io_type); #endif + /* Detect MCCS card. Must always assert OUT2 */ + if (dev->subsystem_vendor == PCI_VENDOR_ID_MACROLINK && + dev->subsystem_device >> 8 == + PCI_DEVICE_ID_MACROLINK_MCCS >> 8) { + serial_req.flags |= ASYNC_FORCE_OUT2; + } line = register_serial(&serial_req); if (line < 0) break; @@ -4224,6 +4252,71 @@ } /* + * Set front panel LED to green if enabled, to yellow if disabled. + * LED control is 16PCI954 MIC reg bits 23-20 in BAR3 +4 (memory). + * Preserve the state of the other writable bits in the MIC reg. + */ +static int __devinit +pci_mccr_fn(struct pci_dev *dev, struct pci_board *board, int enable) +{ + u32 tmp; + char *p; + + p = ioremap(pci_resource_start(dev, 3), 0x80); + tmp = readl(p + 4); + tmp &= ~(0xf << 20); + tmp |= (enable ? 0xb : 0xa) << 20; + writel(tmp, p + 4); + iounmap(p); + return 0; +} + +/* + * Set the front panel LED green (enable) or yellow (disable) via + * bits 7-6 of 16-bit status register at BAR3 +0xa (memory). + * Enable or disable card interrupts with the PCI Interrupt Enable + * bit 6 in the PLX 9050 INTCSR register at BAR0 +0x4c (memory). + + */ +static int __devinit +pci_mccs_fn(struct pci_dev *dev, struct pci_board *board, int enable) +{ + int j; + u32 tmp; + u8 *p; + + /* Wake UART and set prescalar to x1 */ + /* Set all UART MCR bit 3 to avoid interrupt storm */ + p = ioremap(pci_resource_start(dev, 5), board->num_ports * 8); + for (j=0; j < board->num_ports; j++) { + writeb(0xBF, p + (j * 8) + UART_LCR); /* enh regs */ + writeb(UART_EFR_ECB, p + (j * 8) + UART_EFR); /* enable */ + writeb(0x00, p + (j * 8) + UART_LCR); /* gen regs */ + writeb(UART_MCR_OUT2, p + (j * 8) + UART_MCR); /* x1,out2 */ + writeb(0xBF, p + (j * 8) + UART_LCR); /* enh regs */ + writeb(0x00, p + (j * 8) + UART_EFR); /* latch x1 */ + writeb(0x00, p + (j * 8) + UART_LCR); /* gen regs */ + } + iounmap(p); + + p = ioremap(pci_resource_start(dev, 3), 0x80); + writew(0, p + 0x2); /* clear pending interrupt */ + tmp = enable ? 0x42 : 0x00; + writew(tmp, p + 0xa); /* Set front panel LED color */ + iounmap(p); + + p = ioremap(pci_resource_start(dev, 0), 0x80); + tmp = readl(p + 0x4c); + tmp &= ~(0x40); + if (enable) + tmp |= 0x40; + writel(tmp, p + 0x4c); /* (En/Dis)able card interrupt */ + iounmap(p); + + return 0; +} + +/* * This is the configuration table for all of the PCI serial boards * which we support. It is directly indexed by the pci_board_num_t enum * value, which is encoded in the pci_device_id PCI probe table's @@ -4297,6 +4390,15 @@ pbn_computone_4, pbn_computone_6, pbn_computone_8, + + pbn_ml_mccs_8, + pbn_ml_mccs_16, + pbn_ml_mccs_8_hs, + pbn_ml_mccs_16_hs, + pbn_ml_mccr_8_p0, + pbn_ml_mccr_8_p4, + pbn_ml_mccr_16_p0, + pbn_ml_mccr_16_p4, }; static struct pci_board pci_boards[] __devinitdata = { @@ -4401,6 +4503,23 @@ 0x40, 2, NULL, 0x200 }, { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */ 0x40, 2, NULL, 0x200 }, + + { SPCI_FL_BASE5, 8, 921600, /* IOMEM */ /* pbn_ml_mccs_8 */ + 8, 0, pci_mccs_fn }, + { SPCI_FL_BASE5, 16, 921600, /* IOMEM */ /* pbn_ml_mccs_16 */ + 8, 0, pci_mccs_fn }, + { SPCI_FL_BASE5, 8, 921600, /* IOMEM */ /* pbn_ml_mccs_8_hs */ + 8, 0, pci_mccs_fn }, + { SPCI_FL_BASE5, 16, 921600, /* IOMEM */ /* pbn_ml_mccs_16_hs */ + 8, 0, pci_mccs_fn }, + { SPCI_FL_BASE1, 4, 3125000, /* IOMEM */ /* pbn_ml_mccr_8_p0 */ + 0x20, 2 }, + { SPCI_FL_BASE1, 4, 3125000, /* IOMEM */ /* pbn_ml_mccr_8_p4 */ + 0x20, 2, pci_mccr_fn }, + { SPCI_FL_BASE1, 4, 3125000, /* IOMEM */ /* pbn_ml_mccr_16_p0 */ + 0x20, 2 }, + { SPCI_FL_BASE1, 12, 3125000, /* IOMEM */ /* pbn_ml_mccr_16_p4 */ + 0x20, 2, pci_mccr_fn }, }; /* @@ -4632,6 +4751,41 @@ PCI_SUBVENDOR_ID_CHASE_PCIRAS, PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, pbn_b2_8_460800 }, + /* Macrolink 8/16-port CompactPCI serial cards. */ + /* Must precede all other PLX_9050 cards with */ + /* subvendor and subdevice set to PCI_ANY_ID. */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_VENDOR_ID_MACROLINK, + PCI_DEVICE_ID_MACROLINK_MCCS8, 0, 0, + pbn_ml_mccs_8 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_VENDOR_ID_MACROLINK, + PCI_DEVICE_ID_MACROLINK_MCCS, 0, 0, + pbn_ml_mccs_16 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, + PCI_VENDOR_ID_MACROLINK, + PCI_DEVICE_ID_MACROLINK_MCCS8H, 0, 0, + pbn_ml_mccs_8_hs }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, + PCI_VENDOR_ID_MACROLINK, + PCI_DEVICE_ID_MACROLINK_MCCSH, 0, 0, + pbn_ml_mccs_16_hs }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_VENDOR_ID_MACROLINK, + PCI_DEVICE_ID_MACROLINK_MCCR8, 0, 0, /* fn0: p0-3 */ + pbn_ml_mccr_8_p0 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, + PCI_VENDOR_ID_MACROLINK, + PCI_DEVICE_ID_MACROLINK_MCCR8, 0, 0, /* fn1: p4-7 */ + pbn_ml_mccr_8_p4 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_VENDOR_ID_MACROLINK, + PCI_DEVICE_ID_MACROLINK_MCCR, 0, 0, /* fn0: p0-3 */ + pbn_ml_mccr_16_p0 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, + PCI_VENDOR_ID_MACROLINK, + PCI_DEVICE_ID_MACROLINK_MCCR, 0, 0, /* fn1: p4-15 */ + pbn_ml_mccr_16_p4 }, /* Megawolf Romulus PCI Serial Card, from Mike Hudson */ /* (Exoray@isys.ca) */ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, @@ -5708,6 +5862,7 @@ #if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) if (rs_table[i].iomem_base) iounmap(rs_table[i].iomem_base); + rs_table[i].flags &= ~ASYNC_FORCE_OUT2; #endif } #if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP) @@ -5976,7 +6131,11 @@ serial_out(info, UART_DLM, quot >> 8); /* MS of divisor */ serial_out(info, UART_LCR, cval); /* reset DLAB */ serial_out(info, UART_IER, 0); - serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); + info->MCR = UART_MCR_DTR | UART_MCR_RTS; + if (info->flags & ASYNC_FORCE_OUT2) + info->MCR |= UART_MCR_OUT2; + info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ + serial_out(info, UART_MCR, info->MCR); /* * If we read 0xff from the LSR, there is no UART here. diff -urN -X dontdiff.txt linux-2.4.18-pre9/drivers/pci/pci.ids pre9-ml/drivers/pci/pci.ids --- linux-2.4.18-pre9/drivers/pci/pci.ids Mon Feb 11 12:23:03 2002 +++ pre9-ml/drivers/pci/pci.ids Mon Feb 11 15:02:06 2002 @@ -1560,9 +1560,14 @@ 0001 i960 PCI bus interface 1076 VScom 800 8 port serial adaptor 1077 VScom 400 4 port serial adaptor + 9030 PCI <-> IOBus Bridge (Hot Swap) + 15ed 1002 Macrolink MCCS 8-port Serial (Hot Swap) + 15ed 1003 Macrolink MCCS 16-port Serial (Hot Swap) 9036 9036 9050 PCI <-> IOBus Bridge 10b5 2273 SH-ARC SoHard ARCnet card + 15ed 1000 Macrolink MCCS 8-port Serial + 15ed 1001 Macrolink MCCS 16-port Serial d84d 4006 EX-4006 1P d84d 4008 EX-4008 1P EPP/ECP d84d 4014 EX-4014 2P @@ -3952,6 +3957,12 @@ 1413 Addonics 1414 Microsoft Corporation 1415 Oxford Semiconductor Ltd + 9501 16PCI954 Function 0 + 15ed 2000 Macrolink MCCR Serial p0-3 of 8 + 15ed 2001 Macrolink MCCR Serial p0-3 of 16 + 9511 16PCI954 Function 1 + 15ed 2000 Macrolink MCCR Serial p4-7 of 8 + 15ed 2001 Macrolink MCCR Serial p4-15 of 16 1416 Multiwave Innovation pte Ltd 1417 Convergenet Technologies Inc 1418 Kyushu electronics systems Inc diff -urN -X dontdiff.txt linux-2.4.18-pre9/include/linux/pci_ids.h pre9-ml/include/linux/pci_ids.h --- linux-2.4.18-pre9/include/linux/pci_ids.h Mon Feb 11 12:23:08 2002 +++ pre9-ml/include/linux/pci_ids.h Mon Feb 11 15:02:06 2002 @@ -764,6 +764,7 @@ #define PCI_DEVICE_ID_PLX_SPCOM200 0x1103 #define PCI_DEVICE_ID_PLX_DJINN_ITOO 0x1151 #define PCI_DEVICE_ID_PLX_R753 0x1152 +#define PCI_DEVICE_ID_PLX_9030 0x9030 #define PCI_DEVICE_ID_PLX_9050 0x9050 #define PCI_DEVICE_ID_PLX_9060 0x9060 #define PCI_DEVICE_ID_PLX_9060ES 0x906E @@ -1518,6 +1519,14 @@ #define PCI_VENDOR_ID_PDC 0x15e9 #define PCI_DEVICE_ID_PDC_1841 0x1841 +#define PCI_VENDOR_ID_MACROLINK 0x15ed +#define PCI_DEVICE_ID_MACROLINK_MCCS8 0x1000 +#define PCI_DEVICE_ID_MACROLINK_MCCS 0x1001 +#define PCI_DEVICE_ID_MACROLINK_MCCS8H 0x1002 +#define PCI_DEVICE_ID_MACROLINK_MCCSH 0x1003 +#define PCI_DEVICE_ID_MACROLINK_MCCR8 0x2000 +#define PCI_DEVICE_ID_MACROLINK_MCCR 0x2001 + #define PCI_VENDOR_ID_SYMPHONY 0x1c1c #define PCI_DEVICE_ID_SYMPHONY_101 0x0001 diff -urN -X dontdiff.txt linux-2.4.18-pre9/include/linux/serial.h pre9-ml/include/linux/serial.h --- linux-2.4.18-pre9/include/linux/serial.h Mon Feb 11 13:34:57 2002 +++ pre9-ml/include/linux/serial.h Mon Feb 11 15:02:06 2002 @@ -142,7 +142,8 @@ #define ASYNC_CONS_FLOW 0x00800000 /* flow control for console */ #define ASYNC_BOOT_ONLYMCA 0x00400000 /* Probe only if MCA bus */ -#define ASYNC_INTERNAL_FLAGS 0xFFC00000 /* Internal flags */ +#define ASYNC_FORCE_OUT2 0x00200000 /* Must always assert MCR OUT2 */ +#define ASYNC_INTERNAL_FLAGS 0xFFE00000 /* Internal flags */ /* * Multiport serial configuration structure --- external structure diff -urN -X dontdiff.txt linux-2.4.18-pre9/include/linux/serialP.h pre9-ml/include/linux/serialP.h --- linux-2.4.18-pre9/include/linux/serialP.h Mon Feb 11 13:36:16 2002 +++ pre9-ml/include/linux/serialP.h Mon Feb 11 15:02:06 2002 @@ -167,6 +167,7 @@ #define SPCI_FL_BASE2 0x0002 #define SPCI_FL_BASE3 0x0003 #define SPCI_FL_BASE4 0x0004 +#define SPCI_FL_BASE5 0x0005 #define SPCI_FL_GET_BASE(x) (x & SPCI_FL_BASE_MASK) #define SPCI_FL_IRQ_MASK (0x0007 << 4)