patch-2.1.17 linux/drivers/scsi/gvp11.c

Next file: linux/drivers/scsi/gvp11.h
Previous file: linux/drivers/scsi/atari_scsi.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.16/linux/drivers/scsi/gvp11.c linux/drivers/scsi/gvp11.c
@@ -1,11 +1,12 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/blk.h>
+#include <linux/sched.h>
 #include <linux/version.h>
 
+#include <asm/setup.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/bootinfo.h>
 #include <asm/amigaints.h>
 #include <asm/amigahw.h>
 #include <asm/zorro.h>
@@ -29,7 +30,7 @@
 static struct Scsi_Host *first_instance = NULL;
 static Scsi_Host_Template *gvp11_template;
 
-static void gvp11_intr (int irq, struct pt_regs *fp, void *dummy)
+static void gvp11_intr (int irq, void *dummy, struct pt_regs *fp)
 {
     unsigned int status;
     struct Scsi_Host *instance;
@@ -49,15 +50,7 @@
     }
 }
 
-/*
- * DMA transfer mask for GVP Series II SCSI controller.
- * Some versions can only DMA into the 24 bit address space
- * (0->16M).  Others can DMA into the full 32 bit address
- * space.  The default is to only allow DMA into the 24 bit
- * address space.  The "gvp11=0xFFFFFFFE" setup parameter can
- * be supplied to force an alternate (32 bit) mask.
- */
-static int gvp11_xfer_mask = GVP11_XFER_MASK;
+static int gvp11_xfer_mask = 0;
 
 void gvp11_setup (char *str, int *ints)
 {
@@ -68,43 +61,60 @@
 {
     unsigned short cntr = GVP11_DMAC_INT_ENABLE;
     unsigned long addr = VTOP(cmd->SCp.ptr);
+    int bank_mask;
 
     /* don't allow DMA if the physical address is bad */
-    if (addr & gvp11_xfer_mask ||
+    if (addr & HDATA(cmd->host)->dma_xfer_mask ||
 	(!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual)))
     {
 	HDATA(cmd->host)->dma_bounce_len = (cmd->SCp.this_residual + 511)
 	    & ~0x1ff;
 	HDATA(cmd->host)->dma_bounce_buffer =
 	    scsi_malloc (HDATA(cmd->host)->dma_bounce_len);
+	HDATA(cmd->host)->dma_buffer_pool = BUF_SCSI_ALLOCED;
 	
-	/* can't allocate memory; use PIO */
 	if (!HDATA(cmd->host)->dma_bounce_buffer) {
-	    HDATA(cmd->host)->dma_bounce_len = 0;
-	    return 1;
+	    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;
+	    }
+
+	    HDATA(cmd->host)->dma_buffer_pool = BUF_CHIP_ALLOCED;
 	}
 
 	/* check if the address of the bounce buffer is OK */
 	addr = VTOP(HDATA(cmd->host)->dma_bounce_buffer);
 
-	if (addr & gvp11_xfer_mask) {
-	    scsi_free (HDATA(cmd->host)->dma_bounce_buffer,
-		       HDATA(cmd->host)->dma_bounce_len);
-	    HDATA(cmd->host)->dma_bounce_buffer = NULL;
-	    HDATA(cmd->host)->dma_bounce_len = 0;
-	    return 1;
+	if (addr & HDATA(cmd->host)->dma_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);
+	    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 = VTOP(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",
-		       cmd->host->host_no);
-#else
 		memcpy (HDATA(cmd->host)->dma_bounce_buffer,
 				cmd->SCp.ptr, cmd->SCp.this_residual);
-#endif
 	    else
 		memcpy (HDATA(cmd->host)->dma_bounce_buffer,
 			cmd->request_buffer, cmd->request_bufflen);
@@ -128,6 +138,9 @@
 	/* push any dirty cache */
 	cache_push (addr, cmd->SCp.this_residual);
 
+    if ((bank_mask = (~HDATA(cmd->host)->dma_xfer_mask >> 18) & 0x01c0))
+	    DMA(cmd->host)->BANK = bank_mask & (addr >> 18);
+
     /* start DMA */
     DMA(cmd->host)->ST_DMA = 1;
 
@@ -154,8 +167,13 @@
 		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);
+
+	    if (HDATA(instance)->dma_buffer_pool == BUF_SCSI_ALLOCED)
+		scsi_free (HDATA(instance)->dma_bounce_buffer,
+			    HDATA(instance)->dma_bounce_len);
+	    else
+		amiga_chip_free(HDATA(instance)->dma_bounce_buffer);
+
 	    HDATA(instance)->dma_bounce_buffer = NULL;
 	    HDATA(instance)->dma_bounce_len = 0;
 	    
@@ -166,82 +184,134 @@
 			HDATA(instance)->dma_bounce_buffer,
 			SCpnt->request_bufflen);
 
-	    scsi_free (HDATA(instance)->dma_bounce_buffer,
-		       HDATA(instance)->dma_bounce_len);
+	    if (HDATA(instance)->dma_buffer_pool == BUF_SCSI_ALLOCED)
+		scsi_free (HDATA(instance)->dma_bounce_buffer,
+			    HDATA(instance)->dma_bounce_len);
+	    else
+		amiga_chip_free(HDATA(instance)->dma_bounce_buffer);
+
 	    HDATA(instance)->dma_bounce_buffer = NULL;
 	    HDATA(instance)->dma_bounce_len = 0;
 	}
     }
 }
 
