diff options
author | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 1998-05-12 19:25:07 +0000 |
---|---|---|
committer | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 1998-05-12 19:25:07 +0000 |
commit | 3b23e8acfab7fa5522ce96c58335607fe235562a (patch) | |
tree | 16750d1f63fa922c69693fca1ed8f2b2b8bc7d14 /drivers/scsi | |
parent | eceef87159b136a4a21395112b888e232ea8df76 (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/Makefile | 6 | ||||
-rw-r--r-- | drivers/scsi/esp.c | 1496 | ||||
-rw-r--r-- | drivers/scsi/esp.h | 221 | ||||
-rw-r--r-- | drivers/scsi/hosts.c | 2 | ||||
-rw-r--r-- | drivers/scsi/sparc_esp.c | 638 | ||||
-rw-r--r-- | drivers/scsi/sparc_esp.h | 42 |
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) */ |