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

📄 ppw9xring0init.c

📁 simple MIPS EJTAG u-boot loader
💻 C
📖 第 1 页 / 共 2 页
字号:
	ring0_outb(0x55, pp_w9xring0_iobase+LPTREG_DATA);	if (ring0_inb(pp_w9xring0_iobase+LPTREG_DATA) != 0x55)		return 0;	return PARPORT_MODE_PCSPP;}/* Check for ECP * * 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 will write 0x2c to ECR and 0xcc to CTR since both of these * values are "safe" on the CTR since bits 6-7 of CTR are unused. */static int parport_ecr(void){	unsigned char r = 0xc;	ring0_outb(r, pp_w9xring0_iobase + LPTREG_CONTROL);	if ((ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & 0x3) == (r & 0x3)) {		ring0_outb(r ^ 0x2, pp_w9xring0_iobase + LPTREG_CONTROL); /* Toggle bit 1 */		r = ring0_inb(pp_w9xring0_iobase + LPTREG_CONTROL);			if ((ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & 0x2) == (r & 0x2))			goto no_reg; /* Sure that no ECR register exists */	}	if ((ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & 0x3 ) != 0x1)		goto no_reg;	ring0_outb(0x34, pp_w9xring0_iobase + LPTREG_ECONTROL);	if (ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) != 0x35)		goto no_reg;	ring0_outb(0xc, pp_w9xring0_iobase + LPTREG_CONTROL);		/* Go to mode 000 */	ring0_outb(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & ~0xe0, pp_w9xring0_iobase + LPTREG_ECONTROL);	return PARPORT_MODE_PCECR; no_reg:	ring0_outb(0xc, pp_w9xring0_iobase + LPTREG_CONTROL);	return 0; }static int parport_ecp(void){	int i;	int config;	int pword;	int fifo_depth, writeIntrThreshold, readIntrThreshold;	/* Find out FIFO depth */	ring0_outb(0x00, pp_w9xring0_iobase + LPTREG_ECONTROL); /* Reset FIFO */	ring0_outb(0xc0, pp_w9xring0_iobase + LPTREG_ECONTROL); /* TEST FIFO */	for (i=0; i < 1024 && !(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & 0x02); i++)		ring0_outb(0xaa, pp_w9xring0_iobase + LPTREG_TFIFO);	/*	 * Using LGS chipset it uses ECR register, but	 * it doesn't support ECP or FIFO MODE	 */	if (i == 1024) {		ring0_outb(0x00, pp_w9xring0_iobase + LPTREG_ECONTROL);		return 0;	}	fifo_depth = i;	lprintf(3, "ECP: FIFO depth is %d bytes\n", fifo_depth);	/* Find out writeIntrThreshold */	ring0_outb(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) | (1<<2), pp_w9xring0_iobase + LPTREG_ECONTROL);	ring0_outb(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & ~(1<<2) , pp_w9xring0_iobase + LPTREG_ECONTROL);	for (i = 1; i <= fifo_depth; i++) {		ring0_inb(pp_w9xring0_iobase + LPTREG_TFIFO);		usleep(50);		if (ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & (1<<2))			break;	}	if (i <= fifo_depth)		lprintf(3, "ECP: writeIntrThreshold is %d\n", i);	else		/* Number of bytes we know we can write if we get an                   interrupt. */		i = 0;	writeIntrThreshold = i;	/* Find out readIntrThreshold */	ring0_outb((ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & ~0xe0) | 0x20, pp_w9xring0_iobase + LPTREG_ECONTROL); /* Reset FIFO, PS2 */	ring0_outb(ring0_inb(pp_w9xring0_iobase + LPTREG_CONTROL) | PARPORT_CONTROL_DIRECTION, pp_w9xring0_iobase + LPTREG_CONTROL);	ring0_outb((ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & ~0xe0) | 0xc0, pp_w9xring0_iobase + LPTREG_ECONTROL); /* Test FIFO */	ring0_outb(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) | (1<<2), pp_w9xring0_iobase + LPTREG_ECONTROL);	ring0_outb(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & ~(1<<2) , pp_w9xring0_iobase + LPTREG_ECONTROL);	for (i = 1; i <= fifo_depth; i++) {		ring0_outb(0xaa, pp_w9xring0_iobase + LPTREG_TFIFO);		if (ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & (1<<2))			break;	}	if (i <= fifo_depth)		lprintf(3, "ECP: readIntrThreshold is %d\n", i);	else		/* Number of bytes we can read if we get an interrupt. */		i = 0;	readIntrThreshold = i;	ring0_outb(0x00, pp_w9xring0_iobase + LPTREG_ECONTROL); /* Reset FIFO */	ring0_outb(0xf4, pp_w9xring0_iobase + LPTREG_ECONTROL); /* Configuration mode */	config = ring0_inb(pp_w9xring0_iobase + LPTREG_CONFIGA);	pword = (config >> 4) & 0x7;	switch (pword) {	case 0:		pword = 2;		lprintf(0, "ECP: Unsupported pword size! (2)\n");		break;	case 2:		pword = 4;		lprintf(0, "ECP: Unsupported pword size! (4)\n");		break;	default:		lprintf(0, "ECP: Unknown implementation ID (%d)\n", pword);		/* Assume 1 */	case 1:		pword = 1;	}	lprintf(3, "ECP: PWord is %d bits\n", 8 * pword);	config = ring0_inb(pp_w9xring0_iobase + LPTREG_CONFIGB);	lprintf(3, "ECP: Interrupts are ISA-%s\n", config & 0x80 ? "Level" : "Pulses");	if (!(config & 0x40))		lprintf(3, "ECP: IRQ conflict!\n");	/* Go back to mode 000 */	ring0_outb(ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL) & ~0xe0, pp_w9xring0_iobase + LPTREG_ECONTROL);	return PARPORT_MODE_PCECP;}/* EPP mode detection  */static int parport_epp(void){	/* If EPP timeout bit clear then EPP available */	if (!pp_w9xring0_epp_clear_timeout())		return 0;  /* No way to clear timeout */	/*	 * Theory:	 *     Write two values to the EPP address register and	 *     read them back. When the transfer times out, the state of	 *     the EPP register is undefined in some cases (EPP 1.9?) but	 *     in others (EPP 1.7, ECPEPP?) it is possible to read back	 *     its value.	 */	pp_w9xring0_epp_clear_timeout();	usleep(30); /* Wait for possible EPP timeout */	ring0_outb(0x55, pp_w9xring0_iobase + LPTREG_EPPADDR);	pp_w9xring0_epp_clear_timeout();	usleep(30); /* Wait for possible EPP timeout */	if (ring0_inb(pp_w9xring0_iobase + LPTREG_EPPADDR) == 0x55) {		ring0_outb(0xaa, pp_w9xring0_iobase + LPTREG_EPPADDR);		pp_w9xring0_epp_clear_timeout();		usleep(30); /* Wait for possible EPP timeout */		if (ring0_inb(pp_w9xring0_iobase + LPTREG_EPPADDR) == 0xaa) {			pp_w9xring0_epp_clear_timeout();			return PARPORT_MODE_PCEPP;		}	}	/*	 * 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, Wring0_inbond), others ???	 *	This bit is always high in non EPP modes.	 */	ring0_outb(ring0_inb(pp_w9xring0_iobase + LPTREG_CONTROL) | 0x20, pp_w9xring0_iobase + LPTREG_CONTROL);	ring0_outb(ring0_inb(pp_w9xring0_iobase + LPTREG_CONTROL) | 0x10, pp_w9xring0_iobase + LPTREG_CONTROL);	pp_w9xring0_epp_clear_timeout();		ring0_inb(pp_w9xring0_iobase + LPTREG_EPPDATA);	usleep(30);  /* Wait for possible EPP timeout */		if (ring0_inb(pp_w9xring0_iobase + LPTREG_STATUS) & 0x01) {		pp_w9xring0_epp_clear_timeout();		return PARPORT_MODE_PCEPP;	}	return 0;}static int parport_ecpepp(void){	int mode;	unsigned char oecr;	oecr = ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL);	/* Search for SMC style EPP+ECP mode */	ring0_outb(0x80, pp_w9xring0_iobase + LPTREG_ECONTROL);	mode = parport_epp();	ring0_outb(oecr, pp_w9xring0_iobase + LPTREG_ECONTROL);       	return mode ? PARPORT_MODE_PCECPEPP : 0;}/* Detect PS/2 support. * * Bit 5 (0x20) sets the PS/2 data w9xring0ion; 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 parport_ps2(void){	int ok = 0;	unsigned char octr = ring0_inb(pp_w9xring0_iobase + LPTREG_CONTROL);  	pp_w9xring0_epp_clear_timeout();	ring0_outb(octr | 0x20, pp_w9xring0_iobase + LPTREG_CONTROL);  /* try to tri-state the buffer */		ring0_outb(0x55, pp_w9xring0_iobase + LPTREG_DATA);	if (ring0_inb(pp_w9xring0_iobase + LPTREG_DATA) != 0x55) ok++;	ring0_outb(0xaa, pp_w9xring0_iobase + LPTREG_DATA);	if (ring0_inb(pp_w9xring0_iobase + LPTREG_DATA) != 0xaa) ok++;	ring0_outb(octr, pp_w9xring0_iobase);          /* cancel input mode */	return ok ? PARPORT_MODE_PCPS2 : 0;}static int parport_ecpps2(void){	int mode;	unsigned char oecr;	oecr = ring0_inb(pp_w9xring0_iobase + LPTREG_ECONTROL);	ring0_outb(0x20, pp_w9xring0_iobase + LPTREG_ECONTROL);      	mode = parport_ps2();	ring0_outb(oecr, pp_w9xring0_iobase + LPTREG_ECONTROL);	return mode ? PARPORT_MODE_PCECPPS2 : 0;}/* ---------------------------------------------------------------------- */int parport_init_w9xring0_flags(unsigned io, unsigned int flags){	pp_w9xring0_flags = FLAGS_PCSPP;	pp_w9xring0_iobase = io;       	if (iopl(3)) {		lprintf(0, "Cannot get direct IO port access (iopl: %s)\n", strerror(errno));		return -1;	}	if (!parport_spp()) {		lprintf(0, "No parport present at 0x%x\n", pp_w9xring0_iobase);		return -1;	}	if (parport_ecr()) {		pp_w9xring0_flags |= FLAGS_PCECR;		pp_w9xring0_flags |= parport_ecp();		pp_w9xring0_flags |= parport_ecpps2();		pp_w9xring0_flags |= parport_ecpepp();		if ((flags & PPFLAG_FORCEHWEPP) && 		    (pp_w9xring0_flags & (FLAGS_PCPS2|FLAGS_PCECPPS2)) &&		    !(pp_w9xring0_flags & (FLAGS_PCEPP|FLAGS_PCECPEPP)))			pp_w9xring0_flags |= FLAGS_PCECPEPP;		else			flags &= ~PPFLAG_FORCEHWEPP;	} else {		pp_w9xring0_flags |= parport_ps2();		pp_w9xring0_flags |= parport_epp();		if ((flags & PPFLAG_FORCEHWEPP) && 		    (pp_w9xring0_flags & (FLAGS_PCPS2|FLAGS_PCECPPS2)) &&		    !(pp_w9xring0_flags & (FLAGS_PCEPP|FLAGS_PCECPEPP)))			pp_w9xring0_flags |= FLAGS_PCEPP;		else			flags &= ~PPFLAG_FORCEHWEPP;	}	lprintf(0, "Parport 0x%x capabilities: SPP%s%s%s%s%s%s\n",		pp_w9xring0_iobase,		(pp_w9xring0_flags & FLAGS_PCPS2) ? ", PS2" : "",		(pp_w9xring0_flags & FLAGS_PCEPP) ? ((flags & PPFLAG_FORCEHWEPP) ? ", EPP (forced)" : ", EPP") : "",		(pp_w9xring0_flags & FLAGS_PCECR) ? ", ECR" : "",		(pp_w9xring0_flags & FLAGS_PCECP) ? ", ECP" : "",		(pp_w9xring0_flags & FLAGS_PCECPEPP) ? ((flags & PPFLAG_FORCEHWEPP) ? ", ECPEPP (forced)" : ", ECPEPP") : "",		(pp_w9xring0_flags & FLAGS_PCECPPS2) ? ", ECPPS2" : "");	if (!(pp_w9xring0_flags & (FLAGS_PCPS2 | FLAGS_PCECPPS2)))  {		lprintf(0, "Parport 0x%x does not even support PS/2 mode, cannot use it\n",			pp_w9xring0_iobase);		return -1;	}	lprintf(0, "Parport 0x%x using direct Win9x Ring0 hardware access\n", pp_w9xring0_iobase);	if (pp_w9xring0_flags & FLAGS_PCECR)		ring0_outb(0x30, pp_w9xring0_iobase + LPTREG_ECONTROL); /* PS/2 mode */	parport_ops = parport_w9xring0_ops;	if ((flags & PPFLAG_SWEMULECP) || !(pp_w9xring0_flags & FLAGS_PCECP)) {		parport_ops.parport_ecp_write_data = parport_w9xring0_emul_ops.parport_ecp_write_data;		parport_ops.parport_ecp_read_data = parport_w9xring0_emul_ops.parport_ecp_read_data;		parport_ops.parport_ecp_write_addr = parport_w9xring0_emul_ops.parport_ecp_write_addr;		lprintf(0, "Parport 0x%x emulating ECP\n", pp_w9xring0_iobase);	}	if ((flags & PPFLAG_SWEMULEPP) || !(pp_w9xring0_flags & (FLAGS_PCEPP | FLAGS_PCECPEPP))) {		parport_ops.parport_epp_write_data = parport_w9xring0_emul_ops.parport_epp_write_data;		parport_ops.parport_epp_read_data = parport_w9xring0_emul_ops.parport_epp_read_data;		parport_ops.parport_epp_write_addr = parport_w9xring0_emul_ops.parport_epp_write_addr;		parport_ops.parport_epp_read_addr = parport_w9xring0_emul_ops.parport_epp_read_addr;		lprintf(0, "Parport 0x%x emulating EPP\n", pp_w9xring0_iobase);	}	return 0;}int parport_init_w9xring0(unsigned io){        return parport_init_w9xring0_flags(io, 0);}

⌨️ 快捷键说明

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