+static int num_gvp11 = 0;
+
 int gvp11_detect(Scsi_Host_Template *tpnt)
 {
     static unsigned char called = 0;
     struct Scsi_Host *instance;
-    int i, manuf, product, num_gvp11 = 0;
     caddr_t address;
     enum GVP_ident epc;
+    int key;
+    struct ConfigDev *cd;
 
     if (!MACH_IS_AMIGA || called)
 	return 0;
     called = 1;
 
     tpnt->proc_dir = &proc_scsi_gvp11;
+    tpnt->proc_info = &wd33c93_proc_info;
 
-    for (i = 0; i < boot_info.bi_amiga.num_autocon; i++)
-    {
-	manuf = boot_info.bi_amiga.autocon[i].cd_Rom.er_Manufacturer;
-	product = boot_info.bi_amiga.autocon[i].cd_Rom.er_Product;
-#if 0
-/* this seems to catch some non HD boards.  GVP is sooooo stupid */
-	if (manuf == MANUF_GVP &&
-	    ((product == PROD_GVPIISCSI) || (product == PROD_GVPIISCSI_2))) {
-#else
-        if (manuf == MANUF_GVP && product == PROD_GVPIISCSI) {
-#endif
-	    /* check extended product code */
-	    address = boot_info.bi_amiga.autocon[i].cd_BoardAddr;
-	    epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
-
-	    epc = epc & GVP_EPCMASK;
-
-	    /* 
-	     * This should (hopefully) be the correct way to identify
-	     * all the different GVP SCSI controllers (except for the
-	     * SERIES I though).
-	     */
-	    if (!((epc == GVP_A1291_SCSI) || 
-		  (epc == GVP_GFORCE_040_SCSI) ||
-		  (epc == GVP_GFORCE_030_SCSI) ||
-		  (epc == GVP_A530_SCSI) ||
-		  (epc == GVP_COMBO_R4_SCSI) ||
-		  (epc == GVP_COMBO_R3_SCSI) ||
-		  (epc == GVP_SERIESII)))
-		continue;
-
-	    instance = scsi_register (tpnt,
-				      sizeof (struct WD33C93_hostdata));
-	    instance->base = (unsigned char *)ZTWO_VADDR(address);
-	    DMA(instance)->secret2 = 1;
-	    DMA(instance)->secret1 = 0;
-	    DMA(instance)->secret3 = 15;
-	    while (DMA(instance)->CNTR & GVP11_DMAC_BUSY) ;
-	    DMA(instance)->CNTR = 0;
-	    wd33c93_init(instance, (wd33c93_regs *)&(DMA(instance)->SASR),
-			 dma_setup, dma_stop, WD33C93_FS_8_10);
-	    if (num_gvp11++ == 0) {
-		first_instance = instance;
-		gvp11_template = instance->hostt;
-		add_isr(IRQ_AMIGA_PORTS, gvp11_intr, 0, NULL, "GVP11 SCSI");
-	    }
-	    DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
+    while ((key = zorro_find(MANUF_GVP, PROD_GVPIISCSI, 0, 0))) {
+	cd = zorro_get_board(key);
+	address = cd->cd_BoardAddr;
+	/* check extended product code */
+	epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
+	epc = epc & GVP_PRODMASK;
+
+	/* 
+	 * This should (hopefully) be the correct way to identify
+	 * all the different GVP SCSI controllers (except for the
+	 * SERIES I though).
+	 */
+	if (!((epc == GVP_A1291_SCSI) || 
+	      (epc == GVP_GFORCE_040_SCSI) ||
+	      (epc == GVP_GFORCE_030_SCSI) ||
+	      (epc == GVP_A530_SCSI) ||
+	      (epc == GVP_COMBO_R4_SCSI) ||
+	      (epc == GVP_COMBO_R3_SCSI) ||
+	      (epc == GVP_SERIESII)))
+	    continue;
 
-#if 0 /* The Zorro stuff is not totally integrated yet ! */
-	    boot_info.bi_amiga.autocon_configured |= 1<<i;
-#endif
+	instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata));
+	instance->base = (unsigned char *)ZTWO_VADDR(address);
+	instance->irq = IRQ_AMIGA_PORTS & ~IRQ_MACHSPEC;
+	instance->unique_id = key;
+
+	if (gvp11_xfer_mask)
+		HDATA(instance)->dma_xfer_mask = gvp11_xfer_mask;
+	else{
+		switch (epc){
+		case GVP_COMBO_R3_SCSI:
+		case GVP_SERIESII:
+			HDATA(instance)->dma_xfer_mask = ~0x00ffffff;
+			break;
+		case GVP_GFORCE_030_SCSI:
+		case GVP_A530_SCSI:
+		case GVP_COMBO_R4_SCSI:
+			HDATA(instance)->dma_xfer_mask = ~0x01ffffff;
+			break;
+		default:
+			HDATA(instance)->dma_xfer_mask = ~0x07ffffff;
+			break;
+		}
+	}
 
+	DMA(instance)->secret2 = 1;
+	DMA(instance)->secret1 = 0;
+	DMA(instance)->secret3 = 15;
+	while (DMA(instance)->CNTR & GVP11_DMAC_BUSY) ;
+	DMA(instance)->CNTR = 0;
+
+	DMA(instance)->BANK = 0;
+
+	epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000);
+
+	/*
+	 * Check for 14MHz SCSI clock
+	 */
+	if (epc & GVP_SCSICLKMASK)
+	  wd33c93_init(instance, (wd33c93_regs *)&(DMA(instance)->SASR),
+		       dma_setup, dma_stop, WD33C93_FS_8_10);
+	else
+	  wd33c93_init(instance, (wd33c93_regs *)&(DMA(instance)->SASR),
+		       dma_setup, dma_stop, WD33C93_FS_12_15);
+
+	if (num_gvp11++ == 0) {
+	    first_instance = instance;
+	    gvp11_template = instance->hostt;
+	    request_irq(IRQ_AMIGA_PORTS, gvp11_intr, 0, "GVP11 SCSI", gvp11_intr);
 	}
+	DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE;
+	zorro_config_board(key, 0);
     }
 
     return num_gvp11;
+}
+
+
+#ifdef MODULE
+
+#define HOSTS_C
+
+#include "gvp11.h"
+
+Scsi_Host_Template driver_template = GVP11_SCSI;
+
+#include "scsi_module.c"
+
+#endif
+
+int gvp11_release(struct Scsi_Host *instance)
+{
+#ifdef MODULE
+DMA(instance)->CNTR = 0;
+zorro_unconfig_board(instance->unique_id, 0);
+if (--num_gvp11 == 0)
+  free_irq(IRQ_AMIGA_PORTS, gvp11_intr);
+  wd33c93_release();
+#endif
+return 1;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov