*BSD News Article 24976


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);
}