⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parport_pc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	frob_econtrol (p, 0xe0, ECR_CNF << 5);		dma = inb (CONFIGB(p)) & 0x07;	/* 000: Indicates jumpered 8-bit DMA if read-only.	   100: Indicates jumpered 16-bit DMA if read-only. */	if ((dma & 0x03) == 0)		dma = PARPORT_DMA_NONE;	outb (oecr, ECONTROL (p));	return dma;}static int __devinit parport_dma_probe (struct parport *p){	const struct parport_pc_private *priv = p->private_data;	if (priv->ecr)		p->dma = programmable_dma_support(p); /* ask ECP chipset first */	if (p->dma == PARPORT_DMA_NONE)		/* ask known Super-IO chips proper, although these		   claim ECP compatible, some don't report their DMA		   conforming to ECP standards */		p->dma = get_superio_dma(p);	return p->dma;}/* --- Initialisation code -------------------------------- */struct parport *__devinit parport_pc_probe_port (unsigned long int base,						 unsigned long int base_hi,						 int irq, int dma,						 struct pci_dev *dev){	struct parport_pc_private *priv;	struct parport_operations *ops;	struct parport tmp;	struct parport *p = &tmp;	int probedirq = PARPORT_IRQ_NONE;	if (check_region(base, 3)) return NULL;	priv = kmalloc (sizeof (struct parport_pc_private), GFP_KERNEL);	if (!priv) {		printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);		return NULL;	}	ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);	if (!ops) {		printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",			base);		kfree (priv);		return NULL;	}	memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations));	priv->ctr = 0xc;	priv->ctr_writable = 0xff;	priv->ecr = 0;	priv->fifo_depth = 0;	priv->dma_buf = 0;	priv->dma_handle = 0;	priv->dev = dev;	p->base = base;	p->base_hi = base_hi;	p->irq = irq;	p->dma = dma;	p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT;	p->ops = ops;	p->private_data = priv;	p->physport = p;	if (base_hi && !check_region(base_hi,3)) {		parport_ECR_present(p);		parport_ECP_supported(p);	}	if (base != 0x3bc) {		if (!check_region(base+0x3, 5)) {			if (!parport_EPP_supported(p))				parport_ECPEPP_supported(p);		}	}	if (!parport_SPP_supported (p)) {		/* No port. */		kfree (priv);		return NULL;	}	if (priv->ecr)		parport_ECPPS2_supported(p);	else		parport_PS2_supported (p);	if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,					PARPORT_DMA_NONE, ops))) {		kfree (priv);		kfree (ops);		return NULL;	}	p->base_hi = base_hi;	p->modes = tmp.modes;	p->size = (p->modes & PARPORT_MODE_EPP)?8:3;	p->private_data = priv;	printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base);	if (p->base_hi && (p->modes & PARPORT_MODE_ECP))		printk(" (0x%lx)", p->base_hi);	p->irq = irq;	p->dma = dma;	if (p->irq == PARPORT_IRQ_AUTO) {		p->irq = PARPORT_IRQ_NONE;		parport_irq_probe(p);	} else if (p->irq == PARPORT_IRQ_PROBEONLY) {		p->irq = PARPORT_IRQ_NONE;		parport_irq_probe(p);		probedirq = p->irq;		p->irq = PARPORT_IRQ_NONE;	}	if (p->irq != PARPORT_IRQ_NONE) {		printk(", irq %d", p->irq);		if (p->dma == PARPORT_DMA_AUTO) {			p->dma = PARPORT_DMA_NONE;			parport_dma_probe(p);		}	}	if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq                                           is mandatory (see above) */		p->dma = PARPORT_DMA_NONE;#ifdef CONFIG_PARPORT_PC_FIFO	if (p->dma != PARPORT_DMA_NOFIFO &&	    priv->fifo_depth > 0 && p->irq != PARPORT_IRQ_NONE) {		p->ops->compat_write_data = parport_pc_compat_write_block_pio;#ifdef CONFIG_PARPORT_1284		p->ops->ecp_write_data = parport_pc_ecp_write_block_pio;#endif /* IEEE 1284 support */		if (p->dma != PARPORT_DMA_NONE) {			printk(", dma %d", p->dma);			p->modes |= PARPORT_MODE_DMA;		}		else printk(", using FIFO");	}	else		/* We can't use the DMA channel after all. */		p->dma = PARPORT_DMA_NONE;#endif /* Allowed to use FIFO/DMA */	printk(" [");#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}}	{		int f = 0;		printmode(PCSPP);		printmode(TRISTATE);		printmode(COMPAT)		printmode(EPP);		printmode(ECP);		printmode(DMA);	}#undef printmode#ifndef CONFIG_PARPORT_1284	printk ("(,...)");#endif /* CONFIG_PARPORT_1284 */	printk("]\n");	if (probedirq != PARPORT_IRQ_NONE) 		printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq);	parport_proc_register(p);	request_region (p->base, 3, p->name);	if (p->size > 3)		request_region (p->base + 3, p->size - 3, p->name);	if (p->modes & PARPORT_MODE_ECP)		request_region (p->base_hi, 3, p->name);	if (p->irq != PARPORT_IRQ_NONE) {		if (request_irq (p->irq, parport_pc_interrupt,				 0, p->name, p)) {			printk (KERN_WARNING "%s: irq %d in use, "				"resorting to polled operation\n",				p->name, p->irq);			p->irq = PARPORT_IRQ_NONE;			p->dma = PARPORT_DMA_NONE;		}#ifdef CONFIG_PARPORT_PC_FIFO		if (p->dma != PARPORT_DMA_NONE) {			if (request_dma (p->dma, p->name)) {				printk (KERN_WARNING "%s: dma %d in use, "					"resorting to PIO operation\n",					p->name, p->dma);				p->dma = PARPORT_DMA_NONE;			} else {				priv->dma_buf =				  pci_alloc_consistent(priv->dev,						       PAGE_SIZE,						       &priv->dma_handle);				if (! priv->dma_buf) {					printk (KERN_WARNING "%s: "						"cannot get buffer for DMA, "						"resorting to PIO operation\n",						p->name);					free_dma(p->dma);					p->dma = PARPORT_DMA_NONE;				}			}		}#endif /* CONFIG_PARPORT_PC_FIFO */	}	/* Done probing.  Now put the port into a sensible start-up state. */	if (priv->ecr)		/*		 * Put the ECP detected port in PS2 mode.		 * Do this also for ports that have ECR but don't do ECP.		 */		outb (0x34, ECONTROL (p));	parport_pc_write_data(p, 0);	parport_pc_data_forward (p);	/* Now that we've told the sharing engine about the port, and	   found out its characteristics, let the high-level drivers	   know about it. */	parport_announce_port (p);	return p;}/* Via support maintained by Jeff Garzik <jgarzik@mandrakesoft.com> */static int __devinit sio_via_686a_probe (struct pci_dev *pdev){	u8 tmp;	int dma, irq;	unsigned port1, port2, have_eppecp;	/*	 * unlock super i/o configuration, set 0x85_1	 */	pci_read_config_byte (pdev, 0x85, &tmp);	tmp |= (1 << 1);	pci_write_config_byte (pdev, 0x85, tmp);		/* 	 * Super I/O configuration, index port == 3f0h, data port == 3f1h	 */		/* 0xE2_1-0: Parallel Port Mode / Enable */	outb (0xE2, 0x3F0);	tmp = inb (0x3F1);		if ((tmp & 0x03) == 0x03) {		printk (KERN_INFO "parport_pc: Via 686A parallel port disabled in BIOS\n");		return 0;	}		/* 0xE6: Parallel Port I/O Base Address, bits 9-2 */	outb (0xE6, 0x3F0);	port1 = inb (0x3F1) << 2;		switch (port1) {	case 0x3bc: port2 = 0x7bc; break;	case 0x378: port2 = 0x778; break;	case 0x278: port2 = 0x678; break;	default:		printk (KERN_INFO "parport_pc: Via 686A weird parport base 0x%X, ignoring\n",			port1);		return 0;	}	/* 0xF0_5: EPP+ECP enable */	outb (0xF0, 0x3F0);	have_eppecp = (inb (0x3F1) & (1 << 5));		/*	 * lock super i/o configuration, clear 0x85_1	 */	pci_read_config_byte (pdev, 0x85, &tmp);	tmp &= ~(1 << 1);	pci_write_config_byte (pdev, 0x85, tmp);	/*	 * Get DMA and IRQ from PCI->ISA bridge PCI config registers	 */	/* 0x50_3-2: PnP Routing for Parallel Port DRQ */	pci_read_config_byte (pdev, 0x50, &tmp);	dma = ((tmp >> 2) & 0x03);		/* 0x51_7-4: PnP Routing for Parallel Port IRQ */	pci_read_config_byte (pdev, 0x51, &tmp);	irq = ((tmp >> 4) & 0x0F);	/* filter bogus IRQs */	switch (irq) {	case 0:	case 2:	case 8:	case 13:		irq = PARPORT_IRQ_NONE;		break;	default: /* do nothing */		break;	}	/* if ECP not enabled, DMA is not enabled, assumed bogus 'dma' value */	if (!have_eppecp)		dma = PARPORT_DMA_NONE;	/* finally, do the probe with values obtained */	if (parport_pc_probe_port (port1, port2, irq, dma, NULL)) {		printk (KERN_INFO			"parport_pc: Via 686A parallel port: io=0x%X", port1);		if (irq != PARPORT_IRQ_NONE)			printk (", irq=%d", irq);		if (dma != PARPORT_DMA_NONE)			printk (", dma=%d", dma);		printk ("\n");		return 1;	}		printk (KERN_WARNING "parport_pc: Strange, can't probe Via 686A parallel port: io=0x%X, irq=%d, dma=%d\n",		port1, irq, dma);	return 0;}enum parport_pc_sio_types {	sio_via_686a = 0,	/* Via VT82C686A motherboard Super I/O */	last_sio};/* each element directly indexed from enum list, above */static struct parport_pc_superio {	int (*probe) (struct pci_dev *pdev);} parport_pc_superio_info[] __devinitdata = {	{ sio_via_686a_probe, },};enum parport_pc_pci_cards {	siig_1s1p_10x_550 = last_sio,	siig_1s1p_10x_650,	siig_1s1p_10x_850,	siig_1p_10x,	siig_2p_10x,	siig_2s1p_10x_550,	siig_2s1p_10x_650,	siig_2s1p_10x_850,	siig_1p_20x,	siig_2p_20x,	siig_2p1s_20x_550,	siig_2p1s_20x_650,	siig_2p1s_20x_850,	siig_1s1p_20x_550,	siig_1s1p_20x_650,	siig_1s1p_20x_850,	siig_2s1p_20x_550,	siig_2s1p_20x_650,	siig_2s1p_20x_850,	lava_parallel,	lava_parallel_dual_a,	lava_parallel_dual_b,	boca_ioppar,	plx_9050,	afavlab_tk9902,	timedia_4078a,	timedia_4079h,	timedia_4085h,	timedia_4088a,	timedia_4089a,	timedia_4095a,	timedia_4096a,	timedia_4078u,	timedia_4079a,	timedia_4085u,	timedia_4079r,	timedia_4079s,	timedia_4079d,	timedia_4079e,	timedia_4079f,	timedia_9079a,	timedia_9079b,	timedia_9079c,	timedia_4006a,	timedia_4014,	timedia_4008a,	timedia_4018,	timedia_9018a,	syba_2p_epp,	syba_1p_ecp,};/* each element directly indexed from enum list, above  * (but offset by last_sio) */static struct parport_pc_pci {	int numports;	struct { /* BAR (base address registers) numbers in the config                    space header */		int lo;		int hi; /* -1 if not there, >6 for offset-method (max                           BAR is 6) */	} addr[4];} cards[] __devinitdata = {	/* siig_1s1p_10x_550 */		{ 1, { { 3, 4 }, } },	/* siig_1s1p_10x_650 */		{ 1, { { 3, 4 }, } },	/* siig_1s1p_10x_850 */		{ 1, { { 3, 4 }, } },	/* siig_1p_10x */		{ 1, { { 2, 3 }, } },	/* siig_2p_10x */		{ 2, { { 2, 3 }, { 4, 5 }, } },	/* siig_2s1p_10x_550 */		{ 1, { { 4, 5 }, } },	/* siig_2s1p_10x_650 */		{ 1, { { 4, 5 }, } },	/* siig_2s1p_10x_850 */		{ 1, { { 4, 5 }, } },	/* siig_1p_20x */		{ 1, { { 0, 1 }, } },	/* siig_2p_20x */		{ 2, { { 0, 1 }, { 2, 3 }, } },	/* siig_2p1s_20x_550 */		{ 2, { { 1, 2 }, { 3, 4 }, } },	/* siig_2p1s_20x_650 */		{ 2, { { 1, 2 }, { 3, 4 }, } },	/* siig_2p1s_20x_850 */		{ 2, { { 1, 2 }, { 3, 4 }, } },	/* siig_1s1p_20x_550 */		{ 1, { { 1, 2 }, } },	/* siig_1s1p_20x_650 */		{ 1, { { 1, 2 }, } },	/* siig_1s1p_20x_850 */		{ 1, { { 1, 2 }, } },	/* siig_2s1p_20x_550 */		{ 1, { { 2, 3 }, } },	/* siig_2s1p_20x_650 */		{ 1, { { 2, 3 }, } },	/* siig_2s1p_20x_850 */		{ 1, { { 2, 3 }, } },	/* lava_parallel */		{ 1, { { 0, -1 }, } },	/* lava_parallel_dual_a */	{ 1, { { 0, -1 }, } },	/* lava_parallel_dual_b */	{ 1, { { 0, -1 }, } },	/* boca_ioppar */		{ 1, { { 0, -1 }, } },	/* plx_9050 */			{ 2, { { 4, -1 }, { 5, -1 }, } },	/* afavlab_tk9902 */		{ 1, { { 0, 1 }, } },	/* timedia_4078a */		{ 1, { { 2, -1 }, } },	/* timedia_4079h */             { 1, { { 2, 3 }, } },	/* timedia_4085h */             { 2, { { 2, -1 }, { 4, -1 }, } },	/* timedia_4088a */             { 2, { { 2, 3 }, { 4, 5 }, } },	/* timedia_4089a */             { 2, { { 2, 3 }, { 4, 5 }, } },	/* timedia_4095a */             { 2, { { 2, 3 }, { 4, 5 }, } },	/* timedia_4096a */             { 2, { { 2, 3 }, { 4, 5 }, } },	/* timedia_4078u */             { 1, { { 2, -1 }, } },	/* timedia_4079a */             { 1, { { 2, 3 }, } },	/* timedia_4085u */             { 2, { { 2, -1 }, { 4, -1 }, } },	/* timedia_4079r */             { 1, { { 2, 3 }, } },	/* timedia_4079s */             { 1, { { 2, 3 }, } },	/* timedia_4079d */             { 1, { { 2, 3 }, } },	/* timedia_4079e */             { 1, { { 2, 3 }, } },	/* timedia_4079f */             { 1, { { 2, 3 }, } },	/* timedia_9079a */             { 1, { { 2, 3 }, } },	/* timedia_9079b */             { 1, { { 2, 3 }, } },	/* timedia_9079c */             { 1, { { 2, 3 }, } },	/* timedia_4006a */             { 1, { { 0, -1 }, } },	/* timedia_4014  */             { 2, { { 0, -1 }, { 2, -1 }, } },	/* timedia_4008a */             { 1, { { 0, 1 }, } },	/* timedia_4018  */             { 2, { { 0, 1 }, { 2, 3 }, } },	/* timedia_9018a */             { 2, { { 0, 1 }, { 2, 3 }, } },					/* SYBA uses fixed offsets in                                           a 1K io window */	/* syba_2p_epp AP138B */	{ 2, { { 0, 0x078 }, { 0, 0x178 }, } },	/* syba_1p_ecp W83787 */	{ 1, { { 0, 0x078 }, } },};static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {	/* Super-IO onboard chips */	{ 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a },	/* PCI cards */	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x_550 },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x_650 },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x_850 },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_10x,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1p_10x },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_10x,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p_10x },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x_550 },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x_650 },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x_850 },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_20x,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1p_20x },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_20x,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p_20x },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x_550 },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x_650 },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x_850 },	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_2

⌨️ 快捷键说明

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