Subject: Re: NetBSD support for the FSBE/S
To: None <pk@cs.few.eur.nl>
From: David S. Miller <davem@jenolan.rutgers.edu>
List: port-sparc
Date: 11/26/1996 17:58:12
   From: Paul Kranenburg <pk@cs.few.eur.nl>
   Date: Tue, 26 Nov 1996 22:45:37 +0100 (MET)

   Some (all?) FSBEs have a DMA chip revision 4 (aka DMA ESC gate
   array), which the current esp/dma combo does not
   recognise. Probably this DMA revision needs different treatment in
   a couple of places, but I've yet to find out what exactly that
   should be.

The differences for ESC gate array are:

	1) At boot time, must set DMA_ADD_ENABLE and clear
	   DMA_BCNT_ENAB.

#define DMA_ADD_ENABLE   0x00040000        /* Special ESC DVMA optimization */
#define DMA_BCNT_ENAB    0x00002000        /* If on, use the byte counter */

	   Then if sbus supports only 16 byte dma bursts, must
	   _set_ DMA_ESC_BURST.  If 32 byte bursts are supported
	   in the machine, this bit must be cleared.

#define DMA_ESC_BURST    0x00000800        /* 1=16byte 0=32byte */

	2) For setting up read and write DMA transfers it is pretty
	   much the same as the others, escept you must setup the
	   counter register and be careful about a hardware bug
	   in the chip.  Essential, looks like this:

struct ESC_registers {
  __volatile__ unsigned long cond_reg;   /* DMA condition register */
  __volatile__ char * st_addr;           /* Start address of this transfer */
  __volatile__ unsigned long cnt;        /* How many bytes to transfer */
  __volatile__ unsigned long dma_test;   /* DMA test register */
};

The code becomes..

	[ ... do normal control register dma setup here ... then ]
	if(setting_up_dma_for_beginning_of_cmd && this_is_an_ESC) {
		dregs->cnt = PAGE_SIZE;
	}

and...

	[ ... do normal control register dma setup here ... then ]
	if(setting_up_dma_for_data_transfer_phase && this_is_an_ESC) {
		unsigned long src = ((unsigned long) scsi_data_buf);
		unsigned long dest = src + transfer_count;

		/* ESC bug workaround. */
		if(dest & (PAGE_SIZE - 1))
			transfer_count = PAGE_ALIGN(transfer_count);
		dregs->cnt = transfer_count;
	}

Respectively.  For draining the ESC you just need to sit and watch
the DMA_FIFO_ISDRAIN bit in the control register and wait until it
clears before proceeding:

#define DMA_FIFO_ISDRAIN 0x0000000c        /* The DMA FIFO is draining */

That should make it work with zero problems.

--------------------------------------------////
Yow! 10.49 MB/s remote host TCP bandwidth  ////
over 100Mb/s ethernet.  Beat that!        ////
-----------------------------------------////__________  o
David S. Miller, davem@caip.rutgers.edu /_____________/ / // /_/ ><