summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorThomas Bogendoerfer <tsbogend@alpha.franken.de>1998-05-12 19:25:07 +0000
committerThomas Bogendoerfer <tsbogend@alpha.franken.de>1998-05-12 19:25:07 +0000
commit3b23e8acfab7fa5522ce96c58335607fe235562a (patch)
tree16750d1f63fa922c69693fca1ed8f2b2b8bc7d14 /drivers/scsi
parenteceef87159b136a4a21395112b888e232ea8df76 (diff)
removed changes to esp. now esp is the sparc only driver from 2.1.99
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/Makefile6
-rw-r--r--drivers/scsi/esp.c1496
-rw-r--r--drivers/scsi/esp.h221
-rw-r--r--drivers/scsi/hosts.c2
-rw-r--r--drivers/scsi/sparc_esp.c638
-rw-r--r--drivers/scsi/sparc_esp.h42
6 files changed, 1014 insertions, 1391 deletions
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 28ef6bbad..892f81e23 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -286,10 +286,10 @@ else
endif
ifeq ($(CONFIG_SCSI_SUNESP),y)
-L_OBJS += esp.o sparc_esp.o
+L_OBJS += esp.o
else
ifeq ($(CONFIG_SCSI_SUNESP),m)
- M_OBJS += esp.o sparc_esp.o
+ M_OBJS += esp.o
endif
endif
@@ -471,7 +471,7 @@ else
endif
ifeq ($(CONFIG_JAZZ_ESP),y)
-L_OBJS += esp.o jazz_esp.o
+L_OBJS += NCR53C9x.o jazz_esp.o
endif
include $(TOPDIR)/Rules.make
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index eb6ea16db..57b84add6 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -1,8 +1,6 @@
/* esp.c: EnhancedScsiProcessor Sun SCSI driver code.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- *
- * Ugly generalization hacks by Jesper Skov (jskov@cs.auc.dk)
*/
/* TODO:
@@ -29,21 +27,103 @@
#include "hosts.h"
#include "esp.h"
-#ifdef CONFIG_SCSI_SUNESP
-#include "sparc_esp.h"
#include <asm/sbus.h>
#include <asm/dma.h>
+#include <asm/system.h>
#include <asm/machines.h>
+#include <asm/ptrace.h>
+#include <asm/pgtable.h>
#include <asm/oplib.h>
+#include <asm/io.h>
#include <asm/irq.h>
#include <asm/idprom.h>
+#include <asm/spinlock.h>
+
+#define DEBUG_ESP
+/* #define DEBUG_ESP_HME */
+/* #define DEBUG_ESP_DATA */
+/* #define DEBUG_ESP_QUEUE */
+/* #define DEBUG_ESP_DISCONNECT */
+/* #define DEBUG_ESP_STATUS */
+/* #define DEBUG_ESP_PHASES */
+/* #define DEBUG_ESP_WORKBUS */
+/* #define DEBUG_STATE_MACHINE */
+/* #define DEBUG_ESP_CMDS */
+/* #define DEBUG_ESP_IRQS */
+/* #define DEBUG_SDTR */
+/* #define DEBUG_ESP_SG */
+
+/* Use the following to sprinkle debugging messages in a way which
+ * suits you if combinations of the above become too verbose when
+ * trying to track down a specific problem.
+ */
+/* #define DEBUG_ESP_MISC */
+
+#if defined(DEBUG_ESP)
+#define ESPLOG(foo) printk foo
+#else
+#define ESPLOG(foo)
+#endif /* (DEBUG_ESP) */
+
+#if defined(DEBUG_ESP_HME)
+#define ESPHME(foo) printk foo
+#else
+#define ESPHME(foo)
#endif
-#include <asm/spinlock.h>
-#include <asm/system.h>
-#include <asm/ptrace.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
+#if defined(DEBUG_ESP_DATA)
+#define ESPDATA(foo) printk foo
+#else
+#define ESPDATA(foo)
+#endif
+
+#if defined(DEBUG_ESP_QUEUE)
+#define ESPQUEUE(foo) printk foo
+#else
+#define ESPQUEUE(foo)
+#endif
+
+#if defined(DEBUG_ESP_DISCONNECT)
+#define ESPDISC(foo) printk foo
+#else
+#define ESPDISC(foo)
+#endif
+
+#if defined(DEBUG_ESP_STATUS)
+#define ESPSTAT(foo) printk foo
+#else
+#define ESPSTAT(foo)
+#endif
+
+#if defined(DEBUG_ESP_PHASES)
+#define ESPPHASE(foo) printk foo
+#else
+#define ESPPHASE(foo)
+#endif
+
+#if defined(DEBUG_ESP_WORKBUS)
+#define ESPBUS(foo) printk foo
+#else
+#define ESPBUS(foo)
+#endif
+
+#if defined(DEBUG_ESP_IRQS)
+#define ESPIRQ(foo) printk foo
+#else
+#define ESPIRQ(foo)
+#endif
+
+#if defined(DEBUG_SDTR)
+#define ESPSDTR(foo) printk foo
+#else
+#define ESPSDTR(foo)
+#endif
+
+#if defined(DEBUG_ESP_MISC)
+#define ESPMISC(foo) printk foo
+#else
+#define ESPMISC(foo)
+#endif
/* Command phase enumeration. */
enum {
@@ -87,11 +167,13 @@ struct proc_dir_entry proc_scsi_esp = {
S_IFDIR | S_IRUGO | S_IXUGO, 2
};
-struct Sparc_ESP *espchain = 0;
-int nesps = 0, esps_in_use = 0, esps_running = 0;
+/* The master ring of all esp hosts we are managing in this driver. */
+static struct Sparc_ESP *espchain;
+static int esps_running = 0;
-void esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
-void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+/* Forward declarations. */
+static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+static void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
/* Debugging routines */
struct esp_cmdstrings {
@@ -213,7 +295,7 @@ static inline void esp_print_seqreg(unchar stepreg)
(stepreg == ESP_STEP_FINI4 ? "CMD_SENT_OK" :
"UNKNOWN"))))));
}
-#if defined(DEBUG_STATE_MACHINE) || defined(DEBUG_ESP)
+
static char *phase_string(int phase)
{
switch(phase) {
@@ -269,7 +351,6 @@ static char *phase_string(int phase)
return "UNKNOWN";
};
}
-#endif
static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase)
{
@@ -280,7 +361,7 @@ static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase)
s->SCp.phase = newphase;
}
-extern inline void esp_cmd(struct Sparc_ESP *esp, struct ESP_regs *eregs,
+extern inline void esp_cmd(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
unchar cmd)
{
#ifdef DEBUG_ESP_CMDS
@@ -372,10 +453,78 @@ static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
return ptr;
}
-/* Resetting various pieces of the ESP scsi driver chipset */
+/* Resetting various pieces of the ESP scsi driver chipset/buses. */
+static inline void esp_reset_dma(struct Sparc_ESP *esp)
+{
+ struct sparc_dma_registers *dregs = esp->dregs;
+ unsigned long tmp, flags;
+ int can_do_burst16, can_do_burst32;
+
+ can_do_burst16 = esp->bursts & DMA_BURST16;
+ can_do_burst32 = esp->bursts & DMA_BURST32;
+
+ /* Punt the DVMA into a known state. */
+ if(esp->dma->revision != dvmahme) {
+ dregs->cond_reg |= DMA_RST_SCSI;
+ dregs->cond_reg &= ~(DMA_RST_SCSI);
+ }
+ switch(esp->dma->revision) {
+ case dvmahme:
+ /* This is the HME DVMA gate array. */
+
+ save_flags(flags); cli(); /* I really hate this chip. */
+
+ dregs->cond_reg = 0x08000000; /* Reset interface to FAS */
+ dregs->cond_reg = DMA_RST_SCSI; /* Reset DVMA itself */
+
+ tmp = (DMA_PARITY_OFF|DMA_2CLKS|DMA_SCSI_DISAB|DMA_INT_ENAB);
+ tmp &= ~(DMA_ENABLE|DMA_ST_WRITE|DMA_BRST_SZ);
+
+ if(can_do_burst32)
+ tmp |= DMA_BRST32;
+
+ /* This chip is horrible. */
+ while(dregs->cond_reg & DMA_PEND_READ)
+ udelay(1);
+
+ dregs->cond_reg = 0;
+
+ dregs->cond_reg = tmp; /* bite me */
+ restore_flags(flags); /* ugh... */
+ break;
+ case dvmarev2:
+ /* This is the gate array found in the sun4m
+ * NCR SBUS I/O subsystem.
+ */
+ if(esp->erev != esp100)
+ dregs->cond_reg |= DMA_3CLKS;
+ break;
+ case dvmarev3:
+ dregs->cond_reg &= ~(DMA_3CLKS);
+ dregs->cond_reg |= DMA_2CLKS;
+ if(can_do_burst32) {
+ dregs->cond_reg &= ~(DMA_BRST_SZ);
+ dregs->cond_reg |= DMA_BRST32;
+ }
+ break;
+ case dvmaesc1:
+ /* This is the DMA unit found on SCSI/Ether cards. */
+ dregs->cond_reg |= DMA_ADD_ENABLE;
+ dregs->cond_reg &= ~DMA_BCNT_ENAB;
+ if(!can_do_burst32 && can_do_burst16) {
+ dregs->cond_reg |= DMA_ESC_BURST;
+ } else {
+ dregs->cond_reg &= ~(DMA_ESC_BURST);
+ }
+ break;
+ default:
+ break;
+ };
+ DMA_INTSON(dregs);
+}
/* Reset the ESP chip, _not_ the SCSI bus. */
-static inline void esp_reset_esp(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline void esp_reset_esp(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
{
int family_code, version, i;
volatile int trash;
@@ -384,41 +533,36 @@ static inline void esp_reset_esp(struct Sparc_ESP *esp, struct ESP_regs *eregs)
esp_cmd(esp, eregs, ESP_CMD_RC);
esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA);
esp_cmd(esp, eregs, ESP_CMD_NULL | ESP_CMD_DMA);
-
+
+ /* Reload the configuration registers */
+ eregs->esp_cfact = esp->cfact;
+ eregs->esp_stp = 0;
+ eregs->esp_soff = 0;
+ eregs->esp_timeo = esp->neg_defp;
+
/* This is the only point at which it is reliable to read
- * the ID-code for a fast ESP chip variant.
+ * the ID-code for a fast ESP chip variants.
*/
esp->max_period = ((35 * esp->ccycle) / 1000);
if(esp->erev == fast) {
- version = eregs->esp_uid;
+ version = eregs->esp_uid;
family_code = (version & 0xf8) >> 3;
if(family_code == 0x02)
- if ((version & 7) == 2)
- esp->erev = fas216;
- else
- esp->erev = fas236;
+ esp->erev = fas236;
else if(family_code == 0x0a)
esp->erev = fashme; /* Version is usually '5'. */
- else
+ else
esp->erev = fas100a;
-
printk("esp%d: FAST chip is %s (family=%d, version=%d)\n",
esp->esp_id,
(esp->erev == fas236) ? "fas236" :
- ((esp->erev == fas216) ? "fas216" :
- (((esp->erev == fas100a) ? "fas100a" :
- "fasHME"))), family_code, (version & 7));
+ ((esp->erev == fas100a) ? "fas100a" :
+ "fasHME"), family_code, (version & 7));
esp->min_period = ((4 * esp->ccycle) / 1000);
} else {
esp->min_period = ((5 * esp->ccycle) / 1000);
}
-
- /* Reload the configuration registers */
- eregs->esp_cfact = esp->cfact;
- eregs->esp_stp = 0;
- eregs->esp_soff = 0;
- eregs->esp_timeo = esp->neg_defp;
esp->max_period = (esp->max_period + 3)>>2;
esp->min_period = (esp->min_period + 3)>>2;
@@ -438,7 +582,6 @@ static inline void esp_reset_esp(struct Sparc_ESP *esp, struct ESP_regs *eregs)
case fashme:
esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB);
/* fallthrough... */
- case fas216:
case fas236:
/* Fast 236 or HME */
eregs->esp_cfg2 = esp->config2;
@@ -478,13 +621,12 @@ static inline void esp_reset_esp(struct Sparc_ESP *esp, struct ESP_regs *eregs)
}
/* This places the ESP into a known state at boot time. */
-inline void esp_bootup_reset(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline void esp_bootup_reset(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
{
volatile unchar trash;
/* Reset the DMA */
- if(esp->dma_reset)
- esp->dma_reset(esp);
+ esp_reset_dma(esp);
/* Reset the ESP */
esp_reset_esp(esp, eregs);
@@ -499,195 +641,379 @@ inline void esp_bootup_reset(struct Sparc_ESP *esp, struct ESP_regs *eregs)
trash = eregs->esp_intrpt;
}
-/* Allocate structure and insert basic data such as SCSI chip frequency
- * data and a pointer to the device
+/* Detecting ESP chips on the machine. This is the simple and easy
+ * version.
*/
-struct Sparc_ESP* esp_allocate(Scsi_Host_Template *tpnt, void *esp_dev)
+__initfunc(int esp_detect(Scsi_Host_Template *tpnt))
{
+#ifdef __sparc_v9__
+ struct devid_cookie dcookie;
+#endif
struct Sparc_ESP *esp, *elink;
struct Scsi_Host *esp_host;
+ struct linux_sbus *sbus;
+ struct linux_sbus_device *esp_dev, *sbdev_iter;
+ struct Sparc_ESP_regs *eregs;
+ struct sparc_dma_registers *dregs;
+ struct Linux_SBus_DMA *dma, *dlink;
+ unsigned int fmhz;
+ unchar ccf, bsizes, bsizes_more;
+ int nesps = 0, esps_in_use = 0;
+ int esp_node, i;
- esp_host = scsi_register(tpnt, sizeof(struct Sparc_ESP));
- if(!esp_host)
- panic("Cannot register ESP SCSI host");
- esp = (struct Sparc_ESP *) esp_host->hostdata;
- if(!esp)
- panic("No esp in hostdata");
- esp->ehost = esp_host;
- esp->edev = esp_dev;
- esp->esp_id = nesps++;
-
- /* Put into the chain of esp chips detected */
- if(espchain) {
- elink = espchain;
- while(elink->next) elink = elink->next;
- elink->next = esp;
- } else {
- espchain = esp;
+ espchain = 0;
+ if(!SBus_chain) {
+#ifdef CONFIG_PCI
+ return 0;
+#else
+ panic("No SBUS in esp_detect()");
+#endif
}
- esp->next = 0;
+ for_each_sbus(sbus) {
+ for_each_sbusdev(sbdev_iter, sbus) {
+ struct linux_sbus_device *espdma = 0;
+ int hme = 0;
+
+ /* Is it an esp sbus device? */
+ esp_dev = sbdev_iter;
+ if(strcmp(esp_dev->prom_name, "esp") &&
+ strcmp(esp_dev->prom_name, "SUNW,esp")) {
+ if(!strcmp(esp_dev->prom_name, "SUNW,fas")) {
+ hme = 1;
+ espdma = esp_dev;
+ } else {
+ if(!esp_dev->child ||
+ (strcmp(esp_dev->prom_name, "espdma") &&
+ strcmp(esp_dev->prom_name, "dma")))
+ continue; /* nope... */
+ espdma = esp_dev;
+ esp_dev = esp_dev->child;
+ if(strcmp(esp_dev->prom_name, "esp") &&
+ strcmp(esp_dev->prom_name, "SUNW,esp"))
+ continue; /* how can this happen? */
+ }
+ }
+ esp_host = scsi_register(tpnt, sizeof(struct Sparc_ESP));
+ if(!esp_host)
+ panic("Cannot register ESP SCSI host");
+ if(hme)
+ esp_host->max_id = 16;
+ esp = (struct Sparc_ESP *) esp_host->hostdata;
+ if(!esp)
+ panic("No esp in hostdata");
+ esp->ehost = esp_host;
+ esp->edev = esp_dev;
+ esp->esp_id = nesps++;
+
+ /* Put into the chain of esp chips detected */
+ if(espchain) {
+ elink = espchain;
+ while(elink->next) elink = elink->next;
+ elink->next = esp;
+ } else {
+ espchain = esp;
+ }
+ esp->next = 0;
+
+ /* Get misc. prom information */
+#define ESP_IS_MY_DVMA(esp, dma) \
+ ((esp->edev->my_bus == dma->SBus_dev->my_bus) && \
+ (esp->edev->slot == dma->SBus_dev->slot) && \
+ (!strcmp(dma->SBus_dev->prom_name, "dma") || \
+ !strcmp(dma->SBus_dev->prom_name, "espdma")))
+
+ esp_node = esp_dev->prom_node;
+ prom_getstring(esp_node, "name", esp->prom_name,
+ sizeof(esp->prom_name));
+ esp->prom_node = esp_node;
+ if(espdma) {
+ for_each_dvma(dlink) {
+ if(dlink->SBus_dev == espdma)
+ break;
+ }
+ } else {
+ for_each_dvma(dlink) {
+ if(ESP_IS_MY_DVMA(esp, dlink) &&
+ !dlink->allocated)
+ break;
+ }
+ }
+#undef ESP_IS_MY_DVMA
+ /* If we don't know how to handle the dvma,
+ * do not use this device.
+ */
+ if(!dlink){
+ printk ("Cannot find dvma for ESP%d's SCSI\n",
+ esp->esp_id);
+ scsi_unregister (esp_host);
+ continue;
+ }
+ if (dlink->allocated){
+ printk ("esp%d: can't use my espdma\n",
+ esp->esp_id);
+ scsi_unregister (esp_host);
+ continue;
+ }
+ dlink->allocated = 1;
+ dma = dlink;
+ esp->dma = dma;
+ esp->dregs = dregs = dma->regs;
+
+ /* Map in the ESP registers from I/O space */
+ if(!hme) {
+ prom_apply_sbus_ranges(esp->edev->my_bus,
+ esp->edev->reg_addrs,
+ 1, esp->edev);
+
+ esp->eregs = eregs = (struct Sparc_ESP_regs *)
+ sparc_alloc_io(esp->edev->reg_addrs[0].phys_addr, 0,
+ PAGE_SIZE, "ESP Registers",
+ esp->edev->reg_addrs[0].which_io, 0x0);
+ } else {
+ /* On HME, two reg sets exist, first is DVMA,
+ * second is ESP registers.
+ */
+ esp->eregs = eregs = (struct Sparc_ESP_regs *)
+ sparc_alloc_io(esp->edev->reg_addrs[1].phys_addr, 0,
+ PAGE_SIZE, "ESP Registers",
+ esp->edev->reg_addrs[1].which_io, 0x0);
+ }
+ if(!eregs)
+ panic("ESP registers unmappable");
+ esp->esp_command =
+ sparc_dvma_malloc(16, "ESP DVMA Cmd Block",
+ &esp->esp_command_dvma);
+ if(!esp->esp_command || !esp->esp_command_dvma)
+ panic("ESP DVMA transport area unmappable");
+
+ /* Set up the irq's etc. */
+ esp->ehost->base = (unsigned char *) esp->eregs;
+ esp->ehost->io_port =
+ esp->edev->reg_addrs[0].phys_addr;
+ esp->ehost->n_io_port = (unsigned char)
+ esp->edev->reg_addrs[0].reg_size;
+ esp->ehost->irq = esp->irq = esp->edev->irqs[0].pri;
- return esp;
-}
+#ifndef __sparc_v9__
+ /* Allocate the irq only if necessary */
+ for_each_esp(elink) {
+ if((elink != esp) && (esp->irq == elink->irq)) {
+ goto esp_irq_acquired; /* BASIC rulez */
+ }
+ }
+ if(request_irq(esp->ehost->irq, do_esp_intr, SA_SHIRQ,
+ "Sparc ESP SCSI", NULL))
+ panic("Cannot acquire ESP irq line");
+esp_irq_acquired:
+ printk("esp%d: IRQ %d ", esp->esp_id, esp->ehost->irq);
+#else
+ /* On Ultra we must always call request_irq for each
+ * esp, so that imap registers get setup etc.
+ */
+ dcookie.real_dev_id = esp;
+ dcookie.imap = dcookie.iclr = 0;
+ dcookie.pil = -1;
+ dcookie.bus_cookie = sbus;
+ if(request_irq(esp->ehost->irq, do_esp_intr,
+ (SA_SHIRQ | SA_SBUS | SA_DCOOKIE),
+ "Sparc ESP SCSI", &dcookie))
+ panic("Cannot acquire ESP irq line");
+ esp->ehost->irq = esp->irq = dcookie.ret_ino;
+ printk("esp%d: INO[%x] IRQ %d ",
+ esp->esp_id, esp->ehost->irq, dcookie.ret_pil);
+#endif
-/* Complete initialization of ESP structure and device
- * Caller must have initialized appropriate parts of the ESP structure
- * between the call to esp_allocate and this function.
- */
-void esp_initialize(struct Sparc_ESP *esp)
-{
- struct ESP_regs *eregs = esp->eregs;
- unsigned int fmhz;
- unchar ccf;
- int i;
-
- /* Check out the clock properties of the chip. */
+ /* Figure out our scsi ID on the bus */
+ esp->scsi_id = prom_getintdefault(esp->prom_node,
+ "initiator-id",
+ -1);
+ if(esp->scsi_id == -1)
+ esp->scsi_id = prom_getintdefault(esp->prom_node,
+ "scsi-initiator-id",
+ -1);
+ if(esp->scsi_id == -1)
+ esp->scsi_id =
+ prom_getintdefault(esp->edev->my_bus->prom_node,
+ "scsi-initiator-id",
+ 7);
+ esp->ehost->this_id = esp->scsi_id;
+ esp->scsi_id_mask = (1 << esp->scsi_id);
+
+ /* Check for differential SCSI-bus */
+ esp->diff = prom_getbool(esp->prom_node, "differential");
+ if(esp->diff)
+ printk("Differential ");
- /* This is getting messy but it has to be done
- * correctly or else you get weird behavior all
- * over the place. We are trying to basically
- * figure out three pieces of information.
- *
- * a) Clock Conversion Factor
- *
- * This is a representation of the input
- * crystal clock frequency going into the
- * ESP on this machine. Any operation whose
- * timing is longer than 400ns depends on this
- * value being correct. For example, you'll
- * get blips for arbitration/selection during
- * high load or with multiple targets if this
- * is not set correctly.
- *
- * b) Selection Time-Out
- *
- * The ESP isn't very bright and will arbitrate
- * for the bus and try to select a target
- * forever if you let it. This value tells
- * the ESP when it has taken too long to
- * negotiate and that it should interrupt
- * the CPU so we can see what happened.
- * The value is computed as follows (from
- * NCR/Symbios chip docs).
- *
- * (Time Out Period) * (Input Clock)
- * STO = ----------------------------------
- * (8192) * (Clock Conversion Factor)
- *
- * You usually want the time out period to be
- * around 250ms, I think we'll set it a little
- * bit higher to account for fully loaded SCSI
- * bus's and slow devices that don't respond so
- * quickly to selection attempts. (yeah, I know
- * this is out of spec. but there is a lot of
- * buggy pieces of firmware out there so bite me)
- *
- * c) Imperical constants for synchronous offset
- * and transfer period register values
- *
- * This entails the smallest and largest sync
- * period we could ever handle on this ESP.
- */
-
- fmhz = esp->cfreq;
+ /* Check out the clock properties of the chip. */
- if(fmhz <= (5000000))
- ccf = 0;
- else
- ccf = (((5000000 - 1) + (fmhz))/(5000000));
- if(!ccf || ccf > 8) {
- /* If we can't find anything reasonable,
- * just assume 20MHZ. This is the clock
- * frequency of the older sun4c's where I've
- * been unable to find the clock-frequency
- * PROM property. All other machines provide
- * useful values it seems.
- */
- ccf = ESP_CCF_F4;
- fmhz = (20000000);
- }
- if(ccf==(ESP_CCF_F7+1))
- esp->cfact = ESP_CCF_F0;
- else if(ccf == ESP_CCF_NEVER)
- esp->cfact = ESP_CCF_F2;
- else
- esp->cfact = ccf;
- esp->cfreq = fmhz;
- esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);
- esp->ctick = ESP_TICK(ccf, esp->ccycle);
- esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
- esp->sync_defp = SYNC_DEFP_SLOW;
-
- printk("SCSI ID %d Clock %d MHz CCF=%d Time-Out %d ",
- esp->scsi_id, (esp->cfreq / 1000000),
- esp->ccf, (int) esp->neg_defp);
-
- /* Fill in ehost data */
- esp->ehost->base = (unsigned char *) eregs;
- esp->ehost->this_id = esp->scsi_id;
- esp->ehost->irq = esp->irq;
-
- /* SCSI id mask */
- esp->scsi_id_mask = (1 << esp->scsi_id);
-
- /* Probe the revision of this esp */
- esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
- esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
- eregs->esp_cfg2 = esp->config2;
- if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) !=
- (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
- printk("NCR53C90(esp100) detected\n");
- esp->erev = esp100;
- } else {
- eregs->esp_cfg2 = esp->config2 = 0;
- eregs->esp_cfg3 = 0;
- eregs->esp_cfg3 = esp->config3[0] = 5;
- if(eregs->esp_cfg3 != 5) {
- printk("NCR53C90A(esp100a) detected\n");
- esp->erev = esp100a;
- } else {
- int target;
-
- for(target=0; target<8; target++)
- esp->config3[target] = 0;
- eregs->esp_cfg3 = 0;
- if(ccf > ESP_CCF_F5) {
- printk("NCR53C9XF(espfast) detected\n");
- esp->erev = fast;
- eregs->esp_cfg2 = esp->config2 = 0;
- esp->sync_defp = SYNC_DEFP_FAST;
+ /* This is getting messy but it has to be done
+ * correctly or else you get weird behavior all
+ * over the place. We are trying to basically
+ * figure out three pieces of information.
+ *
+ * a) Clock Conversion Factor
+ *
+ * This is a representation of the input
+ * crystal clock frequency going into the
+ * ESP on this machine. Any operation whose
+ * timing is longer than 400ns depends on this
+ * value being correct. For example, you'll
+ * get blips for arbitration/selection during
+ * high load or with multiple targets if this
+ * is not set correctly.
+ *
+ * b) Selection Time-Out
+ *
+ * The ESP isn't very bright and will arbitrate
+ * for the bus and try to select a target
+ * forever if you let it. This value tells
+ * the ESP when it has taken too long to
+ * negotiate and that it should interrupt
+ * the CPU so we can see what happened.
+ * The value is computed as follows (from
+ * NCR/Symbios chip docs).
+ *
+ * (Time Out Period) * (Input Clock)
+ * STO = ----------------------------------
+ * (8192) * (Clock Conversion Factor)
+ *
+ * You usually want the time out period to be
+ * around 250ms, I think we'll set it a little
+ * bit higher to account for fully loaded SCSI
+ * bus's and slow devices that don't respond so
+ * quickly to selection attempts. (yeah, I know
+ * this is out of spec. but there is a lot of
+ * buggy pieces of firmware out there so bite me)
+ *
+ * c) Imperical constants for synchronous offset
+ * and transfer period register values
+ *
+ * This entails the smallest and largest sync
+ * period we could ever handle on this ESP.
+ */
+
+ fmhz = prom_getintdefault(esp->prom_node,
+ "clock-frequency",
+ -1);
+ if(fmhz==-1)
+ fmhz = prom_getintdefault(esp->edev->my_bus->prom_node,
+ "clock-frequency",
+ -1);
+ if(fmhz <= (5000000))
+ ccf = 0;
+ else
+ ccf = (((5000000 - 1) + (fmhz))/(5000000));
+ if(!ccf || ccf > 8) {
+ /* If we can't find anything reasonable,
+ * just assume 20MHZ. This is the clock
+ * frequency of the older sun4c's where I've
+ * been unable to find the clock-frequency
+ * PROM property. All other machines provide
+ * useful values it seems.
+ */
+ ccf = ESP_CCF_F4;
+ fmhz = (20000000);
+ }
+ if(ccf==(ESP_CCF_F7+1))
+ esp->cfact = ESP_CCF_F0;
+ else if(ccf == ESP_CCF_NEVER)
+ esp->cfact = ESP_CCF_F2;
+ else
+ esp->cfact = ccf;
+ esp->cfreq = fmhz;
+ esp->ccycle = ESP_MHZ_TO_CYCLE(fmhz);
+ esp->ctick = ESP_TICK(ccf, esp->ccycle);
+ esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
+ esp->sync_defp = SYNC_DEFP_SLOW;
+ printk("SCSI ID %d Clock %d MHz CCF=%d Time-Out %d ",
+ esp->scsi_id, (fmhz / 1000000),
+ ccf, (int) esp->neg_defp);
+
+ /* Find the burst sizes this dma/sbus/esp supports. */
+ bsizes = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff);
+ bsizes &= 0xff;
+ if(espdma) {
+ bsizes_more = prom_getintdefault(
+ espdma->prom_node,
+ "burst-sizes", 0xff);
+ if(bsizes_more != 0xff)
+ bsizes &= bsizes_more;
+ }
+ bsizes_more = prom_getintdefault(esp->edev->my_bus->prom_node,
+ "burst-sizes", 0xff);
+ if(bsizes_more != 0xff)
+ bsizes &= bsizes_more;
+
+ if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 ||
+ (bsizes & DMA_BURST32)==0)
+ bsizes = (DMA_BURST32 - 1);
+
+ esp->bursts = bsizes;
+
+ /* Probe the revision of this esp */
+ esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
+ esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+ eregs->esp_cfg2 = esp->config2;
+ if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) !=
+ (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
+ printk("NCR53C90(esp100) detected\n");
+ esp->erev = esp100;
} else {
- printk("NCR53C9x(esp236) detected\n");
- esp->erev = esp236;
eregs->esp_cfg2 = esp->config2 = 0;
+ eregs->esp_cfg3 = 0;
+ eregs->esp_cfg3 = esp->config3[0] = 5;
+ if(eregs->esp_cfg3 != 5) {
+ printk("NCR53C90A(esp100a) detected\n");
+ esp->erev = esp100a;
+ } else {
+ int target;
+
+ for(target=0; target<8; target++)
+ esp->config3[target] = 0;
+ eregs->esp_cfg3 = 0;
+ if(ccf > ESP_CCF_F5) {
+ printk("NCR53C9XF(espfast) detected\n");
+ esp->erev = fast;
+ eregs->esp_cfg2 = esp->config2 = 0;
+ esp->sync_defp = SYNC_DEFP_FAST;
+ } else {
+ printk("NCR53C9x(esp236) detected\n");
+ esp->erev = esp236;
+ eregs->esp_cfg2 = esp->config2 = 0;
+ }
+ }
+ }
+
+ /* Initialize the command queues */
+ esp->current_SC = 0;
+ esp->disconnected_SC = 0;
+ esp->issue_SC = 0;
+
+ /* Clear the state machines. */
+ esp->targets_present = 0;
+ esp->resetting_bus = 0;
+ esp->snip = 0;
+ esp->targets_present = 0;
+ for(i = 0; i < 32; i++)
+ esp->espcmdlog[i] = 0;
+ esp->espcmdent = 0;
+ for(i = 0; i < 16; i++) {
+ esp->cur_msgout[i] = 0;
+ esp->cur_msgin[i] = 0;
}
- }
- }
-
- /* Initialize the command queues */
- esp->current_SC = 0;
- esp->disconnected_SC = 0;
- esp->issue_SC = 0;
-
- /* Clear the state machines. */
- esp->targets_present = 0;
- esp->resetting_bus = 0;
- esp->snip = 0;
- esp->targets_present = 0;
- for(i = 0; i < 32; i++)
- esp->espcmdlog[i] = 0;
- esp->espcmdent = 0;
- for(i = 0; i < 16; i++) {
- esp->cur_msgout[i] = 0;
- esp->cur_msgin[i] = 0;
- }
- esp->prevmsgout = esp->prevmsgin = 0;
- esp->msgout_len = esp->msgin_len = 0;
-
- /* Reset the thing before we try anything... */
- esp_bootup_reset(esp, eregs);
-
- esps_in_use++;
+ esp->prevmsgout = esp->prevmsgin = 0;
+ esp->msgout_len = esp->msgin_len = 0;
+
+ /* Reset the thing before we try anything... */
+ esp_bootup_reset(esp, eregs);
+
+ esps_in_use++;
+ } /* for each sbusdev */
+ } /* for each sbus */
+ printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,
+ esps_in_use);
+ esps_running = esps_in_use;
+ return esps_in_use;
}
/* The info function will return whatever useful
@@ -706,8 +1032,6 @@ const char *esp_info(struct Scsi_Host *host)
return "Sparc ESP100A (NCR53C90A)";
case esp236:
return "Sparc ESP236";
- case fas216:
- return "MIPS Jazz FAS216";
case fas236:
return "Sparc ESP236-FAST";
case fashme:
@@ -786,9 +1110,6 @@ static int esp_host_info(struct Sparc_ESP *esp, char *ptr, off_t offset, int len
case esp236:
copy_info(&info, "ESP236\n");
break;
- case fas216:
- copy_info(&info, "FAS216\n");
- break;
case fas236:
copy_info(&info, "FAS236\n");
break;
@@ -806,7 +1127,6 @@ static int esp_host_info(struct Sparc_ESP *esp, char *ptr, off_t offset, int len
copy_info(&info, "Unknown!\n");
break;
};
-#ifdef CONFIG_SCSI_SUNESP
copy_info(&info, "\tDMA Revision\t\t");
switch(esp->dma->revision) {
case dvmarev0:
@@ -834,7 +1154,6 @@ static int esp_host_info(struct Sparc_ESP *esp, char *ptr, off_t offset, int len
copy_info(&info, "Unknown!\n");
break;
};
-#endif
copy_info(&info, "\tLive Targets\t\t[ ");
for(i = 0; i < 15; i++) {
if(esp->targets_present & (1 << i))
@@ -959,7 +1278,8 @@ static inline void build_wide_nego_msg(struct Sparc_ESP *esp, int size)
static inline void esp_exec_cmd(struct Sparc_ESP *esp)
{
- struct ESP_regs *eregs = esp->eregs;
+ struct sparc_dma_registers *dregs = esp->dregs;
+ struct Sparc_ESP_regs *eregs = esp->eregs;
Scsi_Cmnd *SCptr;
Scsi_Device *SDptr;
volatile unchar *cmdp = esp->esp_command;
@@ -968,7 +1288,7 @@ static inline void esp_exec_cmd(struct Sparc_ESP *esp)
int i;
/* Hold off if we've been reselected or an IRQ is showing... */
- if(esp->disconnected_SC || esp->dma_irq_p(esp))
+ if(esp->disconnected_SC || DMA_IRQ_P(dregs))
return;
/* Grab first member of the issue queue. */
@@ -1018,9 +1338,7 @@ static inline void esp_exec_cmd(struct Sparc_ESP *esp)
if(SDptr->sync) {
/* this targets sync is known */
-#ifdef CONFIG_SCSI_SUNESP
do_sync_known:
-#endif
if(SDptr->disconnect)
*cmdp++ = IDENTIFY(1, lun);
else
@@ -1055,7 +1373,6 @@ do_sync_known:
} else {
int toshiba_cdrom_hwbug_wkaround = 0;
-#ifdef CONFIG_SCSI_SUNESP
/* Never allow disconnects or synchronous transfers on
* SparcStation1 and SparcStation1+. Allowing those
* to be enabled seems to lockup the machine completely.
@@ -1073,7 +1390,7 @@ do_sync_known:
esp->snip = 0;
goto do_sync_known;
}
-#endif
+
/* We've talked to this guy before,
* but never negotiated.. lets try,
* need to attempt WIDE first, before
@@ -1177,36 +1494,38 @@ after_nego_msg_built:
i = (cmdp - esp->esp_command);
- /* Set up the DMA and ESP counters */
- if(esp->do_pio_cmds){
- int j = 0;
+ if(esp->erev == fashme) {
+ unsigned long tmp;
- for(;j<i;j++)
- eregs->esp_fdata = esp->esp_command[j];
- the_esp_command &= ~ESP_CMD_DMA;
+ esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* Grrr! */
- /* Tell ESP to "go". */
+ /* Set up the DMA and HME counters */
+ eregs->esp_tclow = i;
+ eregs->esp_tcmed = 0;
+ eregs->fas_rlo = 0;
+ eregs->fas_rhi = 0;
esp_cmd(esp, eregs, the_esp_command);
- } else {
- if(esp->erev == fashme) {
- esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* Grrr! */
-
- /* Set up the HME counters */
- eregs->esp_tclow = i;
- eregs->esp_tcmed = 0;
- eregs->fas_rlo = 0;
- eregs->fas_rhi = 0;
- esp_cmd(esp, eregs, the_esp_command);
- esp->dma_init_write(esp, esp->esp_command_dvma, 16);
- } else {
- /* Set up the ESP counters */
- eregs->esp_tclow = i;
- eregs->esp_tcmed = 0;
- esp->dma_init_write(esp, esp->esp_command_dvma, i);
- /* Tell ESP to "go". */
- esp_cmd(esp, eregs, the_esp_command);
+ /* Talk about touchy hardware... */
+ tmp = dregs->cond_reg;
+ tmp |= (DMA_SCSI_DISAB | DMA_ENABLE);
+ tmp &= ~(DMA_ST_WRITE);
+ dregs->cnt = 16;
+ dregs->st_addr = esp->esp_command_dvma;
+ dregs->cond_reg = tmp;
+ } else {
+ /* Set up the DMA and ESP counters */
+ eregs->esp_tclow = i;
+ eregs->esp_tcmed = 0;
+ dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE);
+ if(esp->dma->revision == dvmaesc1) {
+ if(i) /* Workaround ESC gate array SBUS rerun bug. */
+ dregs->cnt = (PAGE_SIZE);
}
+ dregs->st_addr = esp->esp_command_dvma;
+
+ /* Tell ESP to "go". */
+ esp_cmd(esp, eregs, the_esp_command);
}
}
@@ -1214,6 +1533,7 @@ after_nego_msg_built:
int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
{
struct Sparc_ESP *esp;
+ struct sparc_dma_registers *dregs;
unsigned long flags;
/* Set up func ptr and initial driver cmd-phase. */
@@ -1221,9 +1541,7 @@ int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
SCpnt->SCp.phase = not_issued;
esp = (struct Sparc_ESP *) SCpnt->host->hostdata;
-
- if(esp->dma_led_on)
- esp->dma_led_on(esp);
+ dregs = esp->dregs;
/* We use the scratch area. */
ESPQUEUE(("esp_queue: target=%d lun=%d ", SCpnt->target, SCpnt->lun));
@@ -1234,11 +1552,14 @@ int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
SCpnt->SCp.buffer =
(struct scatterlist *) SCpnt->request_buffer;
SCpnt->SCp.buffers_residual = 0;
- if (esp->dma_mmu_get_scsi_one)
- esp->dma_mmu_get_scsi_one (esp, SCpnt);
- else
- SCpnt->SCp.have_data_in = (int) SCpnt->SCp.ptr =
- (char *)SCpnt->request_buffer;
+ /* Sneaky. */
+ SCpnt->SCp.have_data_in = mmu_get_scsi_one((char *)SCpnt->SCp.buffer,
+ SCpnt->SCp.this_residual,
+ esp->edev->my_bus);
+ /* XXX The casts are extremely gross, but with 64-bit kernel
+ * XXX and 32-bit SBUS what am I to do? -DaveM
+ */
+ SCpnt->SCp.ptr = (char *)((unsigned long)SCpnt->SCp.have_data_in);
} else {
ESPQUEUE(("use_sg "));
#ifdef DEBUG_ESP_SG
@@ -1248,10 +1569,11 @@ int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
- if (esp->dma_mmu_get_scsi_sgl)
- esp->dma_mmu_get_scsi_sgl (esp, SCpnt);
- else
- SCpnt->SCp.ptr = SCpnt->SCp.buffer->address;
+ mmu_get_scsi_sgl((struct mmu_sglist *) SCpnt->SCp.buffer,
+ SCpnt->SCp.buffers_residual,
+ esp->edev->my_bus);
+ /* XXX Again these casts are sick... -DaveM */
+ SCpnt->SCp.ptr=(char *)((unsigned long)SCpnt->SCp.buffer->dvma_address);
}
SCpnt->SCp.Status = CHECK_CONDITION;
SCpnt->SCp.Message = 0xff;
@@ -1266,7 +1588,7 @@ int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
append_SC(&esp->issue_SC, SCpnt);
}
- save_and_cli(flags);
+ save_and_cli(flags);
/* Run it now if we can. */
if(!esp->current_SC && !esp->resetting_bus)
@@ -1279,9 +1601,7 @@ int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
/* Only queuing supported in this ESP driver. */
int esp_command(Scsi_Cmnd *SCpnt)
{
-#ifdef DEBUG_ESP
struct Sparc_ESP *esp = (struct Sparc_ESP *) SCpnt->host->hostdata;
-#endif
ESPLOG(("esp%d: esp_command() called...\n", esp->esp_id));
return -1;
@@ -1297,8 +1617,8 @@ static inline void esp_dump_cmd(Scsi_Cmnd *SCptr)
phase_string(SCptr->SCp.phase)));
}
-static inline void esp_dump_state(struct Sparc_ESP *esp,
- struct ESP_regs *eregs)
+static inline void esp_dump_state(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
#ifdef DEBUG_ESP_CMDS
@@ -1306,10 +1626,8 @@ static inline void esp_dump_state(struct Sparc_ESP *esp,
#endif
ESPLOG(("esp%d: dumping state\n", esp->esp_id));
-
- /* Print DMA status */
- esp->dma_dump_state(esp);
-
+ ESPLOG(("esp%d: dma -- cond_reg<%08x> addr<%08x>\n",
+ esp->esp_id, dregs->cond_reg, dregs->st_addr));
ESPLOG(("esp%d: SW [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
esp->esp_id, esp->sreg, esp->seqreg, esp->ireg));
ESPLOG(("esp%d: HW reread [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
@@ -1353,12 +1671,13 @@ static inline void esp_dump_state(struct Sparc_ESP *esp,
int esp_abort(Scsi_Cmnd *SCptr)
{
struct Sparc_ESP *esp = (struct Sparc_ESP *) SCptr->host->hostdata;
- struct ESP_regs *eregs = esp->eregs;
- int don;
+ struct Sparc_ESP_regs *eregs = esp->eregs;
+ struct sparc_dma_registers *dregs = esp->dregs;
unsigned long flags;
+ int don;
ESPLOG(("esp%d: Aborting command\n", esp->esp_id));
- esp_dump_state(esp, eregs);
+ esp_dump_state(esp, eregs, dregs);
/* Wheee, if this is the current command on the bus, the
* best we can do is assert ATN and wait for msgout phase.
@@ -1380,9 +1699,9 @@ int esp_abort(Scsi_Cmnd *SCptr)
/* If it is still in the issue queue then we can safely
* call the completion routine and report abort success.
*/
- don = esp->dma_ports_p(esp);
+ don = (dregs->cond_reg & DMA_INT_ENAB);
if(don) {
- esp->dma_ints_off(esp);
+ DMA_INTSOFF(dregs);
synchronize_irq();
}
if(esp->issue_SC) {
@@ -1397,7 +1716,7 @@ int esp_abort(Scsi_Cmnd *SCptr)
this->result = DID_ABORT << 16;
this->done(this);
if(don)
- esp->dma_ints_on(esp);
+ DMA_INTSON(dregs);
return SCSI_ABORT_SUCCESS;
}
}
@@ -1427,7 +1746,7 @@ int esp_abort(Scsi_Cmnd *SCptr)
int esp_reset(Scsi_Cmnd *SCptr, unsigned int how)
{
struct Sparc_ESP *esp = (struct Sparc_ESP *) SCptr->host->hostdata;
- struct ESP_regs *eregs = esp->eregs;
+ struct Sparc_ESP_regs *eregs = esp->eregs;
ESPLOG(("esp%d: Resetting scsi bus\n", esp->esp_id));
esp->resetting_bus = 1;
@@ -1448,15 +1767,17 @@ static void esp_done(struct Sparc_ESP *esp, int error)
/* Free dvma entry. */
if(!done_SC->use_sg) {
- if (esp->dma_mmu_release_scsi_one)
- esp->dma_mmu_release_scsi_one (esp, done_SC);
+ /* Sneaky. */
+ mmu_release_scsi_one(done_SC->SCp.have_data_in,
+ done_SC->request_bufflen,
+ esp->edev->my_bus);
} else {
#ifdef DEBUG_ESP_SG
printk("esp%d: unmapping sg ", esp->esp_id);
#endif
- if (esp->dma_mmu_release_scsi_sgl)
- esp->dma_mmu_release_scsi_sgl (esp, done_SC);
-
+ mmu_release_scsi_sgl((struct mmu_sglist *) done_SC->buffer,
+ done_SC->use_sg - 1,
+ esp->edev->my_bus);
#ifdef DEBUG_ESP_SG
printk("done.\n");
#endif
@@ -1489,15 +1810,22 @@ enum {
};
/* Forward declarations. */
-static int esp_do_phase_determine(struct Sparc_ESP *esp,
- struct ESP_regs *eregs);
-static int esp_do_data_finale(struct Sparc_ESP *esp, struct ESP_regs *eregs);
-static int esp_select_complete(struct Sparc_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_status(struct Sparc_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_msgin(struct Sparc_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_msgindone(struct Sparc_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_msgout(struct Sparc_ESP *esp, struct ESP_regs *eregs);
-static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct ESP_regs *eregs);
+static int esp_do_phase_determine(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs);
+static int esp_do_data_finale(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs);
+static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs);
+static int esp_do_status(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs);
+static int esp_do_msgin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs);
+static int esp_do_msgindone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs);
+static int esp_do_msgout(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs);
+static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs);
static inline int sreg_datainp(unchar sreg)
{
@@ -1511,7 +1839,7 @@ static inline int sreg_dataoutp(unchar sreg)
/* Did they drop these fabs on the floor or what?!?!! */
static inline void hme_fifo_hwbug_workaround(struct Sparc_ESP *esp,
- struct ESP_regs *eregs)
+ struct Sparc_ESP_regs *eregs)
{
unchar status = esp->sreg;
@@ -1547,7 +1875,7 @@ static inline void hme_fifo_hwbug_workaround(struct Sparc_ESP *esp,
}
}
-static inline void hme_fifo_push(struct Sparc_ESP *esp, struct ESP_regs *eregs,
+static inline void hme_fifo_push(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
unchar *bytes, unchar count)
{
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
@@ -1561,13 +1889,13 @@ static inline void hme_fifo_push(struct Sparc_ESP *esp, struct ESP_regs *eregs,
/* We try to avoid some interrupts by jumping ahead and see if the ESP
* has gotten far enough yet. Hence the following.
*/
-static inline int skipahead1(struct Sparc_ESP *esp, struct ESP_regs *eregs,
+static inline int skipahead1(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs,
Scsi_Cmnd *scp, int prev_phase, int new_phase)
{
if(scp->SCp.sent_command != prev_phase)
return 0;
-
- if(esp->dma_irq_p(esp)) {
+ if(DMA_IRQ_P(dregs)) {
/* Yes, we are able to save an interrupt. */
esp->sreg = eregs->esp_status;
if(esp->erev == fashme) {
@@ -1593,15 +1921,15 @@ static inline int skipahead1(struct Sparc_ESP *esp, struct ESP_regs *eregs,
return do_intr_end;
}
-static inline int skipahead2(struct Sparc_ESP *esp,
- struct ESP_regs *eregs,
+static inline int skipahead2(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs,
Scsi_Cmnd *scp, int prev_phase1, int prev_phase2,
int new_phase)
{
if(scp->SCp.sent_command != prev_phase1 &&
scp->SCp.sent_command != prev_phase2)
return 0;
- if(esp->dma_irq_p(esp)) {
+ if(DMA_IRQ_P(dregs)) {
/* Yes, we are able to save an interrupt. */
esp->sreg = eregs->esp_status;
if(esp->erev == fashme) {
@@ -1628,8 +1956,100 @@ static inline int skipahead2(struct Sparc_ESP *esp,
return do_intr_end;
}
+/* Now some dma helpers. */
+static inline void dma_setup(struct sparc_dma_registers *dregs, enum dvma_rev drev,
+ __u32 addr, int count, int write)
+{
+ unsigned long nreg = dregs->cond_reg;
+ if(write)
+ nreg |= DMA_ST_WRITE;
+ else
+ nreg &= ~(DMA_ST_WRITE);
+ nreg |= DMA_ENABLE;
+ dregs->cond_reg = nreg;
+ if(drev == dvmaesc1) {
+ /* This ESC gate array sucks! */
+ __u32 src = addr;
+ __u32 dest = src + count;
+
+ if(dest & (PAGE_SIZE - 1))
+ count = PAGE_ALIGN(count);
+ dregs->cnt = count;
+ }
+ dregs->st_addr = addr;
+}
+
+static inline void dma_drain(struct sparc_dma_registers *dregs, enum dvma_rev drev)
+{
+ if(drev == dvmahme)
+ return;
+ if(dregs->cond_reg & DMA_FIFO_ISDRAIN) {
+ switch(drev) {
+ default:
+ dregs->cond_reg |= DMA_FIFO_STDRAIN;
+
+ case dvmarev3:
+ case dvmaesc1:
+ while(dregs->cond_reg & DMA_FIFO_ISDRAIN)
+ udelay(1);
+ };
+ }
+}
+
+static inline void dma_invalidate(struct sparc_dma_registers *dregs, enum dvma_rev drev)
+{
+ unsigned int tmp;
+
+ if(drev == dvmahme) {
+ /* SMCC can bite me. */
+ tmp = dregs->cond_reg;
+ dregs->cond_reg = DMA_RST_SCSI;
+
+ /* This would explain a lot. */
+ tmp |= (DMA_PARITY_OFF|DMA_2CLKS|DMA_SCSI_DISAB);
+
+ tmp &= ~(DMA_ENABLE|DMA_ST_WRITE);
+ dregs->cond_reg = 0;
+ dregs->cond_reg = tmp;
+ } else {
+ while(dregs->cond_reg & DMA_PEND_READ)
+ udelay(1);
+
+ tmp = dregs->cond_reg;
+ tmp &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB);
+ tmp |= DMA_FIFO_INV;
+ dregs->cond_reg = tmp;
+ dregs->cond_reg = (tmp & ~(DMA_FIFO_INV));
+ }
+}
+
+static inline void dma_flashclear(struct sparc_dma_registers *dregs, enum dvma_rev drev)
+{
+ dma_drain(dregs, drev);
+ dma_invalidate(dregs, drev);
+}
+
+static inline int dma_can_transfer(Scsi_Cmnd *sp, enum dvma_rev drev)
+{
+ __u32 base, end, sz;
+
+ if(drev == dvmarev3) {
+ sz = sp->SCp.this_residual;
+ if(sz > 0x1000000)
+ sz = 0x1000000;
+ } else {
+ base = ((__u32)((unsigned long)sp->SCp.ptr));
+ base &= (0x1000000 - 1);
+ end = (base + sp->SCp.this_residual);
+ if(end > 0x1000000)
+ end = 0x1000000;
+ sz = (end - base);
+ }
+ return sz;
+}
+
/* Misc. esp helper routines. */
-static inline void esp_setcount(struct ESP_regs *eregs, int cnt, int hme)
+static inline void esp_setcount(struct Sparc_ESP_regs *eregs, int cnt, int hme)
{
eregs->esp_tclow = (cnt & 0xff);
eregs->esp_tcmed = ((cnt >> 8) & 0xff);
@@ -1639,13 +2059,13 @@ static inline void esp_setcount(struct ESP_regs *eregs, int cnt, int hme)
}
}
-static inline int esp_getcount(struct ESP_regs *eregs)
+static inline int esp_getcount(struct Sparc_ESP_regs *eregs)
{
return (((eregs->esp_tclow)&0xff) |
(((eregs->esp_tcmed)&0xff) << 8));
}
-static inline int fcount(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline int fcount(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
{
if(esp->erev == fashme)
return esp->hme_fifo_workaround_count;
@@ -1653,7 +2073,7 @@ static inline int fcount(struct Sparc_ESP *esp, struct ESP_regs *eregs)
return eregs->esp_fflags & ESP_FF_FBYTES;
}
-static inline int fnzero(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline int fnzero(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
{
if(esp->erev == fashme)
return 0;
@@ -1665,7 +2085,7 @@ static inline int fnzero(struct Sparc_ESP *esp, struct ESP_regs *eregs)
* XXX even on esp100!!! another case of flooding the bus with I/O reg
* XXX writes...
*/
-static inline void esp_maybe_nop(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline void esp_maybe_nop(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
{
if(esp->erev == esp100)
esp_cmd(esp, eregs, ESP_CMD_NULL);
@@ -1687,7 +2107,7 @@ static inline int sreg_to_dataphase(unchar sreg)
* tell the ESP to eat the extraneous byte so that we can proceed
* to the next phase.
*/
-static inline int esp100_sync_hwbug(struct Sparc_ESP *esp, struct ESP_regs *eregs,
+static inline int esp100_sync_hwbug(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
Scsi_Cmnd *sp, int fifocnt)
{
/* Do not touch this piece of code. */
@@ -1714,14 +2134,13 @@ static inline int esp100_sync_hwbug(struct Sparc_ESP *esp, struct ESP_regs *ereg
* ack the possible illegal cmd interrupt pending on the esp100.
*/
static inline int esp100_reconnect_hwbug(struct Sparc_ESP *esp,
- struct ESP_regs *eregs)
+ struct Sparc_ESP_regs *eregs)
{
volatile unchar junk;
if(esp->erev != esp100)
return 0;
junk = eregs->esp_intrpt;
-
if(junk & ESP_INTR_SR)
return 1;
return 0;
@@ -1730,7 +2149,7 @@ static inline int esp100_reconnect_hwbug(struct Sparc_ESP *esp,
/* This verifies the BUSID bits during a reselection so that we know which
* target is talking to us.
*/
-static inline int reconnect_target(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline int reconnect_target(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
{
int it, me = esp->scsi_id_mask, targ = 0;
@@ -1760,7 +2179,7 @@ static inline int reconnect_target(struct Sparc_ESP *esp, struct ESP_regs *eregs
/* This verifies the identify from the target so that we know which lun is
* being reconnected.
*/
-static inline int reconnect_lun(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline int reconnect_lun(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs)
{
int lun;
@@ -1780,7 +2199,7 @@ static inline int reconnect_lun(struct Sparc_ESP *esp, struct ESP_regs *eregs)
/* This puts the driver in a state where it can revitalize a command that
* is being continued due to reselection.
*/
-static inline void esp_connect(struct Sparc_ESP *esp, struct ESP_regs *eregs,
+static inline void esp_connect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
Scsi_Cmnd *sp)
{
Scsi_Device *dp = sp->device;
@@ -1809,7 +2228,8 @@ static inline void esp_reconnect(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
}
/* Begin message in phase. */
-static inline int esp_do_msgin(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline int esp_do_msgin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
/* Must be very careful with the fifo on the HME */
if((esp->erev != fashme) || !(eregs->esp_status2 & ESP_STAT2_FEMPTY))
@@ -1822,15 +2242,26 @@ static inline int esp_do_msgin(struct Sparc_ESP *esp, struct ESP_regs *eregs)
return do_work_bus;
}
-static inline void advance_sg(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
+/* This uses various DMA csr fields and the fifo flags count value to
+ * determine how many bytes were successfully sent/received by the ESP.
+ */
+static inline int esp_bytes_sent(struct Sparc_ESP *esp,
+ struct sparc_dma_registers *dregs,
+ int fifo_count)
+{
+ int rval = dregs->st_addr - esp->esp_command_dvma;
+
+ if(esp->dma->revision == dvmarev1)
+ rval -= (4 - ((dregs->cond_reg & DMA_READ_AHEAD)>>11));
+ return rval - fifo_count;
+}
+
+static inline void advance_sg(Scsi_Cmnd *sp)
{
++sp->SCp.buffer;
--sp->SCp.buffers_residual;
sp->SCp.this_residual = sp->SCp.buffer->length;
- if (esp->dma_advance_sg)
- esp->dma_advance_sg(sp);
- else
- sp->SCp.ptr = sp->SCp.buffer->address;
+ sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
}
/* Please note that the way I've coded these routines is that I _always_
@@ -1851,8 +2282,8 @@ static inline void advance_sg(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
* within a buffer or sub-buffer should not upset us at all no matter
* how bad the target and/or ESP fucks things up.
*/
-
-static inline int esp_do_data(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline int esp_do_data(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
int thisphase, hmuch;
@@ -1862,21 +2293,28 @@ static inline int esp_do_data(struct Sparc_ESP *esp, struct ESP_regs *eregs)
thisphase = sreg_to_dataphase(esp->sreg);
esp_advance_phase(SCptr, thisphase);
ESPDATA(("newphase<%s> ", (thisphase == in_datain) ? "DATAIN" : "DATAOUT"));
- hmuch = esp->dma_can_transfer(esp, SCptr);
+ hmuch = dma_can_transfer(SCptr, esp->dma->revision);
ESPDATA(("hmuch<%d> ", hmuch));
esp->current_transfer_size = hmuch;
if(esp->erev == fashme) {
+ unsigned long tmp = dregs->cond_reg;
+
/* Touchy chip, this stupid HME scsi adapter... */
esp_setcount(eregs, hmuch, 1);
esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
-
+ dregs->cnt = hmuch;
+ tmp |= (DMA_SCSI_DISAB | DMA_ENABLE);
if(thisphase == in_datain)
- esp->dma_init_read(esp, (__u32) SCptr->SCp.ptr, hmuch);
+ tmp |= DMA_ST_WRITE;
else
- esp->dma_init_write(esp, (__u32) SCptr->SCp.ptr, hmuch);
+ tmp &= ~(DMA_ST_WRITE);
+ dregs->st_addr = ((__u32)((unsigned long)SCptr->SCp.ptr));
+ dregs->cond_reg = tmp;
} else {
esp_setcount(eregs, hmuch, 0);
- esp->dma_setup(esp, (__u32) SCptr->SCp.ptr, hmuch, (thisphase == in_datain));
+ dma_setup(dregs, esp->dma->revision,
+ ((__u32)((unsigned long)SCptr->SCp.ptr)),
+ hmuch, (thisphase == in_datain));
ESPDATA(("DMA|TI --> do_intr_end\n"));
esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
}
@@ -1885,14 +2323,12 @@ static inline int esp_do_data(struct Sparc_ESP *esp, struct ESP_regs *eregs)
/* See how successful the data transfer was. */
static inline int esp_do_data_finale(struct Sparc_ESP *esp,
- struct ESP_regs *eregs)
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
int bogus_data = 0, bytes_sent = 0, fifocnt, ecount = 0;
- if(esp->dma_led_off)
- esp->dma_led_off(esp);
-
ESPDATA(("esp_do_data_finale: "));
if(SCptr->SCp.phase == in_datain) {
@@ -1907,18 +2343,16 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
esp->cur_msgout[0] = INITIATOR_ERROR;
esp->msgout_len = 1;
}
- if(esp->dma_drain)
- esp->dma_drain(esp);
+ dma_drain(dregs, esp->dma->revision);
}
- if(esp->dma_invalidate)
- esp->dma_invalidate(esp);
+ dma_invalidate(dregs, esp->dma->revision);
/* This could happen for the above parity error case. */
if(!(esp->ireg == ESP_INTR_BSERV)) {
/* Please go to msgout phase, please please please... */
ESPLOG(("esp%d: !BSERV after data, probably to msgout\n",
esp->esp_id));
- return esp_do_phase_determine(esp, eregs);
+ return esp_do_phase_determine(esp, eregs, dregs);
}
/* Check for partial transfers and other horrible events.
@@ -2025,13 +2459,13 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
* figure this out.
*/
if(SCptr->use_sg && !SCptr->SCp.this_residual)
- advance_sg(esp, SCptr);
+ advance_sg(SCptr);
if(sreg_datainp(esp->sreg) || sreg_dataoutp(esp->sreg)) {
ESPDATA(("to more data\n"));
- return esp_do_data(esp, eregs);
+ return esp_do_data(esp, eregs, dregs);
}
ESPDATA(("to new phase\n"));
- return esp_do_phase_determine(esp, eregs);
+ return esp_do_phase_determine(esp, eregs, dregs);
}
/* Bogus data, just wait for next interrupt. */
ESPLOG(("esp%d: bogus_data during end of data phase\n",
@@ -2042,15 +2476,15 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp,
/* Either a command is completing or a target is dropping off the bus
* to continue the command in the background so we can do other work.
*/
-static inline int esp_do_freebus(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline int esp_do_freebus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
int rval;
- rval = skipahead2(esp, eregs, SCptr, in_status, in_msgindone, in_freeing);
+ rval = skipahead2(esp, eregs, dregs, SCptr, in_status, in_msgindone, in_freeing);
if(rval)
return rval;
-
if(esp->ireg != ESP_INTR_DC) {
ESPLOG(("esp%d: Target will not disconnect\n", esp->esp_id));
return do_reset_bus; /* target will not drop BSY... */
@@ -2117,8 +2551,8 @@ static inline int esp_do_freebus(struct Sparc_ESP *esp, struct ESP_regs *eregs)
}
/* Do the needy when a target tries to reconnect to us. */
-static inline int esp_do_reconnect(struct Sparc_ESP *esp,
- struct ESP_regs *eregs)
+static inline int esp_do_reconnect(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
int lun, target;
Scsi_Cmnd *SCptr;
@@ -2142,8 +2576,7 @@ static inline int esp_do_reconnect(struct Sparc_ESP *esp,
if(esp->erev == fashme) {
/* XXX this still doesn't fix the problem... */
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
- if(esp->dma_invalidate)
- esp->dma_invalidate(esp);
+ dma_invalidate(esp->dregs, dvmahme);
} else {
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
if(esp100_reconnect_hwbug(esp, eregs))
@@ -2193,15 +2626,15 @@ static inline int esp_do_reconnect(struct Sparc_ESP *esp,
/* End of NEXUS (hopefully), pick up status + message byte then leave if
* all goes well.
*/
-static int esp_do_status(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static int esp_do_status(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
int intr, rval;
- rval = skipahead1(esp, eregs, SCptr, in_the_dark, in_status);
+ rval = skipahead1(esp, eregs, dregs, SCptr, in_the_dark, in_status);
if(rval)
return rval;
-
intr = esp->ireg;
ESPSTAT(("esp_do_status: "));
if(intr != ESP_INTR_DC) {
@@ -2211,8 +2644,16 @@ static int esp_do_status(struct Sparc_ESP *esp, struct ESP_regs *eregs)
ESPSTAT(("ack msg, "));
esp_cmd(esp, eregs, ESP_CMD_MOK);
- if(esp->dma_poll)
- esp->dma_poll(esp, (unsigned char *) esp->esp_command);
+ if(esp->erev != fashme) {
+ dma_flashclear(dregs, esp->dma->revision);
+
+ /* Wait till the first bits settle. */
+ while(esp->esp_command[0] == 0xff)
+ udelay(1);
+ } else {
+ esp->esp_command[0] = esp->hme_fifo_workaround_buffer[0];
+ esp->esp_command[1] = esp->hme_fifo_workaround_buffer[1];
+ }
ESPSTAT(("got something, "));
/* ESP chimes in with one of
@@ -2266,7 +2707,7 @@ static int esp_do_status(struct Sparc_ESP *esp, struct ESP_regs *eregs)
/* This shouldn't happen ever. */
ESPSTAT(("got bolixed\n"));
esp_advance_phase(SCptr, in_the_dark);
- return esp_do_phase_determine(esp, eregs);
+ return esp_do_phase_determine(esp, eregs, dregs);
}
if(!message_out) {
@@ -2275,13 +2716,13 @@ static int esp_do_status(struct Sparc_ESP *esp, struct ESP_regs *eregs)
if(SCptr->SCp.Message == COMMAND_COMPLETE) {
ESPSTAT(("and was COMMAND_COMPLETE\n"));
esp_advance_phase(SCptr, in_freeing);
- return esp_do_freebus(esp, eregs);
+ return esp_do_freebus(esp, eregs, dregs);
} else {
ESPLOG(("esp%d: and _not_ COMMAND_COMPLETE\n",
esp->esp_id));
esp->msgin_len = esp->msgin_ctr = 1;
esp_advance_phase(SCptr, in_msgindone);
- return esp_do_msgindone(esp, eregs);
+ return esp_do_msgindone(esp, eregs, dregs);
}
} else {
/* With luck we'll be able to let the target
@@ -2296,13 +2737,13 @@ static int esp_do_status(struct Sparc_ESP *esp, struct ESP_regs *eregs)
esp->cur_msgout[0] = message_out;
esp->msgout_len = esp->msgout_ctr = 1;
esp_advance_phase(SCptr, in_the_dark);
- return esp_do_phase_determine(esp, eregs);
+ return esp_do_phase_determine(esp, eregs, dregs);
}
} else {
/* If we disconnect now, all hell breaks loose. */
ESPLOG(("esp%d: whoops, disconnect\n", esp->esp_id));
esp_advance_phase(SCptr, in_the_dark);
- return esp_do_phase_determine(esp, eregs);
+ return esp_do_phase_determine(esp, eregs, dregs);
}
}
@@ -2310,7 +2751,8 @@ static int esp_do_status(struct Sparc_ESP *esp, struct ESP_regs *eregs)
* taken us.
*/
static int esp_do_phase_determine(struct Sparc_ESP *esp,
- struct ESP_regs *eregs)
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
@@ -2320,49 +2762,41 @@ static int esp_do_phase_determine(struct Sparc_ESP *esp,
case ESP_DOP:
case ESP_DIP:
ESPPHASE(("to data phase\n"));
- return esp_do_data(esp, eregs);
+ return esp_do_data(esp, eregs, dregs);
case ESP_STATP:
/* Whee, status phase, finish up the command. */
ESPPHASE(("to status phase\n"));
-
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-
- if(esp->do_pio_cmds){
- esp_advance_phase(SCptr, in_status);
+ if(esp->erev != fashme) {
+ esp->esp_command[0] = 0xff;
+ esp->esp_command[1] = 0xff;
+ eregs->esp_tclow = 2;
+ eregs->esp_tcmed = 0;
+ dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE);
+ if(esp->dma->revision == dvmaesc1)
+ dregs->cnt = 0x1000;
+ dregs->st_addr = esp->esp_command_dvma;
+ esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_ICCSEQ);
+ } else {
+ /* Using DVMA for status/message bytes is
+ * unreliable on HME, nice job QLogic.
+ * Happy Meal indeed....
+ */
esp_cmd(esp, eregs, ESP_CMD_ICCSEQ);
- while(!(esp->eregs->esp_status & ESP_STAT_INTR));
- esp->esp_command[0] = eregs->esp_fdata;
- while(!(esp->eregs->esp_status & ESP_STAT_INTR));
- esp->esp_command[1] = eregs->esp_fdata;
- } else {
- if(esp->erev != fashme) {
- esp->esp_command[0] = 0xff;
- esp->esp_command[1] = 0xff;
- eregs->esp_tclow = 2;
- eregs->esp_tcmed = 0;
- esp->dma_init_read(esp, esp->esp_command_dvma, 2);
- esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_ICCSEQ);
- } else {
- /* Using DVMA for status/message bytes is
- * unreliable on HME, nice job QLogic.
- * Happy Meal indeed....
- */
- esp_cmd(esp, eregs, ESP_CMD_ICCSEQ);
- }
- esp_advance_phase(SCptr, in_status);
}
- return esp_do_status(esp, eregs);
+ esp_advance_phase(SCptr, in_status);
+ return esp_do_status(esp, eregs, dregs);
case ESP_MOP:
ESPPHASE(("to msgout phase\n"));
esp_advance_phase(SCptr, in_msgout);
- return esp_do_msgout(esp, eregs);
+ return esp_do_msgout(esp, eregs, dregs);
case ESP_MIP:
ESPPHASE(("to msgin phase\n"));
esp_advance_phase(SCptr, in_msgin);
- return esp_do_msgin(esp, eregs);
+ return esp_do_msgin(esp, eregs, dregs);
case ESP_CMDP:
/* Ugh, we're running a non-standard command the
@@ -2370,7 +2804,7 @@ static int esp_do_phase_determine(struct Sparc_ESP *esp,
*/
ESPPHASE(("to cmd phase\n"));
esp_advance_phase(SCptr, in_cmdbegin);
- return esp_do_cmdbegin(esp, eregs);
+ return esp_do_cmdbegin(esp, eregs, dregs);
};
} else {
Scsi_Device *dp = SCptr->device;
@@ -2420,7 +2854,8 @@ static int esp_do_phase_determine(struct Sparc_ESP *esp,
}
/* First interrupt after exec'ing a cmd comes here. */
-static int esp_select_complete(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static int esp_select_complete(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
Scsi_Device *SDptr = SCptr->device;
@@ -2432,9 +2867,8 @@ static int esp_select_complete(struct Sparc_ESP *esp, struct ESP_regs *eregs)
fcnt = esp->hme_fifo_workaround_count;
else
fcnt = (eregs->esp_fflags & ESP_FF_FBYTES);
- cmd_bytes_sent = esp->dma_bytes_sent(esp, fcnt);
- if(esp->dma_invalidate)
- esp->dma_invalidate(esp);
+ cmd_bytes_sent = esp_bytes_sent(esp, dregs, fcnt);
+ dma_invalidate(dregs, esp->dma->revision);
/* Let's check to see if a reselect happened
* while we we're trying to select. This must
@@ -2442,7 +2876,7 @@ static int esp_select_complete(struct Sparc_ESP *esp, struct ESP_regs *eregs)
*/
if(esp->ireg == (ESP_INTR_RSEL | ESP_INTR_FDONE)) {
esp_reconnect(esp, SCptr);
- return esp_do_reconnect(esp, eregs);
+ return esp_do_reconnect(esp, eregs, dregs);
}
/* Looks like things worked, we should see a bus service &
@@ -2585,7 +3019,7 @@ static int esp_select_complete(struct Sparc_ESP *esp, struct ESP_regs *eregs)
/* Now figure out where we went. */
esp_advance_phase(SCptr, in_the_dark);
- return esp_do_phase_determine(esp, eregs);
+ return esp_do_phase_determine(esp, eregs, dregs);
}
/* Did the target even make it? */
@@ -2612,7 +3046,7 @@ static int esp_select_complete(struct Sparc_ESP *esp, struct ESP_regs *eregs)
esp->esp_id, SCptr->target, SCptr->lun);
SDptr->sync_max_offset = 0;
SDptr->sync_min_period = 0;
- SDptr->sync = 1; /* so we don't negotiate again */
+ SDptr->sync = 1; /* so we dont negotiate again */
/* Run the command again, this time though we
* won't try to negotiate for synchronous transfers.
@@ -2680,7 +3114,8 @@ static int esp_select_complete(struct Sparc_ESP *esp, struct ESP_regs *eregs)
}
/* Continue reading bytes for msgin phase. */
-static int esp_do_msgincont(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static int esp_do_msgincont(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
if(esp->ireg & ESP_INTR_BSERV) {
/* in the right phase too? */
@@ -2706,7 +3141,8 @@ static int esp_do_msgincont(struct Sparc_ESP *esp, struct ESP_regs *eregs)
}
static inline int check_singlebyte_msg(struct Sparc_ESP *esp,
- struct ESP_regs *eregs)
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
esp->prevmsgin = esp->cur_msgin[0];
if(esp->cur_msgin[0] & 0x80) {
@@ -2725,7 +3161,7 @@ static inline int check_singlebyte_msg(struct Sparc_ESP *esp,
switch(esp->cur_msgin[0]) {
default:
/* We don't want to hear about it. */
- ESPLOG(("esp%d: msg %02x which we don't know about\n", esp->esp_id,
+ ESPLOG(("esp%d: msg %02x which we dont know about\n", esp->esp_id,
esp->cur_msgin[0]));
return MESSAGE_REJECT;
@@ -2824,7 +3260,8 @@ static inline void sync_report(struct Sparc_ESP *esp)
}
static inline int check_multibyte_msg(struct Sparc_ESP *esp,
- struct ESP_regs *eregs)
+ struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
Scsi_Device *SDptr = SCptr->device;
@@ -2880,8 +3317,7 @@ static inline int check_multibyte_msg(struct Sparc_ESP *esp,
tmp = esp->ccycle / 1000;
regval = (((period << 2) + tmp - 1) / tmp);
if(regval && ((esp->erev == fas100a ||
- esp->erev == fas216 ||
- esp->erev == fas236 ||
+ esp->erev == fas236 ||
esp->erev == fashme))) {
if(period >= 50)
regval--;
@@ -2893,7 +3329,7 @@ static inline int check_multibyte_msg(struct Sparc_ESP *esp,
SDptr->sync_min_period = (regval & 0x1f);
SDptr->sync_max_offset = (offset | esp->radelay);
- if((esp->erev == fas100a || esp->erev == fas216 || esp->erev == fas236 || esp->erev == fashme)) {
+ if((esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme)) {
if((esp->erev == fas100a) || (esp->erev == fashme))
bit = ESP_CONFIG3_FAST;
else
@@ -2922,7 +3358,7 @@ static inline int check_multibyte_msg(struct Sparc_ESP *esp,
SDptr->sync_min_period = 0;
eregs->esp_soff = 0;
eregs->esp_stp = 0;
- if((esp->erev == fas100a || esp->erev == fas216 || esp->erev == fas236 || esp->erev == fashme)) {
+ if((esp->erev == fas100a || esp->erev == fas236 || esp->erev == fashme)) {
if((esp->erev == fas100a) || (esp->erev == fashme))
bit = ESP_CONFIG3_FAST;
else
@@ -2995,12 +3431,13 @@ finish:
return message_out;
}
-static int esp_do_msgindone(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static int esp_do_msgindone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
int message_out = 0, it = 0, rval;
- rval = skipahead1(esp, eregs, SCptr, in_msgin, in_msgindone);
+ rval = skipahead1(esp, eregs, dregs, SCptr, in_msgin, in_msgindone);
if(rval)
return rval;
if(SCptr->SCp.sent_command != in_status) {
@@ -3040,7 +3477,7 @@ static int esp_do_msgindone(struct Sparc_ESP *esp, struct ESP_regs *eregs)
if(esp->msgin_ctr < esp->msgin_len) {
esp_advance_phase(SCptr, in_msgincont);
} else if(esp->msgin_len == 1) {
- message_out = check_singlebyte_msg(esp, eregs);
+ message_out = check_singlebyte_msg(esp, eregs, dregs);
} else if(esp->msgin_len == 2) {
if(esp->cur_msgin[0] == EXTENDED_MESSAGE) {
if((it+2) >= 15) {
@@ -3053,7 +3490,7 @@ static int esp_do_msgindone(struct Sparc_ESP *esp, struct ESP_regs *eregs)
message_out = MESSAGE_REJECT; /* foo on you */
}
} else {
- message_out = check_multibyte_msg(esp, eregs);
+ message_out = check_multibyte_msg(esp, eregs, dregs);
}
}
if(message_out < 0) {
@@ -3073,16 +3510,18 @@ static int esp_do_msgindone(struct Sparc_ESP *esp, struct ESP_regs *eregs)
esp_cmd(esp, eregs, ESP_CMD_MOK);
if((SCptr->SCp.sent_command == in_msgindone) &&
(SCptr->SCp.phase == in_freeing))
- return esp_do_freebus(esp, eregs);
+ return esp_do_freebus(esp, eregs, dregs);
return do_intr_end;
}
-static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
esp_advance_phase(SCptr, in_cmdend);
if(esp->erev == fashme) {
+ unsigned long tmp = dregs->cond_reg;
int i;
for(i = 0; i < esp->esp_scmdleft; i++)
@@ -3091,7 +3530,11 @@ static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct ESP_regs *eregs)
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
esp_setcount(eregs, i, 1);
esp_cmd(esp, eregs, (ESP_CMD_DMA | ESP_CMD_TI));
- esp->dma_init_write(esp, esp->esp_command_dvma, i);
+ tmp |= (DMA_SCSI_DISAB | DMA_ENABLE);
+ tmp &= ~(DMA_ST_WRITE);
+ dregs->cnt = i;
+ dregs->st_addr = esp->esp_command_dvma;
+ dregs->cond_reg = tmp;
} else {
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
eregs->esp_fdata = *esp->esp_scmdp++;
@@ -3101,23 +3544,24 @@ static int esp_do_cmdbegin(struct Sparc_ESP *esp, struct ESP_regs *eregs)
return do_intr_end;
}
-static inline int esp_do_cmddone(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline int esp_do_cmddone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
- if(esp->erev == fashme){
- if(esp->dma_invalidate)
- esp->dma_invalidate(esp);
- } else
+ if(esp->erev == fashme)
+ dma_invalidate(dregs, dvmahme);
+ else
esp_cmd(esp, eregs, ESP_CMD_NULL);
if(esp->ireg & ESP_INTR_BSERV) {
esp_advance_phase(esp->current_SC, in_the_dark);
- return esp_do_phase_determine(esp, eregs);
+ return esp_do_phase_determine(esp, eregs, dregs);
}
ESPLOG(("esp%d: in do_cmddone() but didn't get BSERV interrupt.\n",
esp->esp_id));
return do_reset_bus;
}
-static int esp_do_msgout(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static int esp_do_msgout(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
esp_cmd(esp, eregs, ESP_CMD_FLUSH);
switch(esp->msgout_len) {
@@ -3130,71 +3574,51 @@ static int esp_do_msgout(struct Sparc_ESP *esp, struct ESP_regs *eregs)
break;
case 2:
- if(esp->do_pio_cmds){
- eregs->esp_fdata = esp->cur_msgout[0];
- eregs->esp_fdata = esp->cur_msgout[1];
+ esp->esp_command[0] = esp->cur_msgout[0];
+ esp->esp_command[1] = esp->cur_msgout[1];
+ if(esp->erev == fashme) {
+ hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 2);
esp_cmd(esp, eregs, ESP_CMD_TI);
} else {
- esp->esp_command[0] = esp->cur_msgout[0];
- esp->esp_command[1] = esp->cur_msgout[1];
- if(esp->erev == fashme) {
- hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 2);
- esp_cmd(esp, eregs, ESP_CMD_TI);
- } else {
- esp->dma_setup(esp, esp->esp_command_dvma, 2, 0);
- esp_setcount(eregs, 2, 0);
- esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
- }
+ dma_setup(dregs, esp->dma->revision,
+ esp->esp_command_dvma, 2, 0);
+ esp_setcount(eregs, 2, 0);
+ esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
}
break;
case 4:
+ esp->esp_command[0] = esp->cur_msgout[0];
+ esp->esp_command[1] = esp->cur_msgout[1];
+ esp->esp_command[2] = esp->cur_msgout[2];
+ esp->esp_command[3] = esp->cur_msgout[3];
esp->snip = 1;
- if(esp->do_pio_cmds){
- eregs->esp_fdata = esp->cur_msgout[0];
- eregs->esp_fdata = esp->cur_msgout[1];
- eregs->esp_fdata = esp->cur_msgout[2];
- eregs->esp_fdata = esp->cur_msgout[3];
+ if(esp->erev == fashme) {
+ hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 4);
esp_cmd(esp, eregs, ESP_CMD_TI);
} else {
- esp->esp_command[0] = esp->cur_msgout[0];
- esp->esp_command[1] = esp->cur_msgout[1];
- esp->esp_command[2] = esp->cur_msgout[2];
- esp->esp_command[3] = esp->cur_msgout[3];
- if(esp->erev == fashme) {
- hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 4);
- esp_cmd(esp, eregs, ESP_CMD_TI);
- } else {
- esp->dma_setup(esp, esp->esp_command_dvma, 4, 0);
- esp_setcount(eregs, 4, 0);
- esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
- }
+ dma_setup(dregs, esp->dma->revision,
+ esp->esp_command_dvma, 4, 0);
+ esp_setcount(eregs, 4, 0);
+ esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
}
break;
case 5:
+ esp->esp_command[0] = esp->cur_msgout[0];
+ esp->esp_command[1] = esp->cur_msgout[1];
+ esp->esp_command[2] = esp->cur_msgout[2];
+ esp->esp_command[3] = esp->cur_msgout[3];
+ esp->esp_command[4] = esp->cur_msgout[4];
esp->snip = 1;
- if(esp->do_pio_cmds){
- eregs->esp_fdata = esp->cur_msgout[0];
- eregs->esp_fdata = esp->cur_msgout[1];
- eregs->esp_fdata = esp->cur_msgout[2];
- eregs->esp_fdata = esp->cur_msgout[3];
- eregs->esp_fdata = esp->cur_msgout[4];
+ if(esp->erev == fashme) {
+ hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 5);
esp_cmd(esp, eregs, ESP_CMD_TI);
} else {
- esp->esp_command[0] = esp->cur_msgout[0];
- esp->esp_command[1] = esp->cur_msgout[1];
- esp->esp_command[2] = esp->cur_msgout[2];
- esp->esp_command[3] = esp->cur_msgout[3];
- esp->esp_command[4] = esp->cur_msgout[4];
- if(esp->erev == fashme) {
- hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 5);
- esp_cmd(esp, eregs, ESP_CMD_TI);
- } else {
- esp->dma_setup(esp, esp->esp_command_dvma, 5, 0);
- esp_setcount(eregs, 5, 0);
- esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
- }
+ dma_setup(dregs, esp->dma->revision,
+ esp->esp_command_dvma, 5, 0);
+ esp_setcount(eregs, 5, 0);
+ esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_TI);
}
break;
@@ -3215,12 +3639,23 @@ static int esp_do_msgout(struct Sparc_ESP *esp, struct ESP_regs *eregs)
return do_intr_end;
}
-static inline int esp_do_msgoutdone(struct Sparc_ESP *esp,
- struct ESP_regs *eregs)
+static inline int esp_do_msgoutdone(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
- if((esp->msgout_len > 1) && esp->dma_barrier)
- esp->dma_barrier(esp);
-
+ if(esp->msgout_len > 1) {
+ /* XXX HME/FAS ATN deassert workaround required,
+ * XXX no DMA flushing, only possible ESP_CMD_FLUSH
+ * XXX to kill the fifo.
+ */
+ if(esp->erev != fashme) {
+ while(dregs->cond_reg & DMA_PEND_READ)
+ udelay(1);
+ dregs->cond_reg &= ~(DMA_ENABLE);
+ dma_invalidate(dregs, esp->dma->revision);
+ } else {
+ esp_cmd(esp, eregs, ESP_CMD_FLUSH);
+ }
+ }
if(!(esp->ireg & ESP_INTR_DC)) {
if(esp->erev != fashme)
esp_cmd(esp, eregs, ESP_CMD_NULL);
@@ -3262,24 +3697,25 @@ static inline int esp_do_msgoutdone(struct Sparc_ESP *esp,
esp->prevmsgout = esp->cur_msgout[0];
esp->msgout_len = 0;
esp_advance_phase(esp->current_SC, in_the_dark);
- return esp_do_phase_determine(esp, eregs);
+ return esp_do_phase_determine(esp, eregs, dregs);
}
/* This is the second tier in our dual-level SCSI state machine. */
-static inline int esp_work_bus(struct Sparc_ESP *esp, struct ESP_regs *eregs)
+static inline int esp_work_bus(struct Sparc_ESP *esp, struct Sparc_ESP_regs *eregs,
+ struct sparc_dma_registers *dregs)
{
Scsi_Cmnd *SCptr = esp->current_SC;
ESPBUS(("esp_work_bus: "));
if(!SCptr) {
ESPBUS(("reconnect\n"));
- return esp_do_reconnect(esp, eregs);
+ return esp_do_reconnect(esp, eregs, dregs);
}
switch(SCptr->SCp.phase) {
case in_the_dark:
ESPBUS(("in the dark\n"));
- return esp_do_phase_determine(esp, eregs);
+ return esp_do_phase_determine(esp, eregs, dregs);
case in_slct_norm:
case in_slct_stop:
@@ -3287,48 +3723,48 @@ static inline int esp_work_bus(struct Sparc_ESP *esp, struct ESP_regs *eregs)
case in_slct_tag:
case in_slct_sneg:
ESPBUS(("finish selection\n"));
- return esp_select_complete(esp, eregs);
+ return esp_select_complete(esp, eregs, dregs);
case in_datain:
case in_dataout:
ESPBUS(("finish data\n"));
- return esp_do_data_finale(esp, eregs);
+ return esp_do_data_finale(esp, eregs, dregs);
case in_msgout:
ESPBUS(("message out "));
- return esp_do_msgout(esp, eregs);
+ return esp_do_msgout(esp, eregs, dregs);
case in_msgoutdone:
ESPBUS(("finish message out "));
- return esp_do_msgoutdone(esp, eregs);
+ return esp_do_msgoutdone(esp, eregs, dregs);
case in_msgin:
ESPBUS(("message in "));
- return esp_do_msgin(esp, eregs);
+ return esp_do_msgin(esp, eregs, dregs);
case in_msgincont:
ESPBUS(("continue message in "));
- return esp_do_msgincont(esp, eregs);
+ return esp_do_msgincont(esp, eregs, dregs);
case in_msgindone:
ESPBUS(("finish message in "));
- return esp_do_msgindone(esp, eregs);
+ return esp_do_msgindone(esp, eregs, dregs);
case in_status:
ESPBUS(("status phase "));
- return esp_do_status(esp, eregs);
+ return esp_do_status(esp, eregs, dregs);
case in_freeing:
ESPBUS(("freeing the bus "));
- return esp_do_freebus(esp, eregs);
+ return esp_do_freebus(esp, eregs, dregs);
case in_cmdbegin:
ESPBUS(("begin slow cmd "));
- return esp_do_cmdbegin(esp, eregs);
+ return esp_do_cmdbegin(esp, eregs, dregs);
case in_cmdend:
ESPBUS(("end slow cmd "));
- return esp_do_cmddone(esp, eregs);
+ return esp_do_cmddone(esp, eregs, dregs);
default:
printk("esp%d: command in weird state %2x\n",
@@ -3338,20 +3774,17 @@ static inline int esp_work_bus(struct Sparc_ESP *esp, struct ESP_regs *eregs)
}
/* Main interrupt handler for an esp adapter. */
-inline void esp_handle(struct Sparc_ESP *esp)
+static inline void esp_handle(struct Sparc_ESP *esp)
{
- struct ESP_regs *eregs;
+ struct sparc_dma_registers *dregs;
+ struct Sparc_ESP_regs *eregs;
Scsi_Cmnd *SCptr;
int what_next = do_intr_end;
-#ifdef CONFIG_SCSI_SUNESP
- struct sparc_dma_registers *dregs = esp->dregs;
-#endif
+
eregs = esp->eregs;
+ dregs = esp->dregs;
SCptr = esp->current_SC;
- if(esp->dma_irq_entry)
- esp->dma_irq_entry(esp);
-
/* Check for errors. */
esp->sreg = eregs->esp_status;
esp->sreg &= (~ESP_STAT_INTR);
@@ -3390,7 +3823,6 @@ inline void esp_handle(struct Sparc_ESP *esp)
}
}
-#ifdef CONFIG_SCSI_SUNESP
if(dregs->cond_reg & DMA_HNDL_ERROR) {
/* A DMA gate array error. Here we must
* be seeing one of two things. Either the
@@ -3405,13 +3837,11 @@ inline void esp_handle(struct Sparc_ESP *esp)
/* DMA gate array itself must be reset to clear the
* error condition.
*/
- if(esp->dma_reset)
- esp->dma_reset(esp);
+ esp_reset_dma(esp);
what_next = do_reset_bus;
goto again;
}
-#endif /* CONFIG_SCSI_SUNESP */
if(esp->erev == fashme) {
/* This chip is really losing. */
@@ -3456,7 +3886,7 @@ inline void esp_handle(struct Sparc_ESP *esp)
*/
ESPLOG(("esp%d: illegal command\n", esp->esp_id));
- esp_dump_state(esp, eregs);
+ esp_dump_state(esp, eregs, dregs);
if(SCptr) {
/* Devices with very buggy firmware can drop BSY
@@ -3483,9 +3913,9 @@ inline void esp_handle(struct Sparc_ESP *esp)
if(SCptr) {
phase = SCptr->SCp.phase;
if(phase & in_phases_mask) {
- what_next = esp_work_bus(esp, eregs);
+ what_next = esp_work_bus(esp, eregs, dregs);
} else if(phase & in_slct_mask) {
- what_next = esp_select_complete(esp, eregs);
+ what_next = esp_select_complete(esp, eregs, dregs);
} else {
ESPLOG(("esp%d: interrupt for no good reason...\n",
esp->esp_id));
@@ -3508,13 +3938,13 @@ inline void esp_handle(struct Sparc_ESP *esp)
} else if(esp->ireg & ESP_INTR_RSEL) {
if(!SCptr) {
/* This is ok. */
- what_next = esp_do_reconnect(esp, eregs);
+ what_next = esp_do_reconnect(esp, eregs, dregs);
} else if(SCptr->SCp.phase & in_slct_mask) {
/* Only selection code knows how to clean
* up properly.
*/
ESPDISC(("Reselected during selection attempt\n"));
- what_next = esp_select_complete(esp, eregs);
+ what_next = esp_select_complete(esp, eregs, dregs);
} else {
ESPLOG(("esp%d: Reselected while bus is busy\n",
esp->esp_id));
@@ -3533,11 +3963,11 @@ again:
goto esp_handle_done;
case do_work_bus:
- what_next = esp_work_bus(esp, eregs);
+ what_next = esp_work_bus(esp, eregs, dregs);
break;
case do_phase_determine:
- what_next = esp_do_phase_determine(esp, eregs);
+ what_next = esp_do_phase_determine(esp, eregs, dregs);
break;
case do_reset_bus:
@@ -3552,14 +3982,15 @@ again:
*/
if(esp->current_SC) {
Scsi_Cmnd *SCptr = esp->current_SC;
-
- if(!SCptr->use_sg) {
- if (esp->dma_mmu_release_scsi_one)
- esp->dma_mmu_release_scsi_one (esp, SCptr);
- } else {
- if (esp->dma_mmu_release_scsi_sgl)
- esp->dma_mmu_release_scsi_sgl (esp, SCptr);
- }
+ if(!SCptr->use_sg)
+ mmu_release_scsi_one(SCptr->SCp.have_data_in,
+ SCptr->request_bufflen,
+ esp->edev->my_bus);
+ else
+ mmu_release_scsi_sgl((struct mmu_sglist *)
+ SCptr->buffer,
+ SCptr->use_sg - 1,
+ esp->edev->my_bus);
SCptr->result = (DID_RESET << 16);
SCptr->scsi_done(SCptr);
@@ -3568,13 +3999,15 @@ again:
if(esp->disconnected_SC) {
Scsi_Cmnd *SCptr;
while((SCptr = remove_first_SC(&esp->disconnected_SC))) {
- if(!SCptr->use_sg) {
- if (esp->dma_mmu_release_scsi_one)
- esp->dma_mmu_release_scsi_one (esp, SCptr);
- } else {
- if (esp->dma_mmu_release_scsi_sgl)
- esp->dma_mmu_release_scsi_sgl (esp, SCptr);
- }
+ if(!SCptr->use_sg)
+ mmu_release_scsi_one(SCptr->SCp.have_data_in,
+ SCptr->request_bufflen,
+ esp->edev->my_bus);
+ else
+ mmu_release_scsi_sgl((struct mmu_sglist *)
+ SCptr->buffer,
+ SCptr->use_sg - 1,
+ esp->edev->my_bus);
SCptr->result = (DID_RESET << 16);
SCptr->scsi_done(SCptr);
@@ -3604,12 +4037,10 @@ again:
goto again;
esp_handle_done:
- if(esp->dma_irq_exit)
- esp->dma_irq_exit(esp);
return;
}
-void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+static void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
{
unsigned long flags;
@@ -3621,7 +4052,7 @@ void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
#ifndef __sparc_v9__
#ifndef __SMP__
-void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
{
struct Sparc_ESP *esp;
int again;
@@ -3630,23 +4061,19 @@ void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
repeat:
again = 0;
for_each_esp(esp) {
-#ifndef __mips__
if((esp->irq & 0xf) == irq) {
-#endif
- if(esp->dma_irq_p(esp)) {
+ if(DMA_IRQ_P(esp->dregs)) {
again = 1;
- esp->dma_ints_off(esp);
+ DMA_INTSOFF(esp->dregs);
ESPIRQ(("I%d(", esp->esp_id));
esp_handle(esp);
ESPIRQ((")"));
- esp->dma_ints_on(esp);
+ DMA_INTSON(esp->dregs);
}
-#ifndef __mips__
}
-#endif
}
if(again)
goto repeat;
@@ -3660,15 +4087,15 @@ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
/* Handle all ESP interrupts showing at this IRQ level. */
for_each_esp(esp) {
if(((esp)->irq & 0xf) == irq) {
- if(esp->dma_irq_p(esp)) {
- esp->dma_ints_off(esp);
+ if(DMA_IRQ_P(esp->dregs)) {
+ DMA_INTSOFF(esp->dregs);
ESPIRQ(("I[%d:%d](",
smp_processor_id(), esp->esp_id));
esp_handle(esp);
ESPIRQ((")"));
- esp->dma_ints_on(esp);
+ DMA_INTSON(esp->dregs);
return;
}
}
@@ -3676,7 +4103,7 @@ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
}
#endif
-#else
+#else /* __sparc_v9__ */
static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
{
@@ -3692,4 +4119,5 @@ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
DMA_INTSON(esp->dregs);
}
}
+
#endif
diff --git a/drivers/scsi/esp.h b/drivers/scsi/esp.h
index 76b9ca9f4..dcd8d8941 100644
--- a/drivers/scsi/esp.h
+++ b/drivers/scsi/esp.h
@@ -4,115 +4,11 @@
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
*/
-#ifndef _ESP_H
-#define _ESP_H
-
-/* Macros for debugging messages */
-
-/* #define DEBUG_ESP */
-/* #define DEBUG_ESP_HME */
-/* #define DEBUG_ESP_DATA */
-/* #define DEBUG_ESP_QUEUE */
-/* #define DEBUG_ESP_DISCONNECT */
-/* #define DEBUG_ESP_STATUS */
-/* #define DEBUG_ESP_PHASES */
-/* #define DEBUG_ESP_WORKBUS */
-/* #define DEBUG_STATE_MACHINE */
-/* #define DEBUG_ESP_CMDS */
-/* #define DEBUG_ESP_IRQS */
-/* #define DEBUG_SDTR */
-/* #define DEBUG_ESP_SG */
-
-/* Use the following to sprinkle debugging messages in a way which
- * suits you if combinations of the above become too verbose when
- * trying to track down a specific problem.
- */
-/* #define DEBUG_ESP_MISC */
-
-#if defined(DEBUG_ESP)
-#define ESPLOG(foo) printk foo
-#else
-#define ESPLOG(foo)
-#endif /* (DEBUG_ESP) */
-
-#if defined(DEBUG_ESP_HME)
-#define ESPHME(foo) printk foo
-#else
-#define ESPHME(foo)
-#endif
-
-#if defined(DEBUG_ESP_DATA)
-#define ESPDATA(foo) printk foo
-#else
-#define ESPDATA(foo)
-#endif
-
-#if defined(DEBUG_ESP_QUEUE)
-#define ESPQUEUE(foo) printk foo
-#else
-#define ESPQUEUE(foo)
-#endif
-
-#if defined(DEBUG_ESP_DISCONNECT)
-#define ESPDISC(foo) printk foo
-#else
-#define ESPDISC(foo)
-#endif
-
-#if defined(DEBUG_ESP_STATUS)
-#define ESPSTAT(foo) printk foo
-#else
-#define ESPSTAT(foo)
-#endif
-
-#if defined(DEBUG_ESP_PHASES)
-#define ESPPHASE(foo) printk foo
-#else
-#define ESPPHASE(foo)
-#endif
-
-#if defined(DEBUG_ESP_WORKBUS)
-#define ESPBUS(foo) printk foo
-#else
-#define ESPBUS(foo)
-#endif
-
-#if defined(DEBUG_ESP_IRQS)
-#define ESPIRQ(foo) printk foo
-#else
-#define ESPIRQ(foo)
-#endif
-
-#if defined(DEBUG_SDTR)
-#define ESPSDTR(foo) printk foo
-#else
-#define ESPSDTR(foo)
-#endif
-
-#if defined(DEBUG_ESP_MISC)
-#define ESPMISC(foo) printk foo
-#else
-#define ESPMISC(foo)
-#endif
-
-#define INTERNAL_ESP_ERROR \
- (panic ("Internal ESP driver error in file %s, line %d\n", \
- __FILE__, __LINE__))
-
-#define INTERNAL_ESP_ERROR_NOPANIC \
- (printk ("Internal ESP driver error in file %s, line %d\n", \
- __FILE__, __LINE__))
-
-
-/*
- * padding for register structure
- */
-#ifdef CONFIG_JAZZ_ESP
-#define EREGS_PAD(n)
-#else
-#define EREGS_PAD(n) unchar n[3];
-#endif
+#ifndef _SPARC_ESP_H
+#define _SPARC_ESP_H
+/* For dvma controller register definitions. */
+#include <asm/dma.h>
/* The ESP SCSI controllers have their register sets in three
* "classes":
@@ -128,48 +24,47 @@
* apart with a big-endian ordering to the bytes.
*/
-struct ESP_regs {
+struct Sparc_ESP_regs {
/* Access Description Offset */
volatile unchar esp_tclow; /* rw Low bits of the transfer count 0x00 */
- EREGS_PAD(tlpad);
+ unchar tlpad1[3];
volatile unchar esp_tcmed; /* rw Mid bits of the transfer count 0x04 */
- EREGS_PAD(fdpad);
+ unchar fdpad[3];
volatile unchar esp_fdata; /* rw FIFO data bits 0x08 */
- EREGS_PAD(cbpad);
+ unchar cbpad[3];
volatile unchar esp_cmd; /* rw SCSI command bits 0x0c */
- EREGS_PAD(stpad);
+ unchar stpad[3];
volatile unchar esp_status; /* ro ESP status register 0x10 */
#define esp_busid esp_status /* wo Bus ID for select/reselect 0x10 */
- EREGS_PAD(irqpd);
+ unchar irqpd[3];
volatile unchar esp_intrpt; /* ro Kind of interrupt 0x14 */
#define esp_timeo esp_intrpt /* wo Timeout value for select/resel 0x14 */
- EREGS_PAD(sspad);
+ unchar sspad[3];
volatile unchar esp_sstep; /* ro Sequence step register 0x18 */
#define esp_stp esp_sstep /* wo Transfer period per sync 0x18 */
- EREGS_PAD(ffpad);
+ unchar ffpad[3];
volatile unchar esp_fflags; /* ro Bits of current FIFO info 0x1c */
#define esp_soff esp_fflags /* wo Sync offset 0x1c */
- EREGS_PAD(cf1pd);
+ unchar cf1pd[3];
volatile unchar esp_cfg1; /* rw First configuration register 0x20 */
- EREGS_PAD(cfpad);
+ unchar cfpad[3];
volatile unchar esp_cfact; /* wo Clock conversion factor 0x24 */
#define esp_status2 esp_cfact /* ro HME status2 register 0x24 */
- EREGS_PAD(ctpad);
+ unchar ctpad[3];
volatile unchar esp_ctest; /* wo Chip test register 0x28 */
- EREGS_PAD(cf2pd);
+ unchar cf2pd[3];
volatile unchar esp_cfg2; /* rw Second configuration register 0x2c */
- EREGS_PAD(cf3pd);
+ unchar cf3pd[3];
/* The following is only found on the 53C9X series SCSI chips */
volatile unchar esp_cfg3; /* rw Third configuration register 0x30 */
- EREGS_PAD(holep);
- volatile unchar esp_hole; /* hole in register map 0x34 */
- EREGS_PAD(thpd);
+ unchar thpd[7];
+
/* The following is found on all chips except the NCR53C90 (ESP100) */
volatile unchar esp_tchi; /* rw High bits of transfer count 0x38 */
#define esp_uid esp_tchi /* ro Unique ID code 0x38 */
#define fas_rlo esp_tchi /* rw HME extended counter 0x38 */
- EREGS_PAD(fgpad);
+ unchar fgpad[3];
volatile unchar esp_fgrnd; /* rw Data base for fifo 0x3c */
#define fas_rhi esp_fgrnd /* rw HME extended counter 0x3c */
};
@@ -183,19 +78,18 @@ enum esp_rev {
fas100a = 0x04,
fast = 0x05,
fashme = 0x06,
- fas216 = 0x07,
- espunknown = 0x08
+ espunknown = 0x07
};
/* We get one of these for each ESP probed. */
struct Sparc_ESP {
struct Sparc_ESP *next; /* Next ESP on probed or NULL */
- struct ESP_regs *eregs; /* All esp registers */
+ struct Sparc_ESP_regs *eregs; /* All esp registers */
struct Linux_SBus_DMA *dma; /* Who I do transfers with. */
- void *dregs; /* And his registers. */
+ struct sparc_dma_registers *dregs; /* And his registers. */
struct Scsi_Host *ehost; /* Backpointer to SCSI Host */
- void *edev; /* Pointer to controller base/SBus */
+ struct linux_sbus_device *edev; /* Pointer to SBus entry */
char prom_name[64]; /* Name of ESP device from prom */
int prom_node; /* Prom node where ESP found */
int esp_id; /* Unique per-ESP ID number */
@@ -243,7 +137,6 @@ struct Sparc_ESP {
unsigned int sync_defp; /* Default sync transfer period */
unsigned int max_period; /* longest our period can be */
unsigned int min_period; /* shortest period we can withstand */
- unsigned char ccf; /* Clock conversion factor */
/* For slow to medium speed input clock rates we shoot for 5mb/s,
* but for high input clock rates we try to do 10mb/s although I
* don't think a transfer can even run that fast with an ESP even
@@ -285,40 +178,6 @@ struct Sparc_ESP {
* cannot be assosciated with any specific command.
*/
unchar resetting_bus;
-
- unchar do_pio_cmds; /* Do command transfer with pio */
-
- /* Functions handling DMA
- */
- /* Required functions */
- int (*dma_bytes_sent)(struct Sparc_ESP *, int);
- int (*dma_can_transfer)(struct Sparc_ESP *, Scsi_Cmnd *);
- void (*dma_dump_state)(struct Sparc_ESP *);
- void (*dma_init_read)(struct Sparc_ESP *, __u32, int);
- void (*dma_init_write)(struct Sparc_ESP *, __u32, int);
- void (*dma_ints_off)(struct Sparc_ESP *);
- void (*dma_ints_on)(struct Sparc_ESP *);
- int (*dma_irq_p)(struct Sparc_ESP *);
- int (*dma_ports_p)(struct Sparc_ESP *);
- void (*dma_setup)(struct Sparc_ESP *, __u32, int, int);
-
- /* Optional functions (i.e. may be initialized to 0) */
- void (*dma_barrier)(struct Sparc_ESP *);
- void (*dma_drain)(struct Sparc_ESP *);
- void (*dma_invalidate)(struct Sparc_ESP *);
- void (*dma_irq_entry)(struct Sparc_ESP *);
- void (*dma_irq_exit)(struct Sparc_ESP *);
- void (*dma_led_off)(struct Sparc_ESP *);
- void (*dma_led_on)(struct Sparc_ESP *);
- void (*dma_poll)(struct Sparc_ESP *, unsigned char *);
- void (*dma_reset)(struct Sparc_ESP *);
-
- /* Optional virtual DMA functions */
- void (*dma_mmu_get_scsi_one)(struct Sparc_ESP *, Scsi_Cmnd *);
- void (*dma_mmu_get_scsi_sgl)(struct Sparc_ESP *, Scsi_Cmnd *);
- void (*dma_mmu_release_scsi_one)(struct Sparc_ESP *, Scsi_Cmnd *);
- void (*dma_mmu_release_scsi_sgl)(struct Sparc_ESP *, Scsi_Cmnd *);
- void (*dma_advance_sg)(Scsi_Cmnd *);
};
/* Bitfield meanings for the above registers. */
@@ -525,19 +384,35 @@ struct Sparc_ESP {
#define ESP_MHZ_TO_CYCLE(mhertz) ((1000000000) / ((mhertz) / 1000))
#define ESP_TICK(ccf, cycle) ((7682 * (ccf) * (cycle) / 1000))
+extern int esp_detect(struct SHT *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *, unsigned int);
+extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
+ int hostno, int inout);
extern struct proc_dir_entry proc_scsi_esp;
-/* UGLY, UGLY, UGLY! */
-extern int nesps, esps_in_use, esps_running;
+#define SCSI_SPARC_ESP { \
+ proc_dir: &proc_scsi_esp, \
+ proc_info: &esp_proc_info, \
+ name: "Sun ESP 100/100a/200", \
+ detect: esp_detect, \
+ info: esp_info, \
+ command: esp_command, \
+ queuecommand: esp_queue, \
+ abort: esp_abort, \
+ reset: esp_reset, \
+ can_queue: 7, \
+ this_id: 7, \
+ sg_tablesize: SG_ALL, \
+ cmd_per_lun: 1, \
+ use_clustering: DISABLE_CLUSTERING, }
/* For our interrupt engine. */
#define for_each_esp(esp) \
for((esp) = espchain; (esp); (esp) = (esp)->next)
-extern void do_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
-/* External functions */
-extern struct Sparc_ESP *esp_allocate(Scsi_Host_Template *, void *);
-extern void esp_initialize(struct Sparc_ESP *);
-extern void esp_intr(int, void *, struct pt_regs *);
-#endif /* !(_ESP_H) */
+#endif /* !(_SPARC_ESP_H) */
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 078a875e6..fb7b28532 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -174,7 +174,7 @@
#endif
#ifdef CONFIG_SCSI_SUNESP
-#include "sparc_esp.h"
+#include "esp.h"
#endif
#ifdef CONFIG_SCSI_SGIWD93
diff --git a/drivers/scsi/sparc_esp.c b/drivers/scsi/sparc_esp.c
deleted file mode 100644
index 8bf8cf7e9..000000000
--- a/drivers/scsi/sparc_esp.c
+++ /dev/null
@@ -1,638 +0,0 @@
-/* sparc_esp.c: EnhancedScsiProcessor Sun SCSI driver code.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- *
- * Ugly generalization hacks by Jesper Skov. See "esp.c".
- */
-
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/malloc.h>
-#include <linux/blk.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-
-#include "scsi.h"
-#include "hosts.h"
-#include "esp.h"
-
-#include "sparc_esp.h"
-#include <asm/sbus.h>
-#include <asm/dma.h>
-#include <asm/machines.h>
-#include <asm/oplib.h>
-#include <asm/vaddrs.h>
-#include <asm/pgtable.h>
-
-extern struct Sparc_ESP *espchain;
-
-static void dma_barrier(struct Sparc_ESP *esp);
-static int dma_bytes_sent(struct Sparc_ESP *esp, int fifo_count);
-static int dma_can_transfer(struct Sparc_ESP *esp, Scsi_Cmnd *sp);
-static void dma_drain(struct Sparc_ESP *esp);
-static void dma_dump_state(struct Sparc_ESP *esp);
-static void dma_init_read(struct Sparc_ESP *esp, __u32 vaddress, int length);
-static void dma_init_write(struct Sparc_ESP *esp, __u32 vaddress, int length);
-static void dma_ints_off(struct Sparc_ESP *esp);
-static void dma_ints_on(struct Sparc_ESP *esp);
-static void dma_invalidate(struct Sparc_ESP *esp);
-static void dma_irq_entry(struct Sparc_ESP *esp);
-static void dma_irq_exit(struct Sparc_ESP *esp);
-static int dma_irq_p(struct Sparc_ESP *esp);
-static void dma_poll(struct Sparc_ESP *esp, unsigned char *vaddr);
-static int dma_ports_p(struct Sparc_ESP *esp);
-static void dma_reset(struct Sparc_ESP *esp);
-static void dma_setup(struct Sparc_ESP *esp, __u32 addr, int count, int write);
-static void dma_mmu_get_scsi_one (struct Sparc_ESP *esp, Scsi_Cmnd *sp);
-static void dma_mmu_get_scsi_sgl (struct Sparc_ESP *esp, Scsi_Cmnd *sp);
-static void dma_mmu_release_scsi_one (struct Sparc_ESP *esp, Scsi_Cmnd *sp);
-static void dma_mmu_release_scsi_sgl (struct Sparc_ESP *esp, Scsi_Cmnd *sp);
-static void dma_advance_sg (Scsi_Cmnd *sp);
-
-/* Detecting ESP chips on the machine. This is the simple and easy
- * version.
- */
-int esp_detect(Scsi_Host_Template *tpnt)
-{
- struct Sparc_ESP *esp, *elink;
- struct Scsi_Host *esp_host;
- struct linux_sbus *sbus;
- struct linux_sbus_device *esp_edev, *esp_dev, *sbdev_iter;
- struct ESP_regs *eregs;
- struct sparc_dma_registers *dregs;
- struct Linux_SBus_DMA *dma, *dlink;
- unchar bsizes, bsizes_more;
- int esp_node;
-
- if(!SBus_chain)
- panic("No SBUS in esp_detect()");
- for_each_sbus(sbus) {
- for_each_sbusdev(sbdev_iter, sbus) {
- struct linux_sbus_device *espdma = 0;
- int hme = 0;
-
- /* Is it an esp sbus device? */
- esp_dev = sbdev_iter;
- if(strcmp(esp_dev->prom_name, "esp") &&
- strcmp(esp_dev->prom_name, "SUNW,esp")) {
- if(!strcmp(esp_dev->prom_name, "SUNW,fas")) {
- hme = 1;
- espdma = esp_dev;
- } else {
- if(!esp_dev->child ||
- (strcmp(esp_dev->prom_name, "espdma") &&
- strcmp(esp_dev->prom_name, "dma")))
- continue; /* nope... */
- espdma = esp_dev;
- esp_dev = esp_dev->child;
- if(strcmp(esp_dev->prom_name, "esp") &&
- strcmp(esp_dev->prom_name, "SUNW,esp"))
- continue; /* how can this happen? */
- }
- }
-
- esp = esp_allocate(tpnt, (void *) esp_dev);
-
- esp_host = esp->ehost;
-
- if(hme)
- esp_host->max_id = 16;
-
- /* Do command transfer with DMA */
- esp->do_pio_cmds = 0;
-
- /* Required functions */
- esp->dma_bytes_sent = &dma_bytes_sent;
- esp->dma_can_transfer = &dma_can_transfer;
- esp->dma_dump_state = &dma_dump_state;
- esp->dma_init_read = &dma_init_read;
- esp->dma_init_write = &dma_init_write;
- esp->dma_ints_off = &dma_ints_off;
- esp->dma_ints_on = &dma_ints_on;
- esp->dma_irq_p = &dma_irq_p;
- esp->dma_ports_p = &dma_ports_p;
- esp->dma_setup = &dma_setup;
-
- /* Optional functions */
- esp->dma_barrier = &dma_barrier;
- esp->dma_drain = &dma_drain;
- esp->dma_invalidate = &dma_invalidate;
- esp->dma_irq_entry = &dma_irq_entry;
- esp->dma_irq_exit = &dma_irq_exit;
- esp->dma_led_on = 0;
- esp->dma_led_off = 0;
- esp->dma_poll = &dma_poll;
- esp->dma_reset = &dma_reset;
-
- /* virtual DMA functions */
- esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
- esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
- esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
- esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
- esp->dma_advance_sg = &dma_advance_sg;
-
- /* Get misc. prom information */
-#define ESP_IS_MY_DVMA(esp, dma) \
- ((((struct linux_sbus_device*)(esp->edev))->my_bus == dma->SBus_dev->my_bus) && \
- (((struct linux_sbus_device*)(esp->edev))->slot == dma->SBus_dev->slot) && \
- (!strcmp(dma->SBus_dev->prom_name, "dma") || \
- !strcmp(dma->SBus_dev->prom_name, "espdma")))
-
- esp_node = esp_dev->prom_node;
- prom_getstring(esp_node, "name", esp->prom_name,
- sizeof(esp->prom_name));
- esp->prom_node = esp_node;
- if(espdma) {
- for_each_dvma(dlink) {
- if(dlink->SBus_dev == espdma)
- break;
- }
- } else {
- for_each_dvma(dlink) {
- if(ESP_IS_MY_DVMA(esp, dlink) &&
- !dlink->allocated)
- break;
- }
- }
-#undef ESP_IS_MY_DVMA
- /* If we don't know how to handle the dvma,
- * do not use this device.
- */
- if(!dlink){
- printk ("Cannot find dvma for ESP%d's SCSI\n",
- esp->esp_id);
- scsi_unregister (esp_host);
- continue;
- }
- if (dlink->allocated){
- printk ("esp%d: can't use my espdma\n",
- esp->esp_id);
- scsi_unregister (esp_host);
- continue;
- }
- dlink->allocated = 1;
- dma = dlink;
- esp->dma = (struct Linux_SBus_DMA *) dma;
- esp->dregs = (void *) dregs = dma->regs;
-
- esp_edev = (struct linux_sbus_device *) esp->edev;
-
- /* Map in the ESP registers from I/O space */
- if(!hme) {
- prom_apply_sbus_ranges(esp_edev->my_bus,
- esp_edev->reg_addrs,
- 1, esp_edev);
- esp->eregs = eregs = (struct ESP_regs *)
- sparc_alloc_io(esp_edev->reg_addrs[0].phys_addr, 0,
- PAGE_SIZE, "ESP Registers",
- esp_edev->reg_addrs[0].which_io, 0x0);
- } else {
- /* On HME, two reg sets exist, first is DVMA,
- * second is ESP registers.
- */
- esp->eregs = eregs = (struct ESP_regs *)
- sparc_alloc_io(esp_edev->reg_addrs[1].phys_addr, 0,
- PAGE_SIZE, "ESP Registers",
- esp_edev->reg_addrs[1].which_io, 0x0);
- }
- if(!eregs)
- panic("ESP registers unmappable");
- esp->esp_command =
- sparc_dvma_malloc(16, "ESP DVMA Cmd Block",
- &esp->esp_command_dvma);
- if(!esp->esp_command || !esp->esp_command_dvma)
- panic("ESP DVMA transport area unmappable");
-
- /* Set up the irq's etc. */
- esp->ehost->io_port =
- esp_edev->reg_addrs[0].phys_addr;
- esp_host->n_io_port = (unsigned char)
- esp_edev->reg_addrs[0].reg_size;
- esp->irq = esp_edev->irqs[0].pri;
-
- /* Allocate the irq only if necessary */
- for_each_esp(elink) {
- if((elink != esp) && (esp->irq == elink->irq)) {
- goto esp_irq_acquired; /* BASIC rulez */
- }
- }
- if(request_irq(esp->irq, do_esp_intr, SA_SHIRQ,
- "Sparc ESP SCSI", NULL))
- panic("Cannot acquire ESP irq line");
-esp_irq_acquired:
- printk("esp%d: IRQ %d ", esp->esp_id, esp->irq);
-
- /* Figure out our scsi ID on the bus */
- esp->scsi_id = prom_getintdefault(esp->prom_node,
- "initiator-id",
- -1);
- if(esp->scsi_id == -1)
- esp->scsi_id = prom_getintdefault(esp->prom_node,
- "scsi-initiator-id",
- -1);
- if(esp->scsi_id == -1)
- esp->scsi_id =
- prom_getintdefault(esp_edev->my_bus->prom_node,
- "scsi-initiator-id",
- 7);
-
- /* Check for differential SCSI-bus */
- esp->diff = prom_getbool(esp->prom_node, "differential");
- if(esp->diff)
- printk("Differential ");
-
-
- /* SCSI chip clock */
- esp->cfreq = prom_getintdefault(esp->prom_node,
- "clock-frequency",
- -1);
- if(esp->cfreq==-1)
- esp->cfreq = prom_getintdefault(esp_edev->my_bus->prom_node,
- "clock-frequency",
- -1);
-
- /* Find the burst sizes this dma/sbus/esp supports. */
- bsizes = prom_getintdefault(esp->prom_node, "burst-sizes", 0xff);
- bsizes &= 0xff;
- if(espdma) {
- bsizes_more = prom_getintdefault(
- espdma->prom_node,
- "burst-sizes", 0xff);
- if(bsizes_more != 0xff)
- bsizes &= bsizes_more;
- }
- bsizes_more = prom_getintdefault(esp_edev->my_bus->prom_node,
- "burst-sizes", 0xff);
- if(bsizes_more != 0xff)
- bsizes &= bsizes_more;
-
- if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 ||
- (bsizes & DMA_BURST32)==0)
- bsizes = (DMA_BURST32 - 1);
-
- esp->bursts = bsizes;
-
- esp_initialize(esp);
-
- } /* for each sbusdev */
- } /* for each sbus */
- printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps,
- esps_in_use);
- esps_running = esps_in_use;
- return esps_in_use;
-}
-
-
-/************************************************************* DMA Functions */
-/* XXXX UGLY! : Duplicate esp_cmd here so it can remain inline in esp.c */
-static inline void esp_cmd(struct Sparc_ESP *esp,
- struct ESP_regs *eregs, unchar cmd)
-{
-#ifdef DEBUG_ESP_CMDS
- esp->espcmdlog[esp->espcmdent] = cmd;
- esp->espcmdent = (esp->espcmdent + 1) & 31;
-#endif
- eregs->esp_cmd = cmd;
-}
-
-static void dma_barrier(struct Sparc_ESP *esp)
-{
- struct sparc_dma_registers *dregs =
- (struct sparc_dma_registers *) esp->dregs;
-
- /* XXX HME/FAS ATN deassert workaround required,
- * XXX no DMA flushing, only possible ESP_CMD_FLUSH
- * XXX to kill the fifo.
- */
- if(esp->erev != fashme) {
- while(dregs->cond_reg & DMA_PEND_READ)
- udelay(1);
- dregs->cond_reg &= ~(DMA_ENABLE);
- dma_invalidate(esp);
- } else {
- esp_cmd(esp, esp->eregs, ESP_CMD_FLUSH);
- }
-}
-
-/* This uses various DMA csr fields and the fifo flags count value to
- * determine how many bytes were successfully sent/received by the ESP.
- */
-static int dma_bytes_sent(struct Sparc_ESP *esp, int fifo_count)
-{
- struct sparc_dma_registers *dregs =
- (struct sparc_dma_registers *) esp->dregs;
-
- int rval = dregs->st_addr - esp->esp_command_dvma;
-
- if(((struct Linux_SBus_DMA *) esp->dma)->revision == dvmarev1)
- rval -= (4 - ((dregs->cond_reg & DMA_READ_AHEAD)>>11));
- return rval - fifo_count;
-}
-
-static int dma_can_transfer(struct Sparc_ESP *esp, Scsi_Cmnd *sp)
-{
- __u32 base, end, sz;
- enum dvma_rev drev = ((struct Linux_SBus_DMA *) esp->dma)->revision;
-
- if(drev == dvmarev3) {
- sz = sp->SCp.this_residual;
- if(sz > 0x1000000)
- sz = 0x1000000;
- } else {
- base = ((__u32)sp->SCp.ptr);
- base &= (0x1000000 - 1);
- end = (base + sp->SCp.this_residual);
- if(end > 0x1000000)
- end = 0x1000000;
- sz = (end - base);
- }
- return sz;
-}
-
-static void dma_drain(struct Sparc_ESP *esp)
-{
- struct sparc_dma_registers *dregs =
- (struct sparc_dma_registers *) esp->dregs;
- enum dvma_rev drev = ((struct Linux_SBus_DMA *) esp->dma)->revision;
-
- if(drev == dvmahme)
- return;
- if(dregs->cond_reg & DMA_FIFO_ISDRAIN) {
- switch(drev) {
- default:
- dregs->cond_reg |= DMA_FIFO_STDRAIN;
-
- case dvmarev3:
- case dvmaesc1:
- while(dregs->cond_reg & DMA_FIFO_ISDRAIN)
- udelay(1);
- };
- }
-}
-
-static void dma_dump_state(struct Sparc_ESP *esp)
-{
- struct sparc_dma_registers *dregs =
- (struct sparc_dma_registers *) esp->dregs;
-
- ESPLOG(("esp%d: dma -- cond_reg<%08lx> addr<%p>\n",
- esp->esp_id, dregs->cond_reg, dregs->st_addr));
-}
-
-static void dma_flashclear(struct Sparc_ESP *esp)
-{
- dma_drain(esp);
- dma_invalidate(esp);
-}
-
-static void dma_init_read(struct Sparc_ESP *esp, __u32 vaddress, int length)
-{
- struct sparc_dma_registers *dregs =
- (struct sparc_dma_registers *) esp->dregs;
-
- dregs->cond_reg |= (DMA_ST_WRITE | DMA_ENABLE);
- if(((struct Linux_SBus_DMA *) esp->dma)->revision == dvmaesc1)
- dregs->cnt = 0x1000;
- dregs->st_addr = vaddress;
-}
-
-static void dma_init_write(struct Sparc_ESP *esp, __u32 vaddress, int length)
-{
- struct sparc_dma_registers *dregs =
- (struct sparc_dma_registers *) esp->dregs;
-
- if(esp->erev == fashme) {
- unsigned long tmp;
-
- /* Talk about touchy hardware... */
- tmp = dregs->cond_reg;
- tmp |= (DMA_SCSI_DISAB | DMA_ENABLE);
- tmp &= ~(DMA_ST_WRITE);
- dregs->cnt = length;
- dregs->st_addr = vaddress;
- dregs->cond_reg = tmp;
- } else {
- /* Set up the DMA counters */
- dregs->cond_reg = ((dregs->cond_reg & ~(DMA_ST_WRITE)) | DMA_ENABLE);
- if(((struct Linux_SBus_DMA *) esp->dma)->revision == dvmaesc1) {
- if(length) /* Workaround ESC gate array SBUS rerun bug. */
- dregs->cnt = (PAGE_SIZE);
- }
- dregs->st_addr = vaddress;
- }
-}
-
-static void dma_ints_off(struct Sparc_ESP *esp)
-{
- DMA_INTSOFF((struct sparc_dma_registers *) esp->dregs);
-}
-
-static void dma_ints_on(struct Sparc_ESP *esp)
-{
- DMA_INTSON((struct sparc_dma_registers *) esp->dregs);
-}
-
-static void dma_invalidate(struct Sparc_ESP *esp)
-{
- unsigned int tmp;
- struct sparc_dma_registers *dregs =
- (struct sparc_dma_registers *) esp->dregs;
-
- if(((struct Linux_SBus_DMA *) esp->dma)->revision == dvmahme) {
- /* SMCC can bite me. */
- tmp = dregs->cond_reg;
- dregs->cond_reg = DMA_RST_SCSI;
-
- /* This would explain a lot. */
- tmp |= (DMA_PARITY_OFF|DMA_2CLKS|DMA_SCSI_DISAB);
-
- tmp &= ~(DMA_ENABLE|DMA_ST_WRITE);
- dregs->cond_reg = 0;
- dregs->cond_reg = tmp;
- } else {
- while(dregs->cond_reg & DMA_PEND_READ)
- udelay(1);
-
- tmp = dregs->cond_reg;
- tmp &= ~(DMA_ENABLE | DMA_ST_WRITE | DMA_BCNT_ENAB);
- tmp |= DMA_FIFO_INV;
- dregs->cond_reg = tmp;
- dregs->cond_reg = (tmp & ~(DMA_FIFO_INV));
- }
-}
-
-static void dma_irq_entry(struct Sparc_ESP *esp)
-{
- DMA_IRQ_ENTRY((struct Linux_SBus_DMA *) esp->dma,
- (struct sparc_dma_registers *)esp->dregs);
-}
-
-static void dma_irq_exit(struct Sparc_ESP *esp)
-{
- DMA_IRQ_EXIT((struct Linux_SBus_DMA *) esp->dma,
- (struct sparc_dma_registers *) esp->dregs);
-}
-
-static int dma_irq_p(struct Sparc_ESP *esp)
-{
- return DMA_IRQ_P((struct sparc_dma_registers *) esp->dregs);
-}
-
-static void dma_poll(struct Sparc_ESP *esp, unsigned char *vaddr)
-{
- if(esp->erev != fashme) {
- dma_flashclear(esp);
-
- /* Wait till the first bits settle. */
- while(vaddr[0] == 0xff)
- udelay(1);
- } else {
- vaddr[0] = esp->hme_fifo_workaround_buffer[0];
- vaddr[1] = esp->hme_fifo_workaround_buffer[1];
- }
-}
-
-static int dma_ports_p(struct Sparc_ESP *esp)
-{
- return (((struct sparc_dma_registers *) esp->dregs)->cond_reg
- & DMA_INT_ENAB);
-}
-
-/* Resetting various pieces of the ESP scsi driver chipset/buses. */
-static void dma_reset(struct Sparc_ESP *esp)
-{
- struct sparc_dma_registers *dregs =
- (struct sparc_dma_registers *)esp->dregs;
- struct Linux_SBus_DMA *esp_dma = (struct Linux_SBus_DMA *) esp->dma;
- unsigned long tmp, flags;
- int can_do_burst16, can_do_burst32;
-
- can_do_burst16 = esp->bursts & DMA_BURST16;
- can_do_burst32 = esp->bursts & DMA_BURST32;
-
- /* Punt the DVMA into a known state. */
- if(esp_dma->revision != dvmahme) {
- dregs->cond_reg |= DMA_RST_SCSI;
- dregs->cond_reg &= ~(DMA_RST_SCSI);
- }
- switch(esp_dma->revision) {
- case dvmahme:
- /* This is the HME DVMA gate array. */
-
- save_flags(flags); cli(); /* I really hate this chip. */
-
- dregs->cond_reg = 0x08000000; /* Reset interface to FAS */
- dregs->cond_reg = DMA_RST_SCSI; /* Reset DVMA itself */
-
- tmp = (DMA_PARITY_OFF|DMA_2CLKS|DMA_SCSI_DISAB|DMA_INT_ENAB);
- tmp &= ~(DMA_ENABLE|DMA_ST_WRITE|DMA_BRST_SZ);
-
- if(can_do_burst32)
- tmp |= DMA_BRST32;
-
- /* This chip is horrible. */
- while(dregs->cond_reg & DMA_PEND_READ)
- udelay(1);
-
- dregs->cond_reg = 0;
-
- dregs->cond_reg = tmp; /* bite me */
- restore_flags(flags); /* ugh... */
- break;
- case dvmarev2:
- /* This is the gate array found in the sun4m
- * NCR SBUS I/O subsystem.
- */
- if(esp->erev != esp100)
- dregs->cond_reg |= DMA_3CLKS;
- break;
- case dvmarev3:
- dregs->cond_reg &= ~(DMA_3CLKS);
- dregs->cond_reg |= DMA_2CLKS;
- if(can_do_burst32) {
- dregs->cond_reg &= ~(DMA_BRST_SZ);
- dregs->cond_reg |= DMA_BRST32;
- }
- break;
- case dvmaesc1:
- /* This is the DMA unit found on SCSI/Ether cards. */
- dregs->cond_reg |= DMA_ADD_ENABLE;
- dregs->cond_reg &= ~DMA_BCNT_ENAB;
- if(!can_do_burst32 && can_do_burst16) {
- dregs->cond_reg |= DMA_ESC_BURST;
- } else {
- dregs->cond_reg &= ~(DMA_ESC_BURST);
- }
- break;
- default:
- break;
- };
- DMA_INTSON(dregs);
-}
-
-static void dma_setup(struct Sparc_ESP *esp, __u32 addr, int count, int write)
-{
- struct sparc_dma_registers *dregs =
- (struct sparc_dma_registers *) esp->dregs;
-
- unsigned long nreg = dregs->cond_reg;
- if(write)
- nreg |= DMA_ST_WRITE;
- else
- nreg &= ~(DMA_ST_WRITE);
- nreg |= DMA_ENABLE;
- dregs->cond_reg = nreg;
- if(((struct Linux_SBus_DMA *) esp->dma)->revision == dvmaesc1) {
- /* This ESC gate array sucks! */
- __u32 src = addr;
- __u32 dest = src + count;
-
- if(dest & (PAGE_SIZE - 1))
- count = PAGE_ALIGN(count);
- dregs->cnt = count;
- }
- dregs->st_addr = addr;
-}
-
-static void dma_mmu_get_scsi_one (struct Sparc_ESP *esp, Scsi_Cmnd *sp)
-{
- /* Sneaky. */
- sp->SCp.have_data_in = mmu_get_scsi_one((char *)sp->SCp.buffer,
- sp->SCp.this_residual,
- ((struct linux_sbus_device *)(esp->edev))->my_bus);
- /* XXX The casts are extremely gross, but with 64-bit kernel
- * XXX and 32-bit SBUS what am I to do? -DaveM
- */
- sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in);
-}
-
-static void dma_mmu_get_scsi_sgl (struct Sparc_ESP *esp, Scsi_Cmnd *sp)
-{
- mmu_get_scsi_sgl((struct mmu_sglist *) sp->SCp.buffer,
- sp->SCp.buffers_residual,
- ((struct linux_sbus_device *) (esp->edev))->my_bus);
- /* XXX Again these casts are sick... -DaveM */
- sp->SCp.ptr=(char *)((unsigned long)sp->SCp.buffer->dvma_address);
-}
-
-static void dma_mmu_release_scsi_one (struct Sparc_ESP *esp, Scsi_Cmnd *sp)
-{
- /* Sneaky. */
- mmu_release_scsi_one(sp->SCp.have_data_in,
- sp->request_bufflen,
- ((struct linux_sbus_device *) (esp->edev))->my_bus);
-}
-
-static void dma_mmu_release_scsi_sgl (struct Sparc_ESP *esp, Scsi_Cmnd *sp)
-{
- mmu_release_scsi_sgl((struct mmu_sglist *) sp->buffer,
- sp->use_sg - 1,
- ((struct linux_sbus_device *) (esp->edev))->my_bus);
-}
-
-static void dma_advance_sg (Scsi_Cmnd *sp)
-{
- sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address);
-}
diff --git a/drivers/scsi/sparc_esp.h b/drivers/scsi/sparc_esp.h
deleted file mode 100644
index 4cb20d27e..000000000
--- a/drivers/scsi/sparc_esp.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* sparc_esp.h: Defines and structures for the Sparc ESP (Enhanced SCSI
-¤ * Processor) driver under Linux.
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC_ESP_H
-#define _SPARC_ESP_H
-
-/* For dvma controller register definitions. */
-#include <asm/dma.h>
-
-extern int esp_detect(struct SHT *);
-extern const char *esp_info(struct Scsi_Host *);
-extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int esp_command(Scsi_Cmnd *);
-extern int esp_abort(Scsi_Cmnd *);
-extern int esp_reset(Scsi_Cmnd *, unsigned int);
-extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
- int hostno, int inout);
-
-extern struct proc_dir_entry proc_scsi_esp;
-
-#define DMA_PORTS_P (dregs->cond_reg & DMA_INT_ENAB)
-
-#define SCSI_JAZZ_ESP { \
- proc_dir: &proc_scsi_esp, \
- proc_info: &esp_proc_info, \
- name: "Sun ESP 100/100a/200", \
- detect: jazz_esp_detect, \
- info: esp_info, \
- command: esp_command, \
- queuecommand: esp_queue, \
- abort: esp_abort, \
- reset: esp_reset, \
- can_queue: 7, \
- this_id: 7, \
- sg_tablesize: SG_ALL, \
- cmd_per_lun: 1, \
- use_clustering: DISABLE_CLUSTERING, }
-
-#endif /* !(_SPARC_ESP_H) */