···2323#include <linux/pci.h>2424#include <linux/parport.h>2525#include <linux/parport_pc.h>2626-#include <linux/serial.h>2727-#include <linux/serialP.h>2828-#include <linux/list.h>2926#include <linux/8250_pci.h>3030-3131-#include <asm/serial.h>32273328enum parport_pc_pci_cards {3429 titan_110l = 0,···163168};164169MODULE_DEVICE_TABLE(pci,parport_serial_pci_tbl);165170166166-struct pci_board_no_ids {167167- int flags;168168- int num_ports;169169- int base_baud;170170- int uart_offset;171171- int reg_shift;172172- int (*init_fn)(struct pci_dev *dev, struct pci_board_no_ids *board,173173- int enable);174174- int first_uart_offset;175175-};176176-177177-static int __devinit siig10x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)178178-{179179- return pci_siig10x_fn(dev, enable);180180-}181181-182182-static int __devinit siig20x_init_fn(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)183183-{184184- return pci_siig20x_fn(dev, enable);185185-}186186-187187-static int __devinit netmos_serial_init(struct pci_dev *dev, struct pci_board_no_ids *board, int enable)188188-{189189- board->num_ports = dev->subsystem_device & 0xf;190190- return 0;191191-}192192-193193-static struct pci_board_no_ids pci_boards[] __devinitdata = {194194- /*195195- * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,196196- * Offset to get to next UART's registers,197197- * Register shift to use for memory-mapped I/O,198198- * Initialization function, first UART offset199199- */200200-201201-// Cards not tested are marked n/t202202-// If you have one of these cards and it works for you, please tell me..203203-204204-/* titan_110l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },205205-/* titan_210l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },206206-/* netmos_9xx5_combo */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },207207-/* netmos_9855 */ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },208208-/* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },209209-/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },210210-/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },211211-/* avlab_1s2p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },212212-/* avlab_1s2p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },213213-/* avlab_1s2p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },214214-/* avlab_2s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },215215-/* avlab_2s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },216216-/* avlab_2s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 },217217-/* siig_1s1p_10x */ { SPCI_FL_BASE2, 1, 460800, 0, 0, siig10x_init_fn },218218-/* siig_2s1p_10x */ { SPCI_FL_BASE2, 1, 921600, 0, 0, siig10x_init_fn },219219-/* siig_2p1s_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },220220-/* siig_1s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },221221-/* siig_2s1p_20x */ { SPCI_FL_BASE0, 1, 921600, 0, 0, siig20x_init_fn },171171+/*172172+ * This table describes the serial "geometry" of these boards. Any173173+ * quirks for these can be found in drivers/serial/8250_pci.c174174+ *175175+ * Cards not tested are marked n/t176176+ * If you have one of these cards and it works for you, please tell me..177177+ */178178+static struct pciserial_board pci_parport_serial_boards[] __devinitdata = {179179+ [titan_110l] = {180180+ .flags = FL_BASE1 | FL_BASE_BARS,181181+ .num_ports = 1,182182+ .base_baud = 921600,183183+ .uart_offset = 8,184184+ },185185+ [titan_210l] = {186186+ .flags = FL_BASE1 | FL_BASE_BARS,187187+ .num_ports = 2,188188+ .base_baud = 921600,189189+ .uart_offset = 8,190190+ },191191+ [netmos_9xx5_combo] = {192192+ .flags = FL_BASE0 | FL_BASE_BARS,193193+ .num_ports = 1,194194+ .base_baud = 115200,195195+ .uart_offset = 8,196196+ },197197+ [netmos_9855] = {198198+ .flags = FL_BASE2 | FL_BASE_BARS,199199+ .num_ports = 1,200200+ .base_baud = 115200,201201+ .uart_offset = 8,202202+ },203203+ [avlab_1s1p] = { /* n/t */204204+ .flags = FL_BASE0 | FL_BASE_BARS,205205+ .num_ports = 1,206206+ .base_baud = 115200,207207+ .uart_offset = 8,208208+ },209209+ [avlab_1s1p_650] = { /* nt */210210+ .flags = FL_BASE0 | FL_BASE_BARS,211211+ .num_ports = 1,212212+ .base_baud = 115200,213213+ .uart_offset = 8,214214+ },215215+ [avlab_1s1p_850] = { /* nt */216216+ .flags = FL_BASE0 | FL_BASE_BARS,217217+ .num_ports = 1,218218+ .base_baud = 115200,219219+ .uart_offset = 8,220220+ },221221+ [avlab_1s2p] = { /* n/t */222222+ .flags = FL_BASE0 | FL_BASE_BARS,223223+ .num_ports = 1,224224+ .base_baud = 115200,225225+ .uart_offset = 8,226226+ },227227+ [avlab_1s2p_650] = { /* nt */228228+ .flags = FL_BASE0 | FL_BASE_BARS,229229+ .num_ports = 1,230230+ .base_baud = 115200,231231+ .uart_offset = 8,232232+ },233233+ [avlab_1s2p_850] = { /* nt */234234+ .flags = FL_BASE0 | FL_BASE_BARS,235235+ .num_ports = 1,236236+ .base_baud = 115200,237237+ .uart_offset = 8,238238+ },239239+ [avlab_2s1p] = { /* n/t */240240+ .flags = FL_BASE0 | FL_BASE_BARS,241241+ .num_ports = 2,242242+ .base_baud = 115200,243243+ .uart_offset = 8,244244+ },245245+ [avlab_2s1p_650] = { /* nt */246246+ .flags = FL_BASE0 | FL_BASE_BARS,247247+ .num_ports = 2,248248+ .base_baud = 115200,249249+ .uart_offset = 8,250250+ },251251+ [avlab_2s1p_850] = { /* nt */252252+ .flags = FL_BASE0 | FL_BASE_BARS,253253+ .num_ports = 2,254254+ .base_baud = 115200,255255+ .uart_offset = 8,256256+ },257257+ [siig_1s1p_10x] = {258258+ .flags = FL_BASE2,259259+ .num_ports = 1,260260+ .base_baud = 460800,261261+ .uart_offset = 8,262262+ },263263+ [siig_2s1p_10x] = {264264+ .flags = FL_BASE2,265265+ .num_ports = 1,266266+ .base_baud = 921600,267267+ .uart_offset = 8,268268+ },269269+ [siig_2p1s_20x] = {270270+ .flags = FL_BASE0,271271+ .num_ports = 1,272272+ .base_baud = 921600,273273+ .uart_offset = 8,274274+ },275275+ [siig_1s1p_20x] = {276276+ .flags = FL_BASE0,277277+ .num_ports = 1,278278+ .base_baud = 921600,279279+ .uart_offset = 8,280280+ },281281+ [siig_2s1p_20x] = {282282+ .flags = FL_BASE0,283283+ .num_ports = 1,284284+ .base_baud = 921600,285285+ .uart_offset = 8,286286+ },222287};223288224289struct parport_serial_private {225225- int num_ser;226226- int line[20];227227- struct pci_board_no_ids ser;290290+ struct serial_private *serial;228291 int num_par;229292 struct parport *port[PARPORT_MAX];230293 struct parport_pc_pci par;231294};232295233233-static int __devinit get_pci_port (struct pci_dev *dev,234234- struct pci_board_no_ids *board,235235- struct serial_struct *req,236236- int idx)237237-{238238- unsigned long port;239239- int base_idx;240240- int max_port;241241- int offset;242242-243243- base_idx = SPCI_FL_GET_BASE(board->flags);244244- if (board->flags & SPCI_FL_BASE_TABLE)245245- base_idx += idx;246246-247247- if (board->flags & SPCI_FL_REGION_SZ_CAP) {248248- max_port = pci_resource_len(dev, base_idx) / 8;249249- if (idx >= max_port)250250- return 1;251251- }252252-253253- offset = board->first_uart_offset;254254-255255- /* Timedia/SUNIX uses a mixture of BARs and offsets */256256- /* Ugh, this is ugly as all hell --- TYT */257257- if(dev->vendor == PCI_VENDOR_ID_TIMEDIA ) /* 0x1409 */258258- switch(idx) {259259- case 0: base_idx=0;260260- break;261261- case 1: base_idx=0; offset=8;262262- break;263263- case 2: base_idx=1; 264264- break;265265- case 3: base_idx=1; offset=8;266266- break;267267- case 4: /* BAR 2*/268268- case 5: /* BAR 3 */269269- case 6: /* BAR 4*/270270- case 7: base_idx=idx-2; /* BAR 5*/271271- }272272-273273- port = pci_resource_start(dev, base_idx) + offset;274274-275275- if ((board->flags & SPCI_FL_BASE_TABLE) == 0)276276- port += idx * (board->uart_offset ? board->uart_offset : 8);277277-278278- if (pci_resource_flags (dev, base_idx) & IORESOURCE_IO) {279279- int high_bits_offset = ((sizeof(long)-sizeof(int))*8);280280- req->port = port;281281- if (high_bits_offset)282282- req->port_high = port >> high_bits_offset;283283- else284284- req->port_high = 0;285285- return 0;286286- }287287- req->io_type = SERIAL_IO_MEM;288288- req->iomem_base = ioremap(port, board->uart_offset);289289- req->iomem_reg_shift = board->reg_shift;290290- req->port = 0;291291- return req->iomem_base ? 0 : 1;292292-}293293-294296/* Register the serial port(s) of a PCI card. */295297static int __devinit serial_register (struct pci_dev *dev,296298 const struct pci_device_id *id)297299{298298- struct pci_board_no_ids *board;299300 struct parport_serial_private *priv = pci_get_drvdata (dev);300300- struct serial_struct serial_req;301301- int base_baud;302302- int k;303303- int success = 0;301301+ struct pciserial_board *board;302302+ struct serial_private *serial;304303305305- priv->ser = pci_boards[id->driver_data];306306- board = &priv->ser;307307- if (board->init_fn && ((board->init_fn) (dev, board, 1) != 0))308308- return 1;304304+ board = &pci_parport_serial_boards[id->driver_data];305305+ serial = pciserial_init_ports(dev, board);309306310310- base_baud = board->base_baud;311311- if (!base_baud)312312- base_baud = BASE_BAUD;313313- memset (&serial_req, 0, sizeof (serial_req));307307+ if (IS_ERR(serial))308308+ return PTR_ERR(serial);314309315315- for (k = 0; k < board->num_ports; k++) {316316- int line;317317-318318- if (priv->num_ser == ARRAY_SIZE (priv->line)) {319319- printk (KERN_WARNING320320- "parport_serial: %s: only %u serial lines "321321- "supported (%d reported)\n", pci_name (dev),322322- ARRAY_SIZE (priv->line), board->num_ports);323323- break;324324- }325325-326326- serial_req.irq = dev->irq;327327- if (get_pci_port (dev, board, &serial_req, k))328328- break;329329- serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;330330- serial_req.baud_base = base_baud;331331- line = register_serial (&serial_req);332332- if (line < 0) {333333- printk (KERN_DEBUG334334- "parport_serial: register_serial failed\n");335335- continue;336336- }337337- priv->line[priv->num_ser++] = line;338338- success = 1;339339- }340340-341341- return success ? 0 : 1;310310+ priv->serial = serial;311311+ return 0;342312}343313344314/* Register the parallel port(s) of a PCI card. */···371411 priv = kmalloc (sizeof *priv, GFP_KERNEL);372412 if (!priv)373413 return -ENOMEM;374374- priv->num_ser = priv->num_par = 0;414414+ memset(priv, 0, sizeof(struct parport_serial_private));375415 pci_set_drvdata (dev, priv);376416377417 err = pci_enable_device (dev);···404444 struct parport_serial_private *priv = pci_get_drvdata (dev);405445 int i;406446407407- // Serial ports408408- for (i = 0; i < priv->num_ser; i++) {409409- unregister_serial (priv->line[i]);447447+ pci_set_drvdata(dev, NULL);410448411411- if (priv->ser.init_fn)412412- (priv->ser.init_fn) (dev, &priv->ser, 0);413413- }414414- pci_set_drvdata (dev, NULL);415415-449449+ // Serial ports450450+ if (priv->serial)451451+ pciserial_remove_ports(priv->serial);452452+416453 // Parallel ports417454 for (i = 0; i < priv->num_par; i++)418455 parport_pc_unregister_port (priv->port[i]);···418461 return;419462}420463464464+static int parport_serial_pci_suspend(struct pci_dev *dev, pm_message_t state)465465+{466466+ struct parport_serial_private *priv = pci_get_drvdata(dev);467467+468468+ if (priv->serial)469469+ pciserial_suspend_ports(priv->serial);470470+471471+ /* FIXME: What about parport? */472472+473473+ pci_save_state(dev);474474+ pci_set_power_state(dev, pci_choose_state(dev, state));475475+ return 0;476476+}477477+478478+static int parport_serial_pci_resume(struct pci_dev *dev)479479+{480480+ struct parport_serial_private *priv = pci_get_drvdata(dev);481481+482482+ pci_set_power_state(dev, PCI_D0);483483+ pci_restore_state(dev);484484+485485+ /*486486+ * The device may have been disabled. Re-enable it.487487+ */488488+ pci_enable_device(dev);489489+490490+ if (priv->serial)491491+ pciserial_resume_ports(priv->serial);492492+493493+ /* FIXME: What about parport? */494494+495495+ return 0;496496+}497497+421498static struct pci_driver parport_serial_pci_driver = {422499 .name = "parport_serial",423500 .id_table = parport_serial_pci_tbl,424501 .probe = parport_serial_pci_probe,425502 .remove = __devexit_p(parport_serial_pci_remove),503503+ .suspend = parport_serial_pci_suspend,504504+ .resume = parport_serial_pci_resume,426505};427506428507
+191-311
drivers/serial/8250_pci.c
···3434#undef SERIAL_DEBUG_PCI35353636/*3737- * Definitions for PCI support.3838- */3939-#define FL_BASE_MASK 0x00074040-#define FL_BASE0 0x00004141-#define FL_BASE1 0x00014242-#define FL_BASE2 0x00024343-#define FL_BASE3 0x00034444-#define FL_BASE4 0x00044545-#define FL_GET_BASE(x) (x & FL_BASE_MASK)4646-4747-/* Use successive BARs (PCI base address registers),4848- else use offset into some specified BAR */4949-#define FL_BASE_BARS 0x00085050-5151-/* do not assign an irq */5252-#define FL_NOIRQ 0x00805353-5454-/* Use the Base address register size to cap number of ports */5555-#define FL_REGION_SZ_CAP 0x01005656-5757-struct pci_board {5858- unsigned int flags;5959- unsigned int num_ports;6060- unsigned int base_baud;6161- unsigned int uart_offset;6262- unsigned int reg_shift;6363- unsigned int first_offset;6464-};6565-6666-/*6737 * init function returns:6838 * > 0 - number of ports6939 * = 0 - use board->num_ports···4575 u32 subvendor;4676 u32 subdevice;4777 int (*init)(struct pci_dev *dev);4848- int (*setup)(struct pci_dev *dev, struct pci_board *board,4949- struct uart_port *port, int idx);7878+ int (*setup)(struct serial_private *, struct pciserial_board *,7979+ struct uart_port *, int);5080 void (*exit)(struct pci_dev *dev);5181};52825383#define PCI_NUM_BAR_RESOURCES 654845585struct serial_private {8686+ struct pci_dev *dev;5687 unsigned int nr;5788 void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES];5889 struct pci_serial_quirk *quirk;···72101}7310274103static int7575-setup_port(struct pci_dev *dev, struct uart_port *port,104104+setup_port(struct serial_private *priv, struct uart_port *port,76105 int bar, int offset, int regshift)77106{7878- struct serial_private *priv = pci_get_drvdata(dev);107107+ struct pci_dev *dev = priv->dev;79108 unsigned long base, len;8010981110 if (bar >= PCI_NUM_BAR_RESOURCES)82111 return -EINVAL;83112113113+ base = pci_resource_start(dev, bar);114114+84115 if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) {8585- base = pci_resource_start(dev, bar);86116 len = pci_resource_len(dev, bar);8711788118 if (!priv->remapped_bar[bar])···92120 return -ENOMEM;9312194122 port->iotype = UPIO_MEM;123123+ port->iobase = 0;95124 port->mapbase = base + offset;96125 port->membase = priv->remapped_bar[bar] + offset;97126 port->regshift = regshift;98127 } else {9999- base = pci_resource_start(dev, bar) + offset;100128 port->iotype = UPIO_PORT;101101- port->iobase = base;129129+ port->iobase = base + offset;130130+ port->mapbase = 0;131131+ port->membase = NULL;132132+ port->regshift = 0;102133 }103134 return 0;104135}···111136 * Not that ugly ;) -- HW112137 */113138static int114114-afavlab_setup(struct pci_dev *dev, struct pci_board *board,139139+afavlab_setup(struct serial_private *priv, struct pciserial_board *board,115140 struct uart_port *port, int idx)116141{117142 unsigned int bar, offset = board->first_offset;···124149 offset += (idx - 4) * board->uart_offset;125150 }126151127127- return setup_port(dev, port, bar, offset, board->reg_shift);152152+ return setup_port(priv, port, bar, offset, board->reg_shift);128153}129154130155/*···164189 * some serial ports are supposed to be hidden on certain models.165190 */166191static int167167-pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board,192192+pci_hp_diva_setup(struct serial_private *priv, struct pciserial_board *board,168193 struct uart_port *port, int idx)169194{170195 unsigned int offset = board->first_offset;171196 unsigned int bar = FL_GET_BASE(board->flags);172197173173- switch (dev->subsystem_device) {198198+ switch (priv->dev->subsystem_device) {174199 case PCI_DEVICE_ID_HP_DIVA_MAESTRO:175200 if (idx == 3)176201 idx++;···187212188213 offset += idx * board->uart_offset;189214190190- return setup_port(dev, port, bar, offset, board->reg_shift);215215+ return setup_port(priv, port, bar, offset, board->reg_shift);191216}192217193218/*···282307283308/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */284309static int285285-sbs_setup(struct pci_dev *dev, struct pci_board *board,310310+sbs_setup(struct serial_private *priv, struct pciserial_board *board,286311 struct uart_port *port, int idx)287312{288313 unsigned int bar, offset = board->first_offset;···298323 } else /* we have only 8 ports on PMC-OCTALPRO */299324 return 1;300325301301- return setup_port(dev, port, bar, offset, board->reg_shift);326326+ return setup_port(priv, port, bar, offset, board->reg_shift);302327}303328304329/*···364389 * - 10x cards have control registers in IO and/or memory space;365390 * - 20x cards have control registers in standard PCI configuration space.366391 *392392+ * Note: all 10x cards have PCI device ids 0x10..393393+ * all 20x cards have PCI device ids 0x20..394394+ *367395 * There are also Quartet Serial cards which use Oxford Semiconductor368396 * 16954 quad UART PCI chip clocked by 18.432 MHz quartz.369397 *···423445 return 0;424446}425447426426-int pci_siig10x_fn(struct pci_dev *dev, int enable)448448+static int pci_siig_init(struct pci_dev *dev)427449{428428- int ret = 0;429429- if (enable)430430- ret = pci_siig10x_init(dev);431431- return ret;432432-}450450+ unsigned int type = dev->device & 0xff00;433451434434-int pci_siig20x_fn(struct pci_dev *dev, int enable)435435-{436436- int ret = 0;437437- if (enable)438438- ret = pci_siig20x_init(dev);439439- return ret;440440-}452452+ if (type == 0x1000)453453+ return pci_siig10x_init(dev);454454+ else if (type == 0x2000)455455+ return pci_siig20x_init(dev);441456442442-EXPORT_SYMBOL(pci_siig10x_fn);443443-EXPORT_SYMBOL(pci_siig20x_fn);457457+ moan_device("Unknown SIIG card", dev);458458+ return -ENODEV;459459+}444460445461/*446462 * Timedia has an explosion of boards, and to avoid the PCI table from···495523 * Ugh, this is ugly as all hell --- TYT496524 */497525static int498498-pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,526526+pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board,499527 struct uart_port *port, int idx)500528{501529 unsigned int bar = 0, offset = board->first_offset;···521549 bar = idx - 2;522550 }523551524524- return setup_port(dev, port, bar, offset, board->reg_shift);552552+ return setup_port(priv, port, bar, offset, board->reg_shift);525553}526554527555/*528556 * Some Titan cards are also a little weird529557 */530558static int531531-titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board,559559+titan_400l_800l_setup(struct serial_private *priv,560560+ struct pciserial_board *board,532561 struct uart_port *port, int idx)533562{534563 unsigned int bar, offset = board->first_offset;···546573 offset = (idx - 2) * board->uart_offset;547574 }548575549549- return setup_port(dev, port, bar, offset, board->reg_shift);576576+ return setup_port(priv, port, bar, offset, board->reg_shift);550577}551578552579static int __devinit pci_xircom_init(struct pci_dev *dev)···566593}567594568595static int569569-pci_default_setup(struct pci_dev *dev, struct pci_board *board,596596+pci_default_setup(struct serial_private *priv, struct pciserial_board *board,570597 struct uart_port *port, int idx)571598{572599 unsigned int bar, offset = board->first_offset, maxnr;···577604 else578605 offset += idx * board->uart_offset;579606580580- maxnr = (pci_resource_len(dev, bar) - board->first_offset) /607607+ maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) /581608 (8 << board->reg_shift);582609583610 if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)584611 return 1;585612586586- return setup_port(dev, port, bar, offset, board->reg_shift);613613+ return setup_port(priv, port, bar, offset, board->reg_shift);587614}588615589616/* This should be in linux/pci_ids.h */···727754 .setup = sbs_setup,728755 .exit = __devexit_p(sbs_exit),729756 },730730-731757 /*732758 * SIIG cards.733733- * It is not clear whether these could be collapsed.734759 */735760 {736761 .vendor = PCI_VENDOR_ID_SIIG,737737- .device = PCI_DEVICE_ID_SIIG_1S_10x_550,762762+ .device = PCI_ANY_ID,738763 .subvendor = PCI_ANY_ID,739764 .subdevice = PCI_ANY_ID,740740- .init = pci_siig10x_init,741741- .setup = pci_default_setup,742742- },743743- {744744- .vendor = PCI_VENDOR_ID_SIIG,745745- .device = PCI_DEVICE_ID_SIIG_1S_10x_650,746746- .subvendor = PCI_ANY_ID,747747- .subdevice = PCI_ANY_ID,748748- .init = pci_siig10x_init,749749- .setup = pci_default_setup,750750- },751751- {752752- .vendor = PCI_VENDOR_ID_SIIG,753753- .device = PCI_DEVICE_ID_SIIG_1S_10x_850,754754- .subvendor = PCI_ANY_ID,755755- .subdevice = PCI_ANY_ID,756756- .init = pci_siig10x_init,757757- .setup = pci_default_setup,758758- },759759- {760760- .vendor = PCI_VENDOR_ID_SIIG,761761- .device = PCI_DEVICE_ID_SIIG_2S_10x_550,762762- .subvendor = PCI_ANY_ID,763763- .subdevice = PCI_ANY_ID,764764- .init = pci_siig10x_init,765765- .setup = pci_default_setup,766766- },767767- {768768- .vendor = PCI_VENDOR_ID_SIIG,769769- .device = PCI_DEVICE_ID_SIIG_2S_10x_650,770770- .subvendor = PCI_ANY_ID,771771- .subdevice = PCI_ANY_ID,772772- .init = pci_siig10x_init,773773- .setup = pci_default_setup,774774- },775775- {776776- .vendor = PCI_VENDOR_ID_SIIG,777777- .device = PCI_DEVICE_ID_SIIG_2S_10x_850,778778- .subvendor = PCI_ANY_ID,779779- .subdevice = PCI_ANY_ID,780780- .init = pci_siig10x_init,781781- .setup = pci_default_setup,782782- },783783- {784784- .vendor = PCI_VENDOR_ID_SIIG,785785- .device = PCI_DEVICE_ID_SIIG_4S_10x_550,786786- .subvendor = PCI_ANY_ID,787787- .subdevice = PCI_ANY_ID,788788- .init = pci_siig10x_init,789789- .setup = pci_default_setup,790790- },791791- {792792- .vendor = PCI_VENDOR_ID_SIIG,793793- .device = PCI_DEVICE_ID_SIIG_4S_10x_650,794794- .subvendor = PCI_ANY_ID,795795- .subdevice = PCI_ANY_ID,796796- .init = pci_siig10x_init,797797- .setup = pci_default_setup,798798- },799799- {800800- .vendor = PCI_VENDOR_ID_SIIG,801801- .device = PCI_DEVICE_ID_SIIG_4S_10x_850,802802- .subvendor = PCI_ANY_ID,803803- .subdevice = PCI_ANY_ID,804804- .init = pci_siig10x_init,805805- .setup = pci_default_setup,806806- },807807- {808808- .vendor = PCI_VENDOR_ID_SIIG,809809- .device = PCI_DEVICE_ID_SIIG_1S_20x_550,810810- .subvendor = PCI_ANY_ID,811811- .subdevice = PCI_ANY_ID,812812- .init = pci_siig20x_init,813813- .setup = pci_default_setup,814814- },815815- {816816- .vendor = PCI_VENDOR_ID_SIIG,817817- .device = PCI_DEVICE_ID_SIIG_1S_20x_650,818818- .subvendor = PCI_ANY_ID,819819- .subdevice = PCI_ANY_ID,820820- .init = pci_siig20x_init,821821- .setup = pci_default_setup,822822- },823823- {824824- .vendor = PCI_VENDOR_ID_SIIG,825825- .device = PCI_DEVICE_ID_SIIG_1S_20x_850,826826- .subvendor = PCI_ANY_ID,827827- .subdevice = PCI_ANY_ID,828828- .init = pci_siig20x_init,829829- .setup = pci_default_setup,830830- },831831- {832832- .vendor = PCI_VENDOR_ID_SIIG,833833- .device = PCI_DEVICE_ID_SIIG_2S_20x_550,834834- .subvendor = PCI_ANY_ID,835835- .subdevice = PCI_ANY_ID,836836- .init = pci_siig20x_init,837837- .setup = pci_default_setup,838838- },839839- { .vendor = PCI_VENDOR_ID_SIIG,840840- .device = PCI_DEVICE_ID_SIIG_2S_20x_650,841841- .subvendor = PCI_ANY_ID,842842- .subdevice = PCI_ANY_ID,843843- .init = pci_siig20x_init,844844- .setup = pci_default_setup,845845- },846846- {847847- .vendor = PCI_VENDOR_ID_SIIG,848848- .device = PCI_DEVICE_ID_SIIG_2S_20x_850,849849- .subvendor = PCI_ANY_ID,850850- .subdevice = PCI_ANY_ID,851851- .init = pci_siig20x_init,852852- .setup = pci_default_setup,853853- },854854- {855855- .vendor = PCI_VENDOR_ID_SIIG,856856- .device = PCI_DEVICE_ID_SIIG_4S_20x_550,857857- .subvendor = PCI_ANY_ID,858858- .subdevice = PCI_ANY_ID,859859- .init = pci_siig20x_init,860860- .setup = pci_default_setup,861861- },862862- {863863- .vendor = PCI_VENDOR_ID_SIIG,864864- .device = PCI_DEVICE_ID_SIIG_4S_20x_650,865865- .subvendor = PCI_ANY_ID,866866- .subdevice = PCI_ANY_ID,867867- .init = pci_siig20x_init,868868- .setup = pci_default_setup,869869- },870870- {871871- .vendor = PCI_VENDOR_ID_SIIG,872872- .device = PCI_DEVICE_ID_SIIG_4S_20x_850,873873- .subvendor = PCI_ANY_ID,874874- .subdevice = PCI_ANY_ID,875875- .init = pci_siig20x_init,765765+ .init = pci_siig_init,876766 .setup = pci_default_setup,877767 },878768 /*···826990}827991828992static _INLINE_ int829829-get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx)993993+get_pci_irq(struct pci_dev *dev, struct pciserial_board *board)830994{831995 if (board->flags & FL_NOIRQ)832996 return 0;···9511115 * see first lines of serial_in() and serial_out() in 8250.c9521116*/9531117954954-static struct pci_board pci_boards[] __devinitdata = {11181118+static struct pciserial_board pci_boards[] __devinitdata = {9551119 [pbn_default] = {9561120 .flags = FL_BASE0,9571121 .num_ports = 1,···14111575 * serial specs. Returns 0 on success, 1 on failure.14121576 */14131577static int __devinit14141414-serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)15781578+serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)14151579{14161580 int num_iomem, num_port, first_port = -1, i;14171581···14761640}1477164114781642static inline int14791479-serial_pci_matches(struct pci_board *board, struct pci_board *guessed)16431643+serial_pci_matches(struct pciserial_board *board,16441644+ struct pciserial_board *guessed)14801645{14811646 return14821647 board->num_ports == guessed->num_ports &&···14871650 board->first_offset == guessed->first_offset;14881651}1489165216531653+struct serial_private *16541654+pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board)16551655+{16561656+ struct uart_port serial_port;16571657+ struct serial_private *priv;16581658+ struct pci_serial_quirk *quirk;16591659+ int rc, nr_ports, i;16601660+16611661+ nr_ports = board->num_ports;16621662+16631663+ /*16641664+ * Find an init and setup quirks.16651665+ */16661666+ quirk = find_quirk(dev);16671667+16681668+ /*16691669+ * Run the new-style initialization function.16701670+ * The initialization function returns:16711671+ * <0 - error16721672+ * 0 - use board->num_ports16731673+ * >0 - number of ports16741674+ */16751675+ if (quirk->init) {16761676+ rc = quirk->init(dev);16771677+ if (rc < 0) {16781678+ priv = ERR_PTR(rc);16791679+ goto err_out;16801680+ }16811681+ if (rc)16821682+ nr_ports = rc;16831683+ }16841684+16851685+ priv = kmalloc(sizeof(struct serial_private) +16861686+ sizeof(unsigned int) * nr_ports,16871687+ GFP_KERNEL);16881688+ if (!priv) {16891689+ priv = ERR_PTR(-ENOMEM);16901690+ goto err_deinit;16911691+ }16921692+16931693+ memset(priv, 0, sizeof(struct serial_private) +16941694+ sizeof(unsigned int) * nr_ports);16951695+16961696+ priv->dev = dev;16971697+ priv->quirk = quirk;16981698+16991699+ memset(&serial_port, 0, sizeof(struct uart_port));17001700+ serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;17011701+ serial_port.uartclk = board->base_baud * 16;17021702+ serial_port.irq = get_pci_irq(dev, board);17031703+ serial_port.dev = &dev->dev;17041704+17051705+ for (i = 0; i < nr_ports; i++) {17061706+ if (quirk->setup(priv, board, &serial_port, i))17071707+ break;17081708+17091709+#ifdef SERIAL_DEBUG_PCI17101710+ printk("Setup PCI port: port %x, irq %d, type %d\n",17111711+ serial_port.iobase, serial_port.irq, serial_port.iotype);17121712+#endif17131713+17141714+ priv->line[i] = serial8250_register_port(&serial_port);17151715+ if (priv->line[i] < 0) {17161716+ printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);17171717+ break;17181718+ }17191719+ }17201720+17211721+ priv->nr = i;17221722+17231723+ return priv;17241724+17251725+ err_deinit:17261726+ if (quirk->exit)17271727+ quirk->exit(dev);17281728+ err_out:17291729+ return priv;17301730+}17311731+EXPORT_SYMBOL_GPL(pciserial_init_ports);17321732+17331733+void pciserial_remove_ports(struct serial_private *priv)17341734+{17351735+ struct pci_serial_quirk *quirk;17361736+ int i;17371737+17381738+ for (i = 0; i < priv->nr; i++)17391739+ serial8250_unregister_port(priv->line[i]);17401740+17411741+ for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {17421742+ if (priv->remapped_bar[i])17431743+ iounmap(priv->remapped_bar[i]);17441744+ priv->remapped_bar[i] = NULL;17451745+ }17461746+17471747+ /*17481748+ * Find the exit quirks.17491749+ */17501750+ quirk = find_quirk(priv->dev);17511751+ if (quirk->exit)17521752+ quirk->exit(priv->dev);17531753+17541754+ kfree(priv);17551755+}17561756+EXPORT_SYMBOL_GPL(pciserial_remove_ports);17571757+17581758+void pciserial_suspend_ports(struct serial_private *priv)17591759+{17601760+ int i;17611761+17621762+ for (i = 0; i < priv->nr; i++)17631763+ if (priv->line[i] >= 0)17641764+ serial8250_suspend_port(priv->line[i]);17651765+}17661766+EXPORT_SYMBOL_GPL(pciserial_suspend_ports);17671767+17681768+void pciserial_resume_ports(struct serial_private *priv)17691769+{17701770+ int i;17711771+17721772+ /*17731773+ * Ensure that the board is correctly configured.17741774+ */17751775+ if (priv->quirk->init)17761776+ priv->quirk->init(priv->dev);17771777+17781778+ for (i = 0; i < priv->nr; i++)17791779+ if (priv->line[i] >= 0)17801780+ serial8250_resume_port(priv->line[i]);17811781+}17821782+EXPORT_SYMBOL_GPL(pciserial_resume_ports);17831783+14901784/*14911785 * Probe one serial board. Unfortunately, there is no rhyme nor reason14921786 * to the arrangement of serial ports on a PCI card.···16261658pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)16271659{16281660 struct serial_private *priv;16291629- struct pci_board *board, tmp;16301630- struct pci_serial_quirk *quirk;16311631- int rc, nr_ports, i;16611661+ struct pciserial_board *board, tmp;16621662+ int rc;1632166316331664 if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {16341665 printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",···16461679 * Use a copy of the pci_board entry for this;16471680 * avoid changing entries in the table.16481681 */16491649- memcpy(&tmp, board, sizeof(struct pci_board));16821682+ memcpy(&tmp, board, sizeof(struct pciserial_board));16501683 board = &tmp;1651168416521685 /*···16621695 * detect this boards settings with our heuristic,16631696 * then we no longer need this entry.16641697 */16651665- memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board));16981698+ memcpy(&tmp, &pci_boards[pbn_default],16991699+ sizeof(struct pciserial_board));16661700 rc = serial_pci_guess_board(dev, &tmp);16671701 if (rc == 0 && serial_pci_matches(board, &tmp))16681702 moan_device("Redundant entry in serial pci_table.",16691703 dev);16701704 }1671170516721672- nr_ports = board->num_ports;16731673-16741674- /*16751675- * Find an init and setup quirks.16761676- */16771677- quirk = find_quirk(dev);16781678-16791679- /*16801680- * Run the new-style initialization function.16811681- * The initialization function returns:16821682- * <0 - error16831683- * 0 - use board->num_ports16841684- * >0 - number of ports16851685- */16861686- if (quirk->init) {16871687- rc = quirk->init(dev);16881688- if (rc < 0)16891689- goto disable;16901690- if (rc)16911691- nr_ports = rc;17061706+ priv = pciserial_init_ports(dev, board);17071707+ if (!IS_ERR(priv)) {17081708+ pci_set_drvdata(dev, priv);17091709+ return 0;16921710 }1693171116941694- priv = kmalloc(sizeof(struct serial_private) +16951695- sizeof(unsigned int) * nr_ports,16961696- GFP_KERNEL);16971697- if (!priv) {16981698- rc = -ENOMEM;16991699- goto deinit;17001700- }17121712+ rc = PTR_ERR(priv);1701171317021702- memset(priv, 0, sizeof(struct serial_private) +17031703- sizeof(unsigned int) * nr_ports);17041704-17051705- priv->quirk = quirk;17061706- pci_set_drvdata(dev, priv);17071707-17081708- for (i = 0; i < nr_ports; i++) {17091709- struct uart_port serial_port;17101710- memset(&serial_port, 0, sizeof(struct uart_port));17111711-17121712- serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF |17131713- UPF_SHARE_IRQ;17141714- serial_port.uartclk = board->base_baud * 16;17151715- serial_port.irq = get_pci_irq(dev, board, i);17161716- serial_port.dev = &dev->dev;17171717- if (quirk->setup(dev, board, &serial_port, i))17181718- break;17191719-#ifdef SERIAL_DEBUG_PCI17201720- printk("Setup PCI port: port %x, irq %d, type %d\n",17211721- serial_port.iobase, serial_port.irq, serial_port.iotype);17221722-#endif17231723-17241724- priv->line[i] = serial8250_register_port(&serial_port);17251725- if (priv->line[i] < 0) {17261726- printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]);17271727- break;17281728- }17291729- }17301730-17311731- priv->nr = i;17321732-17331733- return 0;17341734-17351735- deinit:17361736- if (quirk->exit)17371737- quirk->exit(dev);17381714 disable:17391715 pci_disable_device(dev);17401716 return rc;···16861776static void __devexit pciserial_remove_one(struct pci_dev *dev)16871777{16881778 struct serial_private *priv = pci_get_drvdata(dev);16891689- struct pci_serial_quirk *quirk;16901690- int i;1691177916921780 pci_set_drvdata(dev, NULL);1693178116941694- for (i = 0; i < priv->nr; i++)16951695- serial8250_unregister_port(priv->line[i]);16961696-16971697- for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {16981698- if (priv->remapped_bar[i])16991699- iounmap(priv->remapped_bar[i]);17001700- priv->remapped_bar[i] = NULL;17011701- }17021702-17031703- /*17041704- * Find the exit quirks.17051705- */17061706- quirk = find_quirk(dev);17071707- if (quirk->exit)17081708- quirk->exit(dev);17821782+ pciserial_remove_ports(priv);1709178317101784 pci_disable_device(dev);17111711-17121712- kfree(priv);17131785}1714178617151787static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)17161788{17171789 struct serial_private *priv = pci_get_drvdata(dev);1718179017191719- if (priv) {17201720- int i;17911791+ if (priv)17921792+ pciserial_suspend_ports(priv);1721179317221722- for (i = 0; i < priv->nr; i++)17231723- serial8250_suspend_port(priv->line[i]);17241724- }17251794 pci_save_state(dev);17261795 pci_set_power_state(dev, pci_choose_state(dev, state));17271796 return 0;···17141825 pci_restore_state(dev);1715182617161827 if (priv) {17171717- int i;17181718-17191828 /*17201829 * The device may have been disabled. Re-enable it.17211830 */17221831 pci_enable_device(dev);1723183217241724- /*17251725- * Ensure that the board is correctly configured.17261726- */17271727- if (priv->quirk->init)17281728- priv->quirk->init(dev);17291729-17301730- for (i = 0; i < priv->nr; i++)17311731- serial8250_resume_port(priv->line[i]);18331833+ pciserial_resume_ports(priv);17321834 }17331835 return 0;17341836}
+37-2
include/linux/8250_pci.h
···11-int pci_siig10x_fn(struct pci_dev *dev, int enable);22-int pci_siig20x_fn(struct pci_dev *dev, int enable);11+/*22+ * Definitions for PCI support.33+ */44+#define FL_BASE_MASK 0x000755+#define FL_BASE0 0x000066+#define FL_BASE1 0x000177+#define FL_BASE2 0x000288+#define FL_BASE3 0x000399+#define FL_BASE4 0x00041010+#define FL_GET_BASE(x) (x & FL_BASE_MASK)1111+1212+/* Use successive BARs (PCI base address registers),1313+ else use offset into some specified BAR */1414+#define FL_BASE_BARS 0x00081515+1616+/* do not assign an irq */1717+#define FL_NOIRQ 0x00801818+1919+/* Use the Base address register size to cap number of ports */2020+#define FL_REGION_SZ_CAP 0x01002121+2222+struct pciserial_board {2323+ unsigned int flags;2424+ unsigned int num_ports;2525+ unsigned int base_baud;2626+ unsigned int uart_offset;2727+ unsigned int reg_shift;2828+ unsigned int first_offset;2929+};3030+3131+struct serial_private;3232+3333+struct serial_private *3434+pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board);3535+void pciserial_remove_ports(struct serial_private *priv);3636+void pciserial_suspend_ports(struct serial_private *priv);3737+void pciserial_resume_ports(struct serial_private *priv);
-40
include/linux/serialP.h
···140140#define ALPHA_KLUDGE_MCR 0141141#endif142142143143-/*144144- * Definitions for PCI support.145145- */146146-#define SPCI_FL_BASE_MASK 0x0007147147-#define SPCI_FL_BASE0 0x0000148148-#define SPCI_FL_BASE1 0x0001149149-#define SPCI_FL_BASE2 0x0002150150-#define SPCI_FL_BASE3 0x0003151151-#define SPCI_FL_BASE4 0x0004152152-#define SPCI_FL_GET_BASE(x) (x & SPCI_FL_BASE_MASK)153153-154154-#define SPCI_FL_IRQ_MASK (0x0007 << 4)155155-#define SPCI_FL_IRQBASE0 (0x0000 << 4)156156-#define SPCI_FL_IRQBASE1 (0x0001 << 4)157157-#define SPCI_FL_IRQBASE2 (0x0002 << 4)158158-#define SPCI_FL_IRQBASE3 (0x0003 << 4)159159-#define SPCI_FL_IRQBASE4 (0x0004 << 4)160160-#define SPCI_FL_GET_IRQBASE(x) ((x & SPCI_FL_IRQ_MASK) >> 4)161161-162162-/* Use successive BARs (PCI base address registers), 163163- else use offset into some specified BAR */164164-#define SPCI_FL_BASE_TABLE 0x0100165165-166166-/* Use successive entries in the irq resource table */167167-#define SPCI_FL_IRQ_TABLE 0x0200168168-169169-/* Use the irq resource table instead of dev->irq */170170-#define SPCI_FL_IRQRESOURCE 0x0400171171-172172-/* Use the Base address register size to cap number of ports */173173-#define SPCI_FL_REGION_SZ_CAP 0x0800174174-175175-/* Do not use irq sharing for this device */176176-#define SPCI_FL_NO_SHIRQ 0x1000177177-178178-/* This is a PNP device */179179-#define SPCI_FL_ISPNP 0x2000180180-181181-#define SPCI_FL_PNPDEFAULT (SPCI_FL_IRQRESOURCE|SPCI_FL_ISPNP)182182-183143#endif /* _LINUX_SERIAL_H */