Return to BSD News archive
Path: sserve!newshost.anu.edu.au!munnari.oz.au!network.ucsd.edu!ogicse!emory!europa.eng.gtefsd.com!uunet!Germany.EU.net!news From: bs@Germany.EU.net (Bernard Steiner) Newsgroups: comp.os.386bsd.development Subject: an lpt/lpa prbe that works Message-ID: <2ekdoq$c1g@Germany.EU.net> Date: 14 Dec 93 15:06:34 GMT Article-I.D.: Germany.2ekdoq$c1g Distribution: world Organization: EUnet Deutschland GmbH, Dortmund, Germany Lines: 80 NNTP-Posting-Host: qwerty.germany.eu.net Folks, Having fiddled with two different I/O cards, two cables and two printers, one of them with two dofferent sets of dip switch settings, I came to the conclusion that the probe routines supplied with all the drivers I've seen so far make wrong assumptions about the values returned from an inb() on the LPT control port. Please feel free to comment on the version below, and perhaps include it (or the underlying assumptions :) in future lpt/lpa drivers. Cheers, Bernard int lpaprobe(struct isa_device *idev) /* check whether the parallel port exists: return IO_LPTSIZE if so, 0 if not */ { u_char byte, odata, ocontrol, mask; /* save old bytes in case this is not a parallel port */ odata=inb(idev->id_iobase+lpt_data); ocontrol=inb(idev->id_iobase+lpt_control); outb(idev->id_iobase+lpt_control, 0x00); outb(idev->id_iobase+lpt_data, 0x00); if(inb(idev->id_iobase+lpt_data)==0x00) { outb(idev->id_iobase+lpt_data, 0xff); if(inb(idev->id_iobase+lpt_data)==0xff) { outb(idev->id_iobase+lpt_data, 0xaa); if(inb(idev->id_iobase+lpt_data)==0xaa) { outb(idev->id_iobase+lpt_data, 0x55); if(inb(idev->id_iobase+lpt_data)==0x55) { /* no other dirty tricks on the data port; do your own */ outb(idev->id_iobase+lpt_data, 0x00); /* Note: For the lpt control ports, the interface card could do anything with the upper three bits. Some printers drag the Strobe line, and some drag the SelectIn line. My first multi-IO sets Init with my Epson FX-85, and the second multi-IO clears AutoFd with a different dip switch setting but same cable and printer. Thus, only the stupid IRQ enable bit seems to be valid in every case. Alas, all is not lost ! Oh, yeah... "setting" means a 0-bit aka +5V */ mask=0x10; outb(idev->id_iobase+lpt_control, 0x00); if(((byte=inb(idev->id_iobase+lpt_control))&mask)==(mask&0x00)) { /* if a 0-bit Strobe, AutoFd or SelectIn stays, use it */ if((byte & 0x01)==0) mask|=0x01; if((byte & 0x02)==0) mask|=0x02; if((byte & 0x08)==0) mask|=0x08; outb(idev->id_iobase+lpt_control, 0xff); if(((byte=inb(idev->id_iobase+lpt_control))&mask)==(mask&0xff)) { /* if a 1-bit Init stays, use it */ mask|=(byte&0x04); outb(idev->id_iobase+lpt_control, 0x55); if((inb(idev->id_iobase+lpt_control)&mask)==(mask&0x55)) { outb(idev->id_iobase+lpt_control, 0xaa); if((inb(idev->id_iobase+lpt_control)&mask)==(mask&0xaa)) { /* no other dirty tricks on control port; do your own */ /* no other dirty tricks at all; do your own */ /* data port already 0'd (no dirty tricks) */ outb(idev->id_iobase+lpt_control, 0x00); return(IO_LPTSIZE); } } } } } } } } outb(idev->id_iobase+lpt_data, odata); outb(idev->id_iobase+lpt_control, ocontrol); return(0); }