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

📄 parport_pc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	r = parport_pc_read_data (pb);	if (r == w) {		w = 0x55;		parport_pc_write_data (pb, w);		r = parport_pc_read_data (pb);		if (r == w)			return PARPORT_MODE_PCSPP;	}	if (user_specified) {		/* Didn't work, but the user is convinced this is the		 * place. */		printk (KERN_DEBUG "parport 0x%lx (WARNING): DATA: "			"wrote 0x%02x, read 0x%02x\n", pb->base, w, r);		printk (KERN_DEBUG "parport 0x%lx: You gave this address, "			"but there is probably no parallel port there!\n",			pb->base);	}	/* It's possible that we can't read the control register or	 * the data register.  In that case just believe the user. */	if (user_specified)		return PARPORT_MODE_PCSPP;	return 0;}/* Check for ECR * * Old style XT ports alias io ports every 0x400, hence accessing ECR * on these cards actually accesses the CTR. * * Modern cards don't do this but reading from ECR will return 0xff * regardless of what is written here if the card does NOT support * ECP. * * We first check to see if ECR is the same as CTR.  If not, the low * two bits of ECR aren't writable, so we check by writing ECR and * reading it back to see if it's what we expect. */static int __devinit parport_ECR_present(struct parport *pb){	struct parport_pc_private *priv = pb->private_data;	unsigned char r = 0xc;	outb (r, CONTROL (pb));	if ((inb (ECONTROL (pb)) & 0x3) == (r & 0x3)) {		outb (r ^ 0x2, CONTROL (pb)); /* Toggle bit 1 */		r = inb (CONTROL (pb));		if ((inb (ECONTROL (pb)) & 0x2) == (r & 0x2))			goto no_reg; /* Sure that no ECR register exists */	}		if ((inb (ECONTROL (pb)) & 0x3 ) != 0x1)		goto no_reg;	outb (0x34, ECONTROL (pb));	if (inb (ECONTROL (pb)) != 0x35)		goto no_reg;	priv->ecr = 1;	outb (0xc, CONTROL (pb));		/* Go to mode 000 */	frob_econtrol (pb, 0xe0, ECR_SPP << 5);	return 1; no_reg:	outb (0xc, CONTROL (pb));	return 0; }#ifdef CONFIG_PARPORT_1284/* Detect PS/2 support. * * Bit 5 (0x20) sets the PS/2 data direction; setting this high * allows us to read data from the data lines.  In theory we would get back * 0xff but any peripheral attached to the port may drag some or all of the * lines down to zero.  So if we get back anything that isn't the contents * of the data register we deem PS/2 support to be present.  * * Some SPP ports have "half PS/2" ability - you can't turn off the line * drivers, but an external peripheral with sufficiently beefy drivers of * its own can overpower them and assert its own levels onto the bus, from * where they can then be read back as normal.  Ports with this property * and the right type of device attached are likely to fail the SPP test, * (as they will appear to have stuck bits) and so the fact that they might * be misdetected here is rather academic.  */static int __devinit parport_PS2_supported(struct parport *pb){	int ok = 0;  	clear_epp_timeout(pb);	/* try to tri-state the buffer */	parport_pc_data_reverse (pb);		parport_pc_write_data(pb, 0x55);	if (parport_pc_read_data(pb) != 0x55) ok++;	parport_pc_write_data(pb, 0xaa);	if (parport_pc_read_data(pb) != 0xaa) ok++;	/* cancel input mode */	parport_pc_data_forward (pb);	if (ok) {		pb->modes |= PARPORT_MODE_TRISTATE;	} else {		struct parport_pc_private *priv = pb->private_data;		priv->ctr_writable &= ~0x20;	}	return ok;}static int __devinit parport_ECP_supported(struct parport *pb){	int i;	int config, configb;	int pword;	struct parport_pc_private *priv = pb->private_data;	int intrline[]={0,7,9,10,11,14,15,5}; /* Translate ECP                                                 intrLine to ISA irq                                                 value */	/* If there is no ECR, we have no hope of supporting ECP. */	if (!priv->ecr)		return 0;	/* Find out FIFO depth */	outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */	outb (ECR_TST << 5, ECONTROL (pb)); /* TEST FIFO */	for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02); i++)		outb (0xaa, FIFO (pb));	/*	 * Using LGS chipset it uses ECR register, but	 * it doesn't support ECP or FIFO MODE	 */	if (i == 1024) {		outb (ECR_SPP << 5, ECONTROL (pb));		return 0;	}	priv->fifo_depth = i;	printk (KERN_INFO "0x%lx: FIFO is %d bytes\n", pb->base, i);	/* Find out writeIntrThreshold */	frob_econtrol (pb, 1<<2, 1<<2);	frob_econtrol (pb, 1<<2, 0);	for (i = 1; i <= priv->fifo_depth; i++) {		inb (FIFO (pb));		udelay (50);		if (inb (ECONTROL (pb)) & (1<<2))			break;	}	if (i <= priv->fifo_depth)		printk (KERN_INFO "0x%lx: writeIntrThreshold is %d\n",			pb->base, i);	else		/* Number of bytes we know we can write if we get an                   interrupt. */		i = 0;	priv->writeIntrThreshold = i;	/* Find out readIntrThreshold */	frob_econtrol (pb, 0xe0, ECR_PS2 << 5); /* Reset FIFO and enable PS2 */	parport_pc_data_reverse (pb); /* Must be in PS2 mode */	frob_econtrol (pb, 0xe0, ECR_TST << 5); /* Test FIFO */	frob_econtrol (pb, 1<<2, 1<<2);	frob_econtrol (pb, 1<<2, 0);	for (i = 1; i <= priv->fifo_depth; i++) {		outb (0xaa, FIFO (pb));		if (inb (ECONTROL (pb)) & (1<<2))			break;	}	if (i <= priv->fifo_depth)		printk (KERN_INFO "0x%lx: readIntrThreshold is %d\n",			pb->base, i);	else		/* Number of bytes we can read if we get an interrupt. */		i = 0;	priv->readIntrThreshold = i;	outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */	outb (0xf4, ECONTROL (pb)); /* Configuration mode */	config = inb (CONFIGA (pb));	pword = (config >> 4) & 0x7;	switch (pword) {	case 0:		pword = 2;		printk (KERN_WARNING "0x%lx: Unsupported pword size!\n",			pb->base);		break;	case 2:		pword = 4;		printk (KERN_WARNING "0x%lx: Unsupported pword size!\n",			pb->base);		break;	default:		printk (KERN_WARNING "0x%lx: Unknown implementation ID\n",			pb->base);		/* Assume 1 */	case 1:		pword = 1;	}	priv->pword = pword;	printk (KERN_DEBUG "0x%lx: PWord is %d bits\n", pb->base, 8 * pword);	printk (KERN_DEBUG "0x%lx: Interrupts are ISA-%s\n", pb->base,		config & 0x80 ? "Level" : "Pulses");	configb = inb (CONFIGB (pb));	if (!(configb & 0x40)) {		printk (KERN_WARNING "0x%lx: possible IRQ conflict!\n",			pb->base);		pb->irq = PARPORT_IRQ_NONE;	}	printk (KERN_DEBUG "0x%lx: ECP port cfgA=0x%02x cfgB=0x%02x\n",		pb->base, config, configb);        printk (KERN_DEBUG "0x%lx: ECP settings irq=", pb->base);	if ((configb >>3) & 0x07)		printk("%d",intrline[(configb >>3) & 0x07]);	else		printk("<none or set by other means>");	printk ( " dma=");	if( (configb & 0x03 ) == 0x00)		printk("<none or set by other means>\n");	else		printk("%d\n",configb & 0x07);	/* Go back to mode 000 */	frob_econtrol (pb, 0xe0, ECR_SPP << 5);	pb->modes |= PARPORT_MODE_ECP | PARPORT_MODE_COMPAT;	return 1;}static int __devinit parport_ECPPS2_supported(struct parport *pb){	const struct parport_pc_private *priv = pb->private_data;	int result;	unsigned char oecr;	if (!priv->ecr)		return 0;	oecr = inb (ECONTROL (pb));	outb (ECR_PS2 << 5, ECONTROL (pb));		result = parport_PS2_supported(pb);	outb (oecr, ECONTROL (pb));	return result;}/* EPP mode detection  */static int __devinit parport_EPP_supported(struct parport *pb){	const struct parport_pc_private *priv = pb->private_data;	/*	 * Theory:	 *	Bit 0 of STR is the EPP timeout bit, this bit is 0	 *	when EPP is possible and is set high when an EPP timeout	 *	occurs (EPP uses the HALT line to stop the CPU while it does	 *	the byte transfer, an EPP timeout occurs if the attached	 *	device fails to respond after 10 micro seconds).	 *	 *	This bit is cleared by either reading it (National Semi)	 *	or writing a 1 to the bit (SMC, UMC, WinBond), others ???	 *	This bit is always high in non EPP modes.	 */	/* If EPP timeout bit clear then EPP available */	if (!clear_epp_timeout(pb))		return 0;  /* No way to clear timeout */	/* Check for Intel bug. */	if (priv->ecr) {		unsigned char i;		for (i = 0x00; i < 0x80; i += 0x20) {			outb (i, ECONTROL (pb));			if (clear_epp_timeout (pb))				/* Phony EPP in ECP. */				return 0;		}	}	pb->modes |= PARPORT_MODE_EPP;	/* Set up access functions to use EPP hardware. */	pb->ops->epp_read_data = parport_pc_epp_read_data;	pb->ops->epp_write_data = parport_pc_epp_write_data;	pb->ops->epp_read_addr = parport_pc_epp_read_addr;	pb->ops->epp_write_addr = parport_pc_epp_write_addr;	return 1;}static int __devinit parport_ECPEPP_supported(struct parport *pb){	struct parport_pc_private *priv = pb->private_data;	int result;	unsigned char oecr;	if (!priv->ecr)		return 0;	oecr = inb (ECONTROL (pb));	/* Search for SMC style EPP+ECP mode */	outb (0x80, ECONTROL (pb));	outb (0x04, CONTROL (pb));	result = parport_EPP_supported(pb);	outb (oecr, ECONTROL (pb));	if (result) {		/* Set up access functions to use ECP+EPP hardware. */		pb->ops->epp_read_data = parport_pc_ecpepp_read_data;		pb->ops->epp_write_data = parport_pc_ecpepp_write_data;		pb->ops->epp_read_addr = parport_pc_ecpepp_read_addr;		pb->ops->epp_write_addr = parport_pc_ecpepp_write_addr;	}	return result;}#else /* No IEEE 1284 support *//* Don't bother probing for modes we know we won't use. */static int __devinit parport_PS2_supported(struct parport *pb) { return 0; }static int __devinit parport_ECP_supported(struct parport *pb) { return 0; }static int __devinit parport_EPP_supported(struct parport *pb) { return 0; }static int __devinit parport_ECPEPP_supported(struct parport *pb){return 0;}static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;}#endif /* No IEEE 1284 support *//* --- IRQ detection -------------------------------------- *//* Only if supports ECP mode */static int __devinit programmable_irq_support(struct parport *pb){	int irq, intrLine;	unsigned char oecr = inb (ECONTROL (pb));	static const int lookup[8] = {		PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5	};	outb (ECR_CNF << 5, ECONTROL (pb)); /* Configuration MODE */	intrLine = (inb (CONFIGB (pb)) >> 3) & 0x07;	irq = lookup[intrLine];	outb (oecr, ECONTROL (pb));	return irq;}static int __devinit irq_probe_ECP(struct parport *pb){	int i;	unsigned long irqs;	sti();	irqs = probe_irq_on();			outb (ECR_SPP << 5, ECONTROL (pb)); /* Reset FIFO */	outb ((ECR_TST << 5) | 0x04, ECONTROL (pb));	outb (ECR_TST << 5, ECONTROL (pb));	/* If Full FIFO sure that writeIntrThreshold is generated */	for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02) ; i++) 		outb (0xaa, FIFO (pb));			pb->irq = probe_irq_off(irqs);	outb (ECR_SPP << 5, ECONTROL (pb));	if (pb->irq <= 0)		pb->irq = PARPORT_IRQ_NONE;	return pb->irq;}/* * This detection seems that only works in National Semiconductors * This doesn't work in SMC, LGS, and Winbond  */static int __devinit irq_probe_EPP(struct parport *pb){#ifndef ADVANCED_DETECT	return PARPORT_IRQ_NONE;#else	int irqs;	unsigned char oecr;	if (pb->modes & PARPORT_MODE_PCECR)		oecr = inb (ECONTROL (pb));	sti();	irqs = probe_irq_on();	if (pb->modes & PARPORT_MODE_PCECR)		frob_econtrol (pb, 0x10, 0x10);		clear_epp_timeout(pb);	parport_pc_frob_control (pb, 0x20, 0x20);	parport_pc_frob_control (pb, 0x10, 0x10);	clear_epp_timeout(pb);	/* Device isn't expecting an EPP read	 * and generates an IRQ.	 */	parport_pc_read_epp(pb);	udelay(20);	pb->irq = probe_irq_off (irqs);	if (pb->modes & PARPORT_MODE_PCECR)		outb (oecr, ECONTROL (pb));	parport_pc_write_control(pb, 0xc);	if (pb->irq <= 0)		pb->irq = PARPORT_IRQ_NONE;	return pb->irq;#endif /* Advanced detection */}static int __devinit irq_probe_SPP(struct parport *pb){	/* Don't even try to do this. */	return PARPORT_IRQ_NONE;}/* We will attempt to share interrupt requests since other devices * such as sound cards and network cards seem to like using the * printer IRQs. * * When ECP is available we can autoprobe for IRQs. * NOTE: If we can autoprobe it, we can register the IRQ. */static int __devinit parport_irq_probe(struct parport *pb){	const struct parport_pc_private *priv = pb->private_data;	if (priv->ecr) {		pb->irq = programmable_irq_support(pb);	}	if (pb->modes & PARPORT_MODE_ECP)		pb->irq = irq_probe_ECP(pb);	if (pb->irq == PARPORT_IRQ_NONE && priv->ecr &&	    (pb->modes & PARPORT_MODE_EPP))		pb->irq = irq_probe_EPP(pb);	clear_epp_timeout(pb);	if (pb->irq == PARPORT_IRQ_NONE && (pb->modes & PARPORT_MODE_EPP))		pb->irq = irq_probe_EPP(pb);	clear_epp_timeout(pb);	if (pb->irq == PARPORT_IRQ_NONE)		pb->irq = irq_probe_SPP(pb);	if (pb->irq == PARPORT_IRQ_NONE)		pb->irq = get_superio_irq(pb);	return pb->irq;}/* --- DMA detection -------------------------------------- *//* Only if chipset conforms to ECP ISA Interface Standard */static int __devinit programmable_dma_support (struct parport *p){	unsigned char oecr = inb (ECONTROL (p));	int dma;

⌨️ 快捷键说明

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