diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 7088373efc153945acbba9e5277462ba81c2c5ed..e71a28b4b94ebaa7804e8ffd7bacb44fc892c022 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1029,11 +1029,11 @@ config SERIAL_VR41XX_CONSOLE a console on a serial port, say Y. Otherwise, say N. config SERIAL_JSM - tristate "Digi International NEO PCI Support" + tristate "Digi International NEO and Classic PCI Support" depends on PCI select SERIAL_CORE help - This is a driver for Digi International's Neo series + This is a driver for Digi International's Neo and Classic series of cards which provide multiple serial ports. You would need something like this to connect more than two modems to your Linux box, for instance in order to become a dial-in server. This driver diff --git a/drivers/tty/serial/jsm/jsm.h b/drivers/tty/serial/jsm/jsm.h index 30942827357130245ee636d677ffbca9997f2083..662523d66704208d975c184e772b2e8f2f873435 100644 --- a/drivers/tty/serial/jsm/jsm.h +++ b/drivers/tty/serial/jsm/jsm.h @@ -68,6 +68,10 @@ do { \ #define MAX_STOPS_SENT 5 /* Board ids */ +#define PCI_DEVICE_ID_CLASSIC_4 0x0028 +#define PCI_DEVICE_ID_CLASSIC_8 0x0029 +#define PCI_DEVICE_ID_CLASSIC_4_422 0x00D0 +#define PCI_DEVICE_ID_CLASSIC_8_422 0x00D1 #define PCI_DEVICE_ID_NEO_4 0x00B0 #define PCI_DEVICE_ID_NEO_1_422 0x00CC #define PCI_DEVICE_ID_NEO_1_422_485 0x00CD diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c index d2885a7bb090c4d6ecc2a59e0038e0302d076462..0927ddf3d071bb8062ac7bdd4faf80f2207bba93 100644 --- a/drivers/tty/serial/jsm/jsm_driver.c +++ b/drivers/tty/serial/jsm/jsm_driver.c @@ -31,8 +31,7 @@ #include "jsm.h" MODULE_AUTHOR("Digi International, http://www.digi.com"); -MODULE_DESCRIPTION("Driver for the Digi International " - "Neo PCI based product line"); +MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line"); MODULE_LICENSE("GPL"); MODULE_SUPPORTED_DEVICE("jsm"); @@ -50,7 +49,7 @@ struct uart_driver jsm_uart_driver = { }; static pci_ers_result_t jsm_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state); + pci_channel_state_t state); static pci_ers_result_t jsm_io_slot_reset(struct pci_dev *pdev); static void jsm_io_resume(struct pci_dev *pdev); @@ -68,7 +67,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) { int rc = 0; struct jsm_board *brd; - static int adapter_count = 0; + static int adapter_count; rc = pci_enable_device(pdev); if (rc) { @@ -82,10 +81,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_disable_device; } - brd = kzalloc(sizeof(struct jsm_board), GFP_KERNEL); + brd = kzalloc(sizeof(*brd), GFP_KERNEL); if (!brd) { - dev_err(&pdev->dev, - "memory allocation for board structure failed\n"); rc = -ENOMEM; goto out_release_regions; } @@ -95,7 +92,6 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) brd->pci_dev = pdev; switch (pdev->device) { - case PCI_DEVICE_ID_NEO_2DB9: case PCI_DEVICE_ID_NEO_2DB9PRI: case PCI_DEVICE_ID_NEO_2RJ45: @@ -104,6 +100,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) brd->maxports = 2; break; + case PCI_DEVICE_ID_CLASSIC_4: + case PCI_DEVICE_ID_CLASSIC_4_422: case PCI_DEVICE_ID_NEO_4: case PCIE_DEVICE_ID_NEO_4: case PCIE_DEVICE_ID_NEO_4RJ45: @@ -111,6 +109,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) brd->maxports = 4; break; + case PCI_DEVICE_ID_CLASSIC_8: + case PCI_DEVICE_ID_CLASSIC_8_422: case PCI_DEVICE_ID_DIGI_NEO_8: case PCIE_DEVICE_ID_NEO_8: case PCIE_DEVICE_ID_NEO_8RJ45: @@ -129,36 +129,109 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) brd->irq = pdev->irq; - jsm_dbg(INIT, &brd->pci_dev, "jsm_found_board - NEO adapter\n"); + switch (pdev->device) { + case PCI_DEVICE_ID_CLASSIC_4: + case PCI_DEVICE_ID_CLASSIC_4_422: + case PCI_DEVICE_ID_CLASSIC_8: + case PCI_DEVICE_ID_CLASSIC_8_422: + + jsm_dbg(INIT, &brd->pci_dev, + "jsm_found_board - Classic adapter\n"); + + /* + * For PCI ClassicBoards + * PCI Local Address (.i.e. "resource" number) space + * 0 PLX Memory Mapped Config + * 1 PLX I/O Mapped Config + * 2 I/O Mapped UARTs and Status + * 3 Memory Mapped VPD + * 4 Memory Mapped UARTs and Status + */ + + /* Get the PCI Base Address Registers */ + brd->membase = pci_resource_start(pdev, 4); + brd->membase_end = pci_resource_end(pdev, 4); + + if (brd->membase & 0x1) + brd->membase &= ~0x3; + else + brd->membase &= ~0xF; + + brd->iobase = pci_resource_start(pdev, 1); + brd->iobase_end = pci_resource_end(pdev, 1); + brd->iobase = ((unsigned int)(brd->iobase)) & 0xFFFE; + + /* Assign the board_ops struct */ + brd->bd_ops = &jsm_cls_ops; + + brd->bd_uart_offset = 0x8; + brd->bd_dividend = 921600; + + brd->re_map_membase = ioremap(brd->membase, + pci_resource_len(pdev, 4)); + if (!brd->re_map_membase) { + dev_err(&pdev->dev, + "Card has no PCI Memory resources, failing board.\n"); + rc = -ENOMEM; + goto out_kfree_brd; + } - /* get the PCI Base Address Registers */ - brd->membase = pci_resource_start(pdev, 0); - brd->membase_end = pci_resource_end(pdev, 0); + /* + * Enable Local Interrupt 1 (0x1), + * Local Interrupt 1 Polarity Active high (0x2), + * Enable PCI interrupt (0x43) + */ + outb(0x43, brd->iobase + 0x4c); - if (brd->membase & 1) - brd->membase &= ~3; - else - brd->membase &= ~15; + break; - /* Assign the board_ops struct */ - brd->bd_ops = &jsm_neo_ops; + case PCI_DEVICE_ID_NEO_2DB9: + case PCI_DEVICE_ID_NEO_2DB9PRI: + case PCI_DEVICE_ID_NEO_2RJ45: + case PCI_DEVICE_ID_NEO_2RJ45PRI: + case PCI_DEVICE_ID_NEO_2_422_485: + case PCI_DEVICE_ID_NEO_4: + case PCIE_DEVICE_ID_NEO_4: + case PCIE_DEVICE_ID_NEO_4RJ45: + case PCIE_DEVICE_ID_NEO_4_IBM: + case PCI_DEVICE_ID_DIGI_NEO_8: + case PCIE_DEVICE_ID_NEO_8: + case PCIE_DEVICE_ID_NEO_8RJ45: - brd->bd_uart_offset = 0x200; - brd->bd_dividend = 921600; + jsm_dbg(INIT, &brd->pci_dev, "jsm_found_board - NEO adapter\n"); - brd->re_map_membase = ioremap(brd->membase, pci_resource_len(pdev, 0)); - if (!brd->re_map_membase) { - dev_err(&pdev->dev, - "card has no PCI Memory resources, " - "failing board.\n"); - rc = -ENOMEM; - goto out_kfree_brd; + /* get the PCI Base Address Registers */ + brd->membase = pci_resource_start(pdev, 0); + brd->membase_end = pci_resource_end(pdev, 0); + + if (brd->membase & 1) + brd->membase &= ~0x3; + else + brd->membase &= ~0xF; + + /* Assign the board_ops struct */ + brd->bd_ops = &jsm_neo_ops; + + brd->bd_uart_offset = 0x200; + brd->bd_dividend = 921600; + + brd->re_map_membase = ioremap(brd->membase, + pci_resource_len(pdev, 0)); + if (!brd->re_map_membase) { + dev_err(&pdev->dev, + "Card has no PCI Memory resources, failing board.\n"); + rc = -ENOMEM; + goto out_kfree_brd; + } + + break; + default: + return -ENXIO; } - rc = request_irq(brd->irq, brd->bd_ops->intr, - IRQF_SHARED, "JSM", brd); + rc = request_irq(brd->irq, brd->bd_ops->intr, IRQF_SHARED, "JSM", brd); if (rc) { - printk(KERN_WARNING "Failed to hook IRQ %d\n",brd->irq); + dev_warn(&pdev->dev, "Failed to hook IRQ %d\n", brd->irq); goto out_iounmap; } @@ -178,7 +251,7 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* Log the information about the board */ - dev_info(&pdev->dev, "board %d: Digi Neo (rev %d), irq %d\n", + dev_info(&pdev->dev, "board %d: Digi Classic/Neo (rev %d), irq %d\n", adapter_count, brd->rev, brd->irq); pci_set_drvdata(pdev, brd); @@ -205,6 +278,18 @@ static void jsm_remove_one(struct pci_dev *pdev) struct jsm_board *brd = pci_get_drvdata(pdev); int i = 0; + switch (pdev->device) { + case PCI_DEVICE_ID_CLASSIC_4: + case PCI_DEVICE_ID_CLASSIC_4_422: + case PCI_DEVICE_ID_CLASSIC_8: + case PCI_DEVICE_ID_CLASSIC_8_422: + /* Tell card not to interrupt anymore. */ + outb(0x0, brd->iobase + 0x4c); + break; + default: + break; + } + jsm_remove_uart_port(brd); free_irq(brd->irq, brd); @@ -239,6 +324,10 @@ static struct pci_device_id jsm_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4), 0, 0, 11 }, { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4RJ45), 0, 0, 12 }, { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_8RJ45), 0, 0, 13 }, + { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_4), 0, 0, 14 }, + { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_4_422), 0, 0, 15 }, + { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_8), 0, 0, 16 }, + { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_CLASSIC_8_422), 0, 0, 17 }, { 0, } }; MODULE_DEVICE_TABLE(pci, jsm_pci_tbl); diff --git a/drivers/tty/serial/jsm/jsm_tty.c b/drivers/tty/serial/jsm/jsm_tty.c index 8814680630a43dd979ccff431c3ef60876ce42de..4259e5af8467e13198867fcd46e10223122ff7a4 100644 --- a/drivers/tty/serial/jsm/jsm_tty.c +++ b/drivers/tty/serial/jsm/jsm_tty.c @@ -425,6 +425,8 @@ int jsm_tty_init(struct jsm_board *brd) if (brd->bd_uart_offset == 0x200) ch->ch_neo_uart = vaddr + (brd->bd_uart_offset * i); + else + ch->ch_cls_uart = vaddr + (brd->bd_uart_offset * i); ch->ch_bd = brd; ch->ch_portnum = i;