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
- Lines: 330
- Date:
Fri Dec 20 11:20:02 1996
- Orig file:
v2.1.16/linux/drivers/scsi/gvp11.c
- Orig date:
Fri Apr 26 10:30:51 1996
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