8250_pci.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,238 行 · 第 1/4 页

C
2,238
字号
		.flags		= FL_BASE0,		.num_ports	= 1,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b0_2_921600] = {		.flags		= FL_BASE0,		.num_ports	= 2,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b0_4_921600] = {		.flags		= FL_BASE0,		.num_ports	= 4,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b0_bt_1_115200] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 1,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b0_bt_2_115200] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 2,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b0_bt_8_115200] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 8,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b0_bt_1_460800] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 1,		.base_baud	= 460800,		.uart_offset	= 8,	},	[pbn_b0_bt_2_460800] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 2,		.base_baud	= 460800,		.uart_offset	= 8,	},	[pbn_b0_bt_4_460800] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 4,		.base_baud	= 460800,		.uart_offset	= 8,	},	[pbn_b0_bt_1_921600] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 1,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b0_bt_2_921600] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 2,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b0_bt_4_921600] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 4,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b0_bt_8_921600] = {		.flags		= FL_BASE0|FL_BASE_BARS,		.num_ports	= 8,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b1_1_115200] = {		.flags		= FL_BASE1,		.num_ports	= 1,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b1_2_115200] = {		.flags		= FL_BASE1,		.num_ports	= 2,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b1_4_115200] = {		.flags		= FL_BASE1,		.num_ports	= 4,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b1_8_115200] = {		.flags		= FL_BASE1,		.num_ports	= 8,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b1_1_921600] = {		.flags		= FL_BASE1,		.num_ports	= 1,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b1_2_921600] = {		.flags		= FL_BASE1,		.num_ports	= 2,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b1_4_921600] = {		.flags		= FL_BASE1,		.num_ports	= 4,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b1_8_921600] = {		.flags		= FL_BASE1,		.num_ports	= 8,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b1_bt_2_921600] = {		.flags		= FL_BASE1|FL_BASE_BARS,		.num_ports	= 2,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b1_2_1382400] = {		.flags		= FL_BASE1,		.num_ports	= 2,		.base_baud	= 1382400,		.uart_offset	= 8,	},	[pbn_b1_4_1382400] = {		.flags		= FL_BASE1,		.num_ports	= 4,		.base_baud	= 1382400,		.uart_offset	= 8,	},	[pbn_b1_8_1382400] = {		.flags		= FL_BASE1,		.num_ports	= 8,		.base_baud	= 1382400,		.uart_offset	= 8,	},	[pbn_b2_1_115200] = {		.flags		= FL_BASE2,		.num_ports	= 1,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b2_8_115200] = {		.flags		= FL_BASE2,		.num_ports	= 8,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b2_1_460800] = {		.flags		= FL_BASE2,		.num_ports	= 1,		.base_baud	= 460800,		.uart_offset	= 8,	},	[pbn_b2_4_460800] = {		.flags		= FL_BASE2,		.num_ports	= 4,		.base_baud	= 460800,		.uart_offset	= 8,	},	[pbn_b2_8_460800] = {		.flags		= FL_BASE2,		.num_ports	= 8,		.base_baud	= 460800,		.uart_offset	= 8,	},	[pbn_b2_16_460800] = {		.flags		= FL_BASE2,		.num_ports	= 16,		.base_baud	= 460800,		.uart_offset	= 8,	 },	[pbn_b2_1_921600] = {		.flags		= FL_BASE2,		.num_ports	= 1,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b2_4_921600] = {		.flags		= FL_BASE2,		.num_ports	= 4,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b2_8_921600] = {		.flags		= FL_BASE2,		.num_ports	= 8,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b2_bt_1_115200] = {		.flags		= FL_BASE2|FL_BASE_BARS,		.num_ports	= 1,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b2_bt_2_115200] = {		.flags		= FL_BASE2|FL_BASE_BARS,		.num_ports	= 2,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b2_bt_4_115200] = {		.flags		= FL_BASE2|FL_BASE_BARS,		.num_ports	= 4,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b2_bt_2_921600] = {		.flags		= FL_BASE2|FL_BASE_BARS,		.num_ports	= 2,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b2_bt_4_921600] = {		.flags		= FL_BASE2|FL_BASE_BARS,		.num_ports	= 4,		.base_baud	= 921600,		.uart_offset	= 8,	},	[pbn_b3_4_115200] = {		.flags		= FL_BASE3,		.num_ports	= 4,		.base_baud	= 115200,		.uart_offset	= 8,	},	[pbn_b3_8_115200] = {		.flags		= FL_BASE3,		.num_ports	= 8,		.base_baud	= 115200,		.uart_offset	= 8,	},	/*	 * Entries following this are board-specific.	 */	/*	 * Panacom - IOMEM	 */	[pbn_panacom] = {		.flags		= FL_BASE2,		.num_ports	= 2,		.base_baud	= 921600,		.uart_offset	= 0x400,		.reg_shift	= 7,	},	[pbn_panacom2] = {		.flags		= FL_BASE2|FL_BASE_BARS,		.num_ports	= 2,		.base_baud	= 921600,		.uart_offset	= 0x400,		.reg_shift	= 7,	},	[pbn_panacom4] = {		.flags		= FL_BASE2|FL_BASE_BARS,		.num_ports	= 4,		.base_baud	= 921600,		.uart_offset	= 0x400,		.reg_shift	= 7,	},	/* I think this entry is broken - the first_offset looks wrong --rmk */	[pbn_plx_romulus] = {		.flags		= FL_BASE2,		.num_ports	= 4,		.base_baud	= 921600,		.uart_offset	= 8 << 2,		.reg_shift	= 2,		.first_offset	= 0x03,	},	/*	 * This board uses the size of PCI Base region 0 to	 * signal now many ports are available	 */	[pbn_oxsemi] = {		.flags		= FL_BASE0|FL_REGION_SZ_CAP,		.num_ports	= 32,		.base_baud	= 115200,		.uart_offset	= 8,	},	/*	 * EKF addition for i960 Boards form EKF with serial port.	 * Max 256 ports.	 */	[pbn_intel_i960] = {		.flags		= FL_BASE0,		.num_ports	= 32,		.base_baud	= 921600,		.uart_offset	= 8 << 2,		.reg_shift	= 2,		.first_offset	= 0x10000,	},	[pbn_sgi_ioc3] = {		.flags		= FL_BASE0|FL_NOIRQ,		.num_ports	= 1,		.base_baud	= 458333,		.uart_offset	= 8,		.reg_shift	= 0,		.first_offset	= 0x20178,	},	/*	 * NEC Vrc-5074 (Nile 4) builtin UART.	 */	[pbn_nec_nile4] = {		.flags		= FL_BASE0,		.num_ports	= 1,		.base_baud	= 520833,		.uart_offset	= 8 << 3,		.reg_shift	= 3,		.first_offset	= 0x300,	},	/*	 * Computone - uses IOMEM.	 */	[pbn_computone_4] = {		.flags		= FL_BASE0,		.num_ports	= 4,		.base_baud	= 921600,		.uart_offset	= 0x40,		.reg_shift	= 2,		.first_offset	= 0x200,	},	[pbn_computone_6] = {		.flags		= FL_BASE0,		.num_ports	= 6,		.base_baud	= 921600,		.uart_offset	= 0x40,		.reg_shift	= 2,		.first_offset	= 0x200,	},	[pbn_computone_8] = {		.flags		= FL_BASE0,		.num_ports	= 8,		.base_baud	= 921600,		.uart_offset	= 0x40,		.reg_shift	= 2,		.first_offset	= 0x200,	},	[pbn_sbsxrsio] = {		.flags		= FL_BASE0,		.num_ports	= 8,		.base_baud	= 460800,		.uart_offset	= 256,		.reg_shift	= 4,	},	/*	 * Exar Corp. XR17C15[248] Dual/Quad/Octal UART	 *  Only basic 16550A support.	 *  XR17C15[24] are not tested, but they should work.	 */	[pbn_exar_XR17C152] = {		.flags		= FL_BASE0,		.num_ports	= 2,		.base_baud	= 921600,		.uart_offset	= 0x200,	},	[pbn_exar_XR17C154] = {		.flags		= FL_BASE0,		.num_ports	= 4,		.base_baud	= 921600,		.uart_offset	= 0x200,	},	[pbn_exar_XR17C158] = {		.flags		= FL_BASE0,		.num_ports	= 8,		.base_baud	= 921600,		.uart_offset	= 0x200,	},};/* * Given a complete unknown PCI device, try to use some heuristics to * guess what the configuration might be, based on the pitiful PCI * serial specs.  Returns 0 on success, 1 on failure. */static int __devinitserial_pci_guess_board(struct pci_dev *dev, struct pci_board *board){	int num_iomem, num_port, first_port = -1, i;		/*	 * If it is not a communications device or the programming	 * interface is greater than 6, give up.	 *	 * (Should we try to make guesses for multiport serial devices	 * later?) 	 */	if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) &&	     ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) ||	    (dev->class & 0xff) > 6)		return -ENODEV;	num_iomem = num_port = 0;	for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {		if (pci_resource_flags(dev, i) & IORESOURCE_IO) {			num_port++;			if (first_port == -1)				first_port = i;		}		if (pci_resource_flags(dev, i) & IORESOURCE_MEM)			num_iomem++;	}	/*	 * If there is 1 or 0 iomem regions, and exactly one port,	 * use it.  We guess the number of ports based on the IO	 * region size.	 */	if (num_iomem <= 1 && num_port == 1) {		board->flags = first_port;		board->num_ports = pci_resource_len(dev, first_port) / 8;		return 0;	}	/*	 * Now guess if we've got a board which indexes by BARs.	 * Each IO BAR should be 8 bytes, and they should follow	 * consecutively.	 */	first_port = -1;	num_port = 0;	for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {		if (pci_resource_flags(dev, i) & IORESOURCE_IO &&		    pci_resource_len(dev, i) == 8 &&		    (first_port == -1 || (first_port + num_port) == i)) {			num_port++;			if (first_port == -1)				first_port = i;		}	}	if (num_port > 1) {		board->flags = first_port | FL_BASE_BARS;		board->num_ports = num_port;		return 0;	}	return -ENODEV;}static inline intserial_pci_matches(struct pci_board *board, struct pci_board *guessed){	return	    board->num_ports == guessed->num_ports &&	    board->base_baud == guessed->base_baud &&	    board->uart_offset == guessed->uart_offset &&	    board->reg_shift == guessed->reg_shift &&	    board->first_offset == guessed->first_offset;}/* * Probe one serial board.  Unfortunately, there is no rhyme nor reason * to the arrangement of serial ports on a PCI card. */static int __devinitpciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent){	struct serial_private *priv;	struct pci_board *board, tmp;	struct pci_serial_quirk *quirk;	struct serial_struct serial_req;	int rc, nr_ports, i;	if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {		printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n",			ent->driver_data);		return -EINVAL;	}	board = &pci_boards[ent->driver_data];	rc = pci_enable_device(dev);	if (rc)		return rc;	if (ent->driver_data == pbn_default) {		/*		 * Use a copy of the pci_board entry for this;		 * avoid changing entries in the table.		 */		memcpy(&tmp, board, sizeof(struct pci_board));		board = &tmp;		/*		 * We matched one of our class entries.  Try to		 * determine the parameters of this board.		 */		rc = serial_pci_guess_board(dev, board);		if (rc)			goto disable;	} else {		/*		 * We matched an explicit entry.  If we are able to		 * detect this boards settings with our heuristic,		 * then we no longer need this entry.		 */		memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board));		rc = serial_pci_guess_board(dev, &tmp);		if (rc == 0 && serial_pci_matches(board, &tmp))			moan_device("Redundant entry in serial pci_table.",				    dev);	}	nr_ports = board->num_ports;	/*	 * Find an init and setup quirks.	 */	quirk = find_quirk(dev);	/*	 * Run the new-style initialization function.	 * The initialization function returns:	 *  <0  - error	 *   0  - use board->num_ports	 *  >0  - number of ports	 */	if (quirk->init) {		rc = quirk->init(dev);		if (rc < 0)			goto disable;		if (rc)			nr_ports = rc;	}	priv = kmalloc(sizeof(struct serial_private) +		       sizeof(unsigned int) * nr_ports,		       GFP_KERNEL);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?