Resent-Date: Fri, 14 May 1999 01:06:33 +0200 (MET DST)
Date: Thu, 13 May 1999 02:28:12 -0500
From: Chris Lawrence <quango@watervalley.net>
To: Linux/m68k Mailing List <linux-m68k@lists.linux-m68k.org>
Subject: A2091 diffs
Mail-Followup-To: Linux/m68k Mailing List <linux-m68k@lists.linux-m68k.org>
Organization: Kathie Lee's Sweatshops
X-Operating-System: Linux/ppc 2.2.3-pre1
Resent-From: linux-m68k@phil.uni-sb.de

The following diffs (after the .sig) implement the chip ram allocation
stuff from the GVP driver for the A2091.  The patch is tested (it's
providing DMA from my A2091).  This should improve performance
markedly for users of the A2091 on the A4000 (and other systems which
don't have 16 bit RAM in the Linux allocation space).

It's relative to the latest APUS kernel, but should be OK against any
recent kernel...


Chris, whose A4091 obviously isn't here yet ;-)
-- 
=============================================================================
|        Chris Lawrence        |         Get your Debian 2.1 CD-ROMs        |
|   <quango@watervalley.net>   |          http://www.lordsutch.com/         |
|                              |                                            |
|   Grad Student, Pol. Sci.    |   Visit the Lurker's Guide to Babylon 5:   |
|  University of Mississippi   |   <*> http://www.midwinter.com/lurk/ <*>   |
=============================================================================

--- linux-2.2.3pre1/drivers/scsi/a2091.c	Tue May 11 04:47:23 1999
+++ linux/drivers/scsi/a2091.c	Wed May 12 01:27:45 1999
@@ -56,6 +56,7 @@
     unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
     unsigned long addr = virt_to_bus(cmd->SCp.ptr);
     struct Scsi_Host *instance = cmd->host;
+    static int scsi_alloc_out_of_range = 0;
 
     /* don't allow DMA if the physical address is bad */
     if (addr & A2091_XFER_MASK ||
@@ -63,41 +64,55 @@
     {
 	HDATA(instance)->dma_bounce_len = (cmd->SCp.this_residual + 511)
 	    & ~0x1ff;
-	HDATA(instance)->dma_bounce_buffer =
-	    scsi_malloc (HDATA(instance)->dma_bounce_len);
-	
-	/* can't allocate memory; use PIO */
-	if (!HDATA(instance)->dma_bounce_buffer) {
-	    HDATA(instance)->dma_bounce_len = 0;
-	    return 1;
+ 	if( !scsi_alloc_out_of_range ) {
+	    HDATA(cmd->host)->dma_bounce_buffer =
+		scsi_malloc (HDATA(cmd->host)->dma_bounce_len);
+	    HDATA(cmd->host)->dma_buffer_pool = BUF_SCSI_ALLOCED;
 	}
 
-	/* get the physical address of the bounce buffer */
-	addr = virt_to_bus(HDATA(instance)->dma_bounce_buffer);
+	if ( scsi_alloc_out_of_range || !HDATA(cmd->host)->dma_bounce_buffer) {
+	    HDATA(cmd->host)->dma_bounce_buffer =
+		amiga_chip_alloc(HDATA(cmd->host)->dma_bounce_len);
+
+	    if(!HDATA(cmd->host)->dma_bounce_buffer)
+	    {
+		HDATA(cmd->host)->dma_bounce_len = 0;
+		return 1;
+	    }
 
-	/* the bounce buffer may not be in the first 16M of physmem */
-	if (addr & A2091_XFER_MASK) {
-	    /* we could use chipmem... maybe later */
-	    scsi_free (HDATA(instance)->dma_bounce_buffer,
-		       HDATA(instance)->dma_bounce_len);
-	    HDATA(instance)->dma_bounce_buffer = NULL;
-	    HDATA(instance)->dma_bounce_len = 0;
-	    return 1;
+	    HDATA(cmd->host)->dma_buffer_pool = BUF_CHIP_ALLOCED;
 	}
 
+	/* check if the address of the bounce buffer is OK */
+	addr = virt_to_bus(HDATA(cmd->host)->dma_bounce_buffer);
+
+	if (addr & A2091_XFER_MASK) {
+	    /* fall back to Chip RAM if address out of range */
+	    if( HDATA(cmd->host)->dma_buffer_pool == BUF_SCSI_ALLOCED) {
+		scsi_free (HDATA(cmd->host)->dma_bounce_buffer,
+			   HDATA(cmd->host)->dma_bounce_len);
+		scsi_alloc_out_of_range = 1;
+	    } else {
+		amiga_chip_free (HDATA(cmd->host)->dma_bounce_buffer);
+            }
+		
+	    HDATA(cmd->host)->dma_bounce_buffer =
+		amiga_chip_alloc(HDATA(cmd->host)->dma_bounce_len);
+
+	    if(!HDATA(cmd->host)->dma_bounce_buffer)
+	    {
+		HDATA(cmd->host)->dma_bounce_len = 0;
+		return 1;
+	    }
+
+	    addr = virt_to_bus(HDATA(cmd->host)->dma_bounce_buffer);
+	    HDATA(cmd->host)->dma_buffer_pool = BUF_CHIP_ALLOCED;
+	}
+	    
 	if (!dir_in) {
 	    /* copy to bounce buffer for a write */
-	    if (cmd->use_sg)
-#if 0
-		panic ("scsi%ddma: incomplete s/g support",
-		       instance->host_no);
-#else
-		memcpy (HDATA(instance)->dma_bounce_buffer,
-			cmd->SCp.ptr, cmd->SCp.this_residual);
-#endif
-	    else
-		memcpy (HDATA(instance)->dma_bounce_buffer,
-			cmd->request_buffer, cmd->request_bufflen);
+	    memcpy (HDATA(cmd->host)->dma_bounce_buffer,
+		    cmd->SCp.ptr, cmd->SCp.this_residual);
 	}
     }
 
@@ -164,32 +179,19 @@
 
     /* copy from a bounce buffer, if necessary */
     if (status && HDATA(instance)->dma_bounce_buffer) {
-	if (SCpnt && SCpnt->use_sg) {
-#if 0
-	    panic ("scsi%d: incomplete s/g support",
-		   instance->host_no);
-#else
-	    if( HDATA(instance)->dma_dir )
-		memcpy (SCpnt->SCp.ptr, 
-			HDATA(instance)->dma_bounce_buffer,
-			SCpnt->SCp.this_residual);
-	    scsi_free (HDATA(instance)->dma_bounce_buffer,
-		       HDATA(instance)->dma_bounce_len);
-	    HDATA(instance)->dma_bounce_buffer = NULL;
-	    HDATA(instance)->dma_bounce_len = 0;
-	    
-#endif
-	} else {
-	    if (HDATA(instance)->dma_dir && SCpnt)
-		memcpy (SCpnt->request_buffer,
-			HDATA(instance)->dma_bounce_buffer,
-			SCpnt->request_bufflen);
-
+	if (HDATA(instance)->dma_dir && SCpnt)
+	    memcpy (SCpnt->SCp.ptr, 
+		    HDATA(instance)->dma_bounce_buffer,
+		    SCpnt->SCp.this_residual);
+	
+	if (HDATA(instance)->dma_buffer_pool == BUF_SCSI_ALLOCED)
 	    scsi_free (HDATA(instance)->dma_bounce_buffer,
 		       HDATA(instance)->dma_bounce_len);
-	    HDATA(instance)->dma_bounce_buffer = NULL;
-	    HDATA(instance)->dma_bounce_len = 0;
-	}
+	else
+	    amiga_chip_free(HDATA(instance)->dma_bounce_buffer);
+	
+	HDATA(instance)->dma_bounce_buffer = NULL;
+	HDATA(instance)->dma_bounce_len = 0;
     }
 }
 

