8250_pci.c

来自「linux 内核源代码」· C语言 代码 · 共 2,606 行 · 第 1/5 页

C
2,606
字号
		offset = board->uart_offset;		bar = 0;		break;	case 2:		bar = 1;		break;	case 3:		offset = board->uart_offset;		/* FALLTHROUGH */	case 4: /* BAR 2 */	case 5: /* BAR 3 */	case 6: /* BAR 4 */	case 7: /* BAR 5 */		bar = idx - 2;	}	return setup_port(priv, port, bar, offset, board->reg_shift);}/* * Some Titan cards are also a little weird */static inttitan_400l_800l_setup(struct serial_private *priv,		      struct pciserial_board *board,		      struct uart_port *port, int idx){	unsigned int bar, offset = board->first_offset;	switch (idx) {	case 0:		bar = 1;		break;	case 1:		bar = 2;		break;	default:		bar = 4;		offset = (idx - 2) * board->uart_offset;	}	return setup_port(priv, port, bar, offset, board->reg_shift);}static int pci_xircom_init(struct pci_dev *dev){	msleep(100);	return 0;}static int pci_netmos_init(struct pci_dev *dev){	/* subdevice 0x00PS means <P> parallel, <S> serial */	unsigned int num_serial = dev->subsystem_device & 0xf;	if (num_serial == 0)		return -ENODEV;	return num_serial;}/* * ITE support by Niels de Vos <niels.devos@wincor-nixdorf.com> * * These chips are available with optionally one parallel port and up to * two serial ports. Unfortunately they all have the same product id. * * Basic configuration is done over a region of 32 I/O ports. The base * ioport is called INTA or INTC, depending on docs/other drivers. * * The region of the 32 I/O ports is configured in POSIO0R... *//* registers */#define ITE_887x_MISCR		0x9c#define ITE_887x_INTCBAR	0x78#define ITE_887x_UARTBAR	0x7c#define ITE_887x_PS0BAR		0x10#define ITE_887x_POSIO0		0x60/* I/O space size */#define ITE_887x_IOSIZE		32/* I/O space size (bits 26-24; 8 bytes = 011b) */#define ITE_887x_POSIO_IOSIZE_8		(3 << 24)/* I/O space size (bits 26-24; 32 bytes = 101b) */#define ITE_887x_POSIO_IOSIZE_32	(5 << 24)/* Decoding speed (1 = slow, 2 = medium, 3 = fast) */#define ITE_887x_POSIO_SPEED		(3 << 29)/* enable IO_Space bit */#define ITE_887x_POSIO_ENABLE		(1 << 31)static int pci_ite887x_init(struct pci_dev *dev){	/* inta_addr are the configuration addresses of the ITE */	static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,							0x200, 0x280, 0 };	int ret, i, type;	struct resource *iobase = NULL;	u32 miscr, uartbar, ioport;	/* search for the base-ioport */	i = 0;	while (inta_addr[i] && iobase == NULL) {		iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,								"ite887x");		if (iobase != NULL) {			/* write POSIO0R - speed | size | ioport */			pci_write_config_dword(dev, ITE_887x_POSIO0,				ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |				ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]);			/* write INTCBAR - ioport */			pci_write_config_dword(dev, ITE_887x_INTCBAR, inta_addr[i]);			ret = inb(inta_addr[i]);			if (ret != 0xff) {				/* ioport connected */				break;			}			release_region(iobase->start, ITE_887x_IOSIZE);			iobase = NULL;		}		i++;	}	if (!inta_addr[i]) {		printk(KERN_ERR "ite887x: could not find iobase\n");		return -ENODEV;	}	/* start of undocumented type checking (see parport_pc.c) */	type = inb(iobase->start + 0x18) & 0x0f;	switch (type) {	case 0x2:	/* ITE8871 (1P) */	case 0xa:	/* ITE8875 (1P) */		ret = 0;		break;	case 0xe:	/* ITE8872 (2S1P) */		ret = 2;		break;	case 0x6:	/* ITE8873 (1S) */		ret = 1;		break;	case 0x8:	/* ITE8874 (2S) */		ret = 2;		break;	default:		moan_device("Unknown ITE887x", dev);		ret = -ENODEV;	}	/* configure all serial ports */	for (i = 0; i < ret; i++) {		/* read the I/O port from the device */		pci_read_config_dword(dev, ITE_887x_PS0BAR + (0x4 * (i + 1)),								&ioport);		ioport &= 0x0000FF00;	/* the actual base address */		pci_write_config_dword(dev, ITE_887x_POSIO0 + (0x4 * (i + 1)),			ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED |			ITE_887x_POSIO_IOSIZE_8 | ioport);		/* write the ioport to the UARTBAR */		pci_read_config_dword(dev, ITE_887x_UARTBAR, &uartbar);		uartbar &= ~(0xffff << (16 * i));	/* clear half the reg */		uartbar |= (ioport << (16 * i));	/* set the ioport */		pci_write_config_dword(dev, ITE_887x_UARTBAR, uartbar);		/* get current config */		pci_read_config_dword(dev, ITE_887x_MISCR, &miscr);		/* disable interrupts (UARTx_Routing[3:0]) */		miscr &= ~(0xf << (12 - 4 * i));		/* activate the UART (UARTx_En) */		miscr |= 1 << (23 - i);		/* write new config with activated UART */		pci_write_config_dword(dev, ITE_887x_MISCR, miscr);	}	if (ret <= 0) {		/* the device has no UARTs if we get here */		release_region(iobase->start, ITE_887x_IOSIZE);	}	return ret;}static void __devexit pci_ite887x_exit(struct pci_dev *dev){	u32 ioport;	/* the ioport is bit 0-15 in POSIO0R */	pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport);	ioport &= 0xffff;	release_region(ioport, ITE_887x_IOSIZE);}static intpci_default_setup(struct serial_private *priv, struct pciserial_board *board,		  struct uart_port *port, int idx){	unsigned int bar, offset = board->first_offset, maxnr;	bar = FL_GET_BASE(board->flags);	if (board->flags & FL_BASE_BARS)		bar += idx;	else		offset += idx * board->uart_offset;	maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >>		(board->reg_shift + 3);	if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr)		return 1;				return setup_port(priv, port, bar, offset, board->reg_shift);}/* This should be in linux/pci_ids.h */#define PCI_VENDOR_ID_SBSMODULARIO	0x124B#define PCI_SUBVENDOR_ID_SBSMODULARIO	0x124B#define PCI_DEVICE_ID_OCTPRO		0x0001#define PCI_SUBDEVICE_ID_OCTPRO232	0x0108#define PCI_SUBDEVICE_ID_OCTPRO422	0x0208#define PCI_SUBDEVICE_ID_POCTAL232	0x0308#define PCI_SUBDEVICE_ID_POCTAL422	0x0408/* * Master list of serial port init/setup/exit quirks. * This does not describe the general nature of the port. * (ie, baud base, number and location of ports, etc) * * This list is ordered alphabetically by vendor then device. * Specific entries must come before more generic entries. */static struct pci_serial_quirk pci_serial_quirks[] = {	/*	 * AFAVLAB cards - these may be called via parport_serial	 *  It is not clear whether this applies to all products.	 */	{		.vendor		= PCI_VENDOR_ID_AFAVLAB,		.device		= PCI_ANY_ID,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.setup		= afavlab_setup,	},	/*	 * HP Diva	 */	{		.vendor		= PCI_VENDOR_ID_HP,		.device		= PCI_DEVICE_ID_HP_DIVA,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.init		= pci_hp_diva_init,		.setup		= pci_hp_diva_setup,	},	/*	 * Intel	 */	{		.vendor		= PCI_VENDOR_ID_INTEL,		.device		= PCI_DEVICE_ID_INTEL_80960_RP,		.subvendor	= 0xe4bf,		.subdevice	= PCI_ANY_ID,		.init		= pci_inteli960ni_init,		.setup		= pci_default_setup,	},	/*	 * ITE	 */	{		.vendor		= PCI_VENDOR_ID_ITE,		.device		= PCI_DEVICE_ID_ITE_8872,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.init		= pci_ite887x_init,		.setup		= pci_default_setup,		.exit		= __devexit_p(pci_ite887x_exit),	},	/*	 * Panacom	 */	{		.vendor		= PCI_VENDOR_ID_PANACOM,		.device		= PCI_DEVICE_ID_PANACOM_QUADMODEM,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.init		= pci_plx9050_init,		.setup		= pci_default_setup,		.exit		= __devexit_p(pci_plx9050_exit),	},			{		.vendor		= PCI_VENDOR_ID_PANACOM,		.device		= PCI_DEVICE_ID_PANACOM_DUALMODEM,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.init		= pci_plx9050_init,		.setup		= pci_default_setup,		.exit		= __devexit_p(pci_plx9050_exit),	},	/*	 * PLX	 */	{		.vendor		= PCI_VENDOR_ID_PLX,		.device		= PCI_DEVICE_ID_PLX_9030,		.subvendor	= PCI_SUBVENDOR_ID_PERLE,		.subdevice	= PCI_ANY_ID,		.setup		= pci_default_setup,	},	{		.vendor		= PCI_VENDOR_ID_PLX,		.device		= PCI_DEVICE_ID_PLX_9050,		.subvendor	= PCI_SUBVENDOR_ID_EXSYS,		.subdevice	= PCI_SUBDEVICE_ID_EXSYS_4055,		.init		= pci_plx9050_init,		.setup		= pci_default_setup,		.exit		= __devexit_p(pci_plx9050_exit),	},	{		.vendor		= PCI_VENDOR_ID_PLX,		.device		= PCI_DEVICE_ID_PLX_9050,		.subvendor	= PCI_SUBVENDOR_ID_KEYSPAN,		.subdevice	= PCI_SUBDEVICE_ID_KEYSPAN_SX2,		.init		= pci_plx9050_init,		.setup		= pci_default_setup,		.exit		= __devexit_p(pci_plx9050_exit),	},	{		.vendor		= PCI_VENDOR_ID_PLX,		.device		= PCI_DEVICE_ID_PLX_ROMULUS,		.subvendor	= PCI_VENDOR_ID_PLX,		.subdevice	= PCI_DEVICE_ID_PLX_ROMULUS,		.init		= pci_plx9050_init,		.setup		= pci_default_setup,		.exit		= __devexit_p(pci_plx9050_exit),	},	/*	 * SBS Technologies, Inc., PMC-OCTALPRO 232	 */	{		.vendor		= PCI_VENDOR_ID_SBSMODULARIO,		.device		= PCI_DEVICE_ID_OCTPRO,		.subvendor	= PCI_SUBVENDOR_ID_SBSMODULARIO,		.subdevice	= PCI_SUBDEVICE_ID_OCTPRO232,		.init		= sbs_init,		.setup		= sbs_setup,		.exit		= __devexit_p(sbs_exit),	},	/*	 * SBS Technologies, Inc., PMC-OCTALPRO 422	 */	{		.vendor		= PCI_VENDOR_ID_SBSMODULARIO,		.device		= PCI_DEVICE_ID_OCTPRO,		.subvendor	= PCI_SUBVENDOR_ID_SBSMODULARIO,		.subdevice	= PCI_SUBDEVICE_ID_OCTPRO422,		.init		= sbs_init,		.setup		= sbs_setup,		.exit		= __devexit_p(sbs_exit),	},	/*	 * SBS Technologies, Inc., P-Octal 232	 */	{		.vendor		= PCI_VENDOR_ID_SBSMODULARIO,		.device		= PCI_DEVICE_ID_OCTPRO,		.subvendor	= PCI_SUBVENDOR_ID_SBSMODULARIO,		.subdevice	= PCI_SUBDEVICE_ID_POCTAL232,		.init		= sbs_init,		.setup		= sbs_setup,		.exit		= __devexit_p(sbs_exit),	},	/*	 * SBS Technologies, Inc., P-Octal 422	 */	{		.vendor		= PCI_VENDOR_ID_SBSMODULARIO,		.device		= PCI_DEVICE_ID_OCTPRO,		.subvendor	= PCI_SUBVENDOR_ID_SBSMODULARIO,		.subdevice	= PCI_SUBDEVICE_ID_POCTAL422,		.init		= sbs_init,		.setup		= sbs_setup,		.exit		= __devexit_p(sbs_exit),	},	/*	 * SIIG cards - these may be called via parport_serial	 */	{		.vendor		= PCI_VENDOR_ID_SIIG,		.device		= PCI_ANY_ID,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.init		= pci_siig_init,		.setup		= pci_siig_setup,	},	/*	 * Titan cards	 */	{		.vendor		= PCI_VENDOR_ID_TITAN,		.device		= PCI_DEVICE_ID_TITAN_400L,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.setup		= titan_400l_800l_setup,	},	{		.vendor		= PCI_VENDOR_ID_TITAN,		.device		= PCI_DEVICE_ID_TITAN_800L,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.setup		= titan_400l_800l_setup,	},	/*	 * Timedia cards	 */	{		.vendor		= PCI_VENDOR_ID_TIMEDIA,		.device		= PCI_DEVICE_ID_TIMEDIA_1889,		.subvendor	= PCI_VENDOR_ID_TIMEDIA,		.subdevice	= PCI_ANY_ID,		.init		= pci_timedia_init,		.setup		= pci_timedia_setup,	},	{		.vendor		= PCI_VENDOR_ID_TIMEDIA,		.device		= PCI_ANY_ID,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.setup		= pci_timedia_setup,	},	/*	 * Xircom cards	 */	{		.vendor		= PCI_VENDOR_ID_XIRCOM,		.device		= PCI_DEVICE_ID_XIRCOM_X3201_MDM,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.init		= pci_xircom_init,		.setup		= pci_default_setup,	},	/*	 * Netmos cards - these may be called via parport_serial	 */	{		.vendor		= PCI_VENDOR_ID_NETMOS,		.device		= PCI_ANY_ID,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.init		= pci_netmos_init,		.setup		= pci_default_setup,	},	/*	 * Default "match everything" terminator entry	 */	{		.vendor		= PCI_ANY_ID,		.device		= PCI_ANY_ID,		.subvendor	= PCI_ANY_ID,		.subdevice	= PCI_ANY_ID,		.setup		= pci_default_setup,	}};static inline int quirk_id_matches(u32 quirk_id, u32 dev_id){	return quirk_id == PCI_ANY_ID || quirk_id == dev_id;}static struct pci_serial_quirk *find_quirk(struct pci_dev *dev){	struct pci_serial_quirk *quirk;	for (quirk = pci_serial_quirks; ; quirk++)		if (quirk_id_matches(quirk->vendor, dev->vendor) &&		    quirk_id_matches(quirk->device, dev->device) &&		    quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&		    quirk_id_matches(quirk->subdevice, dev->subsystem_device))		 	break;	return quirk;}static inline int get_pci_irq(struct pci_dev *dev,				struct pciserial_board *board){	if (board->flags & FL_NOIRQ)		return 0;	else		return dev->irq;}/* * 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 * driver_data member. * * The makeup of these names are: *  pbn_bn{_bt}_n_baud{_offsetinhex} * *  bn		= PCI BAR number *  bt		= Index using PCI BARs *  n		= number of serial ports *  baud	= baud rate *  offsetinhex	= offset for each sequential port (in hex) * * This table is sorted by (in order): bn, bt, baud, offsetindex, n. * * Please note: in theory if n = 1, _bt infix should make no difference. * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200 */enum pci_board_num_t {	pbn_default = 0,	pbn_b0_1_115200,	pbn_b0_2_115200,	pbn_b0_4_115200,	pbn_b0_5_115200,	pbn_b0_8_115200,	pbn_b0_1_921600,	pbn_b0_2_921600,	pbn_b0_4_921600,

⌨️ 快捷键说明

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