Bug 16078
Summary: | ECP port not detected on IBM Thinkpad i1492 | ||
---|---|---|---|
Product: | [Retired] Red Hat Linux | Reporter: | d_rosky |
Component: | kernel | Assignee: | Michael K. Johnson <johnsonm> |
Status: | CLOSED WONTFIX | QA Contact: | |
Severity: | medium | Docs Contact: | |
Priority: | medium | ||
Version: | 6.2 | CC: | twaugh |
Target Milestone: | --- | ||
Target Release: | --- | ||
Hardware: | i386 | ||
OS: | Linux | ||
Whiteboard: | |||
Fixed In Version: | Doc Type: | Bug Fix | |
Doc Text: | Story Points: | --- | |
Clone Of: | Environment: | ||
Last Closed: | 2001-06-05 14:47:19 UTC | Type: | --- |
Regression: | --- | Mount Type: | --- |
Documentation: | --- | CRM: | |
Verified Versions: | Category: | --- | |
oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
Cloudforms Team: | --- | Target Upstream Version: | |
Embargoed: |
Description
d_rosky
2000-08-12 21:04:19 UTC
Tim, any thoughts? Please do this: # dmesg -c # insmod parport # insmod parport_pc io=0x378 # dmesg > logfile and attach the logfile so we can see what the driver says. (Use the 2.2.16-3 kernel.) I have some additional information regarding this bug. I have been able to get the National PC97338 parallel port in my Thinkpad to work in ECP mode. The problem appears to be that the BIOS does not configure the chip properly for ECP mode when ECP mode is selected in the BIOS setup. I downloaded the PC97338 data sheet from National and eventually figured out that although the BIOS was setting the ECP mode bit in the parallel port control register (0x04), it was not resetting the EPP mode bit. Apparently this puts the chip into an undefined state which makes it appear on the I/O bus as if it has only SPP capabilities. Unfortunately, I didn't save the direct link to the datasheet download, but it can be found by navigating from www.national.com It is possible to detect the presence of the PC87338/97338 chip and set the configuration registers properly even if the BIOS hasn't. There still is a "bug" in the current Linux kernel driver in that it apparently doesn't try to detect and configure the actual chip - it depends on correct BIOS setup and then detects the port type from the I/O register behavior. Windows 98, on the other hand, apparently detects and configures the chip properly, because ECP mode worked OK in Win98. The PC87338/97338 datasheet has a complete description of how to detect the presence of a PC87338/97338 by probing for its configuration registers. I have not tried any of the 2.3 or 2.4 kernels, so I don't know if these kernels have improved I/O chip detection. If they do, this bug may be moot. If not, the problem probably belongs in the hands of the kernel parport developers. The following program is a modified version of a program I found from the Linux parport mailing list archive. I fixed a bug and modified it to detect the PC87338/97338 instead of the older chips it was originally written for. This program operates a little differently than the detection description in the datasheet, but it seems to work and I have put it at the end of my /etc/rc.d/rc.sysinit script: #include <asm/io.h> #ifndef __KERNEL__ #include <stdio.h> #include <unistd.h> #define PPA_PROBE_SPP 0x0001 #define PPA_PROBE_PS2 0x0002 #define PPA_PROBE_ECR 0x0010 #define PPA_PROBE_EPP17 0x0100 #define PPA_PROBE_EPP19 0x0200 #define PPA_ID "" int pc87338_port(unsigned short base); void main(void) { if (iopl(3)) { fprintf(stderr, "Could not unlock IO ports. Are you superuser?\n"); exit(1); } pc87338_port(0x3bc); pc87338_port(0x278); pc87338_port(0x378); } #else #include <linux/kernel.h> #define printf printk #define PPA_ID "ppa: " #endif int pc87338_port(unsigned short base) { /* A routine to detect and kludge pc87338 chipsets into the * ECP mode... */ /* This is where an pc87338 can hide */ unsigned short index_addr[4] = { 0x0398, 0x026e, 0x015c, 0x002e }; /* Bits 0&1 of FAR (Function Address Register) which specify where * the LPT port will show up at. */ unsigned short port_ref[4] = { 0x378, 0x3bc, 0x278, 0xffff }; unsigned char a; int loop; for (loop = 0; loop < 4; loop++) { /* Clear the "wax" out of the pc87338, only needed after hard * reset. */ inb(index_addr[loop]); inb(index_addr[loop]); inb(index_addr[loop]); inb(index_addr[loop]); /* Anyone home ?? */ outb(0xff, index_addr[loop]); a = inb(index_addr[loop]); /* printf("0x%02x\n", a); */ switch (a) { case (0x7f): /* PC87338 */ break; default: continue; } /* Is this pc87338 on the desired port */ outb(0x01, index_addr[loop]); a = inb(index_addr[loop] + 1); if (port_ref[a & 0x03] != base) continue; /* Found a pc87338 */ printf("NatSemi PC87338 (or variant) at 0x%04x\n", base); printf(" Config registers at 0x%04x\n", index_addr[loop]); /* Try to enable EPP modes * with hardware data direction */ /* The following has been modified to set ECP mode regardless of the base address */ if (0) { printf(" Switching to EPP mode\n"); /* EPP 1.9 */ outb(0x04, index_addr[loop]); a = inb(index_addr[loop] + 1); /* 0x01 for EPP 1.7, 0x03 for EPP 1.9, 0x0c for ECP */ a = (a & 0xf0) | 0x03; outb(a, index_addr[loop] + 1); outb(a, index_addr[loop] + 1); /* Software data direction selection */ outb(0x02, index_addr[loop]); a = inb(index_addr[loop] + 1); /* 0x80 for software, 0x00 for hardware */ a = (a & 0x7f) | 0x80; outb(a, index_addr[loop] + 1); outb(a, index_addr[loop] + 1); } else { /* There is not enough address space for the 0x3bc port * to have EPP registers so we will kludge it into an * ECP * port to allow bi-directional byte mode... */ printf(" Switching to ECP mode\n"); /* ECP */ outb(0x04, index_addr[loop]); a = inb(index_addr[loop] + 1); a = (a & 0xfe) | 0x06; outb(a, index_addr[loop] + 1); outb(a, index_addr[loop] + 1); } outb(0x04, index_addr[loop]); a = inb(index_addr[loop] + 1); return 1; } return 0; } Arguably, this is a better approach than getting the kernel to do it. I'll have a think about it. Come to think of it the code to do this is already in the 2.4 tree, but under a config option ISTR. You can't just go blatting at I/O ports like 0x2e since it can have all kinds of bad effects if you don't have one of these chips. Agreed. This chip is an ISA device, and as with any ISA device autodetecting it can be a bit tricky subject to conflicts. The device data sheet (downloadable from www.national.com) has some tips for safely detecting it. If devices like this can be detected and configured at boot time, it would provide a measure of protection against buggy BIOS's. Hopefully this will be all sorted out when the PnPBIOS code gets merged into 2.4.x. (It's in the -ac tree currently.) |