Subject: lance ethernet driver question (DS5k/1xx, 3min)
To: None <port-pmax@NetBSD.ORG>
From: Tad Hunt <tad@mail.csh.rit.edu>
List: port-pmax
Date: 02/26/1997 19:05:45
    Hey... I've posted before.  I'm working on porting plan9 to the
DS5k/100.  Anyway, I'm moving along fairly good (user processes are up
and running, serial, and clock are working)... Anyway, my next
step is to get the lance driver working.  I've gotten interrupts from
it, but when I decode the bits in the csr, the MISS bit is set.

>From the AM79C90 documentation:

	Bit 12	MISS	MISSED PACKET is set when the receiver loses a
			packet because it does not own any receive buffer,
			indicating loss of data.
			FIFO overflow is not reported because there is no
			receive ring entry in which to write status.
			When MISS is set, an interrupt will be generated
			if INEA=1.
			MISS is READ/CLEAR ONLY, and is set by the C-LANCE
			and cleared by writing a "1" into the bit.
			Writing a "0" has no effect.  It is cleared by RESET
			or by setting the STOP bit.

So what the csr seems to be telling me is that I'm giving it a bad address
for the receive buffer ring.  I'm pretty sure from looking through the
NetBSD source tree that I should be doing the following:

	ulong *ldp = IOASIC_REG_LANCE_DMAPTR(base);

	addr = allocate_some_memory(size=128k,align=128k);

	*ldp = addr << 3;

	initblk = addr;
	bufblk = addr + BYTES_PER_PAGE;

	/* build init block */

	put the following into the initblk:
		- mode
		- physical address
		- logical address map
		- rdralow = low order 16 bits of bufblk
		    /*
		     *top 3 bits of rdrahigh is the number of entries
		     * in the receive ring expressed as a power of 2
		     */
		- rdrahigh = rcv_buf_val << 13 | high order 8 bits of bufblk
		- tdralow = low order 16 bits of bufblk
		    /*
		     * top 3 bits of tdrahigh is the number of entries
		     * in the transmit ring expressed as a power of 2
		     */
		- tdrahigh = rcv_buf_val << 13 | high order 8 bits of bufblk

	/* give the init block to the lance */

	lance->rap = 1;					/* select csr 1 */
	lance->rdp = low order 16 bits of initblock	/* write */
	wbflush();
	lance->rap = 2;					/* select csr 2 */
	lance->rdp = high order 8 bits of initblock	/* write */
	wbflush();
	lance->rap = 3;	/* select csr 3 */
	lance->rdp = 0;	/* write busctl (BSWP=0 | ACON=0 | BCON=0) */
	wbflush();

	/* turn on interrupts, tell lance to read initblk and generate
	 * an IDON interrupt when it's done
	 */
	lance->rap = 0;
	lance->rdp = INEA|INIT|STRT;

Now, I know I must be doing something right because I am getting the IDON
interrupt.  However, after that, when the host receives a packet is when
I get the MISS error. csr0 == 0x90f3 <ERR,MISS,INTR,INEA,RXON,TXON,STRT,INIT>.

This is what I'm thinking:

    I use the lance dma register (named ldp above) to tell the asic which
    bits to logically AND with the address request from the lance.  If this
    is true, then the addresses I program into the lance (the start of the
    init block and the start of the data block) should simply be an offset
    from the value I programmed into the lance dma register (ldp).


Is this close to correct?

-Tad