Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 31 Aug 1995 05:17:15 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        hackers@freebsd.org, jdl@chrome.onramp.net
Subject:   Re: More ATAPI -- possible insight into probe problems...?
Message-ID:  <199508301917.FAA18876@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>Oh my!  Let's peek at my highly superior wd.c:
>...
>    #ifdef WDDEBUG_PROBE
>        printf("wd%d: checking RW register on port 0x%x + 0x%x\n",
>                unit, du->dk_port, wd_cyl_lo);
>    #endif

>        /* check if we have registers that work */
>        outb(du->dk_port + wd_cyl_lo, 0xa5);    /* wd_cyl_lo is read/write */
>        if (inb(du->dk_port + wd_cyl_lo) == 0xff)       /* XXX too weak */
>                goto nodevice;
>
>So who can tell me any details about that lovely weak check for R/W
>registers that appears to be failing for me?  Simple things like:

>    - Is this a valid register for a CDROM drive too? Ie, is this check
>      tacitly assuming a hard disk beneath it?
>    - Is it subject to timing problems?
>    - It *claims* to be "too weak", however it appears to be too strong!

It's too weak for ST506...EIDE controllers with normal drives attached.
These all have read/write registers, so the inb() should return what
was written.  That used to be tested for, but someone weakened the
test without documenting why.  I don't know what happens for CDROM
drives.

The point of the test is to attempt to limit the damage if there is
a device other than an ST506...EIDE controller behind the port.  It
is far too weak for that (if 0xff wasn't so magic, then the test
would have much less than a 1/256 chance of detecting conflicts).  
Even if it tested for `== 0xa5', then any device with a read/write
port at the probed address would pass the test.

The test is very sloppy.  It should do something like:

int
is_rw_port(port)
	u_int_port;
{
	u_char in1, in2, was;

	DELAY(5);
	was = inb(port);
	DELAY(5);
	outb(port, 0xa5);
	DELAY(5);
	(void)inb(0x20);	/* attempt to eliminate bus echoes */
	DELAY(5);
	in1 = inb(port);
	DELAY(5);
	outb(port, 0x5a);
	DELAY(5);
	(void)inb(0x20);
	DELAY(5);
	in2 = inb(port);
	DELAY(5);
	outb(port, was);
	DELAY(5);
	return (in1 == 0xa5 && in2 == 0x5a);
}
	...
	if (!is_rw_port(du->dk_port + wd_cyl_lo))
		goto nodevice;

Then the test would be stronger and your CDROM would be sure to fail :-).

Bruce



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199508301917.FAA18876>