[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Parallel port fails because /INIT held low



All,

	I've been studying this dratted printer port problem of mine.
	And so I'll share my thinking with you, if only because
	writing it down helps me :-)

	Assumption 1: linux lp code is correct in that lp_reset()
		for example does a parport_write_control( LP_PINITP)
		to *deassert* /INIT

		This is confirmed by some parallel port FAQs
		eg http://www.lvr.com/files/ibmlpt.txt which
		indicates that the register -> electrical path
		is non-inverting for "init"

		ie parport_write_control( LP_PINITP) sets the register bit = 1
		which in turn sets /INIT to 1 (Vcc)  which thus deasserts
		"init" from the printer's perspective.

	So we have a reasonable belief that parport_write_control (LP_PINITP)
	in the PC/linux world *DEASSERTS* init, ie /INIT goes to 1 (Vcc).

	Now under Cris-linux

		parport_write_control( LP_PINITP ) maps to
		parport_etrax_write_control( LP_PINITP )
		which for the "init" bit value maps to
		SETF( ..., R_PAR0_CTRL_DATA, init, 1)
			(assuming "(unsigned)LP_PINITP > 0"  == 1 and not -1, I forget )

		now the relevant bits (no pun intended) of SETF() use IO_FIELD()
		to set the init bit in the CTRL register to the given value (here == 1)

		Now "1" written into the init bit (refer Etrax100LX Desiger Ref Manual pg
19-105)
		means pin is "active".

		According to the documentation on page 105, 106 making init "active"
		means ASSERTING /p0init (the chip output pin), ie  /p0init -> 0 (Gnd)
		because it is active low.

	But there are two catches to this:

		1) the (flexible) Extrax100LX chip has a config register which can be used
			to INVERT the signal sense: 19.113 "iinit"
		2) The Developer LX board has a chip inverter on the output U1-C
			(refer schematic pg 10)

		The axis-cris parport driver init code SETS  iinit to INVERT.
		So the pin is inverted in the chip and then reinverted on the board.
		The nett effect of this is that 1) and 2) cancel each other out.


	So we end up with:

		(Note i've omitted the double inversion from iinit and U1-C)

			parport_write_control( LP_PINITP )	// in lp.c means "deassert /INIT"
		->	init_register=1
		->	assert(/p0init)
		->	/INIT = 0		// ie	"ASSERT /INIT"

		WHICH IS WRONG!!

		Or to be fairer, the etrax code is SELF consistent
		and the linux lp code is SELF consistent
		but the two have opposite interpretations of how LP_PINIT is used.

		Personally I think I prefer the Axis interpretion, I prefer
		to have cleared bits set to their default state, so that 0 should deassert
init.
		but that is just a personal preference.

	So how to fix?

		well I'm not touching the linux lp.c standard code
		and I'm not taking a soldering iron to the developer board

		I'm tossing up between
			a) changing parport_etrax_write_control() function
		and
			b) setting the "iinit" bit to non-inverting.

	BUT
		IO_STATE(.. init, inactive) needs to "do the right thing"
		Now inactive in THIS case is 0 (include/asm-cris/sv_addr.agh and pg
19-105)
		so register init = 0 (inactive) should deassert /INIT to be internally
		consistent with axis logic.

	So
			init_register=inactive
		->	init_register=0
		->	deassert(/p0init)
		->	/INIT = 1		// ie	"DEASSERT /INIT"

		WHICH IS CORRECT

		Now recall I am skipping over the double inversion within that sequence
		but this does mean that unless I redefine all the axis defines from
		their ASIC and docs etc I need to keep the double inversion intact.

	Therefore I cannot change the iinit config to non-inivert.

	Which means the bug is formally in the etrax <-> linux interface layer
	ie parport_etrax_write_control().

	So I gotta go hack that to be something like
		(control & LP_PINITP) == 0	// instead of > 0


	NOW I suppose I ahve to worry about which other status bits
	may be wrong too... (eg STROBE, AUTOFD, FAULT and SELECT_IN for output,
	and ACK, BUSY, SELECT, PAPER_ERROR on input)  *sigh*

	Hopefully since the ouputs at least are handled (I think) interally by
	the chip (in non-manual mode) that they are all correct
	and it is just the explicit linux-etrax 'manual' toggling that is wrong.

	Incidentally the lp_reset() also sets LP_PSELECP permanently
	to select the printer (I don't recall the exact use of this line)
	but it is also an active low, however my PC parallel port guide
	notes that it is an inverted pin in the PC world. ie register=high ==
output=low
	(the opposite of LP_PINITP)

	The extrax_write_control() does the same logic for all control bits, so it
	may be that this just happens to be correct.

	Taking this line of thinking AutoFd is also inverted in the PC world so
	it too is correct, and strobe is likewise correct (being inverted).
	Thus it seems that ONLY the /INIT line is "perverse" in the PC world.

	For etrax inputs (ack, bust, paper end, selectin) none of these are
inverted
	on the PCB... oh heck I'm sick of this...


	Well AXIS I think I;ve found bug#1
	change line 207 of the extrax parport.c (ver 1.8)
	from
		(control & PARPORT_CONTROL_INIT) > 0);

	to
		(control & PARPORT_CONTROL_INIT) == 0);

	Well now would someone care to comment on my logic and tell me if
	it is all rubbish and I've got the wrong end of the stick or what...

	Do I get a sweety ?

	regards
		kim

Kim Lester,
Senior Engineer,
Datafusion and Visualisation Systems

www.dfusion.com.au