diff options
author | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 1998-09-16 21:40:23 +0000 |
---|---|---|
committer | Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 1998-09-16 21:40:23 +0000 |
commit | 01a6bedbfdfa6d779c1e22ef4f8fd44e31278b3d (patch) | |
tree | 775abf47fc25dab9894df8ec7eb22f3e84e18eb0 /drivers/scsi | |
parent | e7a164b40732fc218a55b2fe709f9969c454b2c4 (diff) |
restored DaveM's playground; we are using NCR53C9x.c for our game.
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/esp.c | 1326 | ||||
-rw-r--r-- | drivers/scsi/esp.h | 221 |
2 files changed, 967 insertions, 580 deletions
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c index bc3ad6197..b1eb3e6ce 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,15 @@ 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); +#ifndef __sparc_v9__ +static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs); +#endif /* Debugging routines */ struct esp_cmdstrings { @@ -213,7 +297,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 +353,6 @@ static char *phase_string(int phase) return "UNKNOWN"; }; } -#endif static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase) { @@ -280,7 +363,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 @@ -315,7 +398,9 @@ extern inline void esp_cmd(struct Sparc_ESP *esp, struct ESP_regs *eregs, static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC) { Scsi_Cmnd *end; + unsigned long flags; + save_flags(flags); cli(); new_SC->host_scribble = (unsigned char *) NULL; if(!*SC) *SC = new_SC; @@ -324,27 +409,38 @@ static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC) ; end->host_scribble = (unsigned char *) new_SC; } + restore_flags(flags); } static inline void prepend_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC) { + unsigned long flags; + + save_flags(flags); cli(); new_SC->host_scribble = (unsigned char *) *SC; *SC = new_SC; + restore_flags(flags); } static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC) { Scsi_Cmnd *ptr; + unsigned long flags; + + save_flags(flags); cli(); ptr = *SC; if(ptr) *SC = (Scsi_Cmnd *) (*SC)->host_scribble; + restore_flags(flags); return ptr; } static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun) { Scsi_Cmnd *ptr, *prev; + unsigned long flags; + save_flags(flags); cli(); for(ptr = *SC, prev = NULL; ptr && ((ptr->target != target) || (ptr->lun != lun)); prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble) @@ -355,13 +451,82 @@ static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun) else *SC=(Scsi_Cmnd *)ptr->host_scribble; } + restore_flags(flags); 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; @@ -370,41 +535,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; @@ -424,7 +584,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; @@ -464,13 +623,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); @@ -485,23 +643,31 @@ 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 - */ -struct Sparc_ESP* esp_allocate(Scsi_Host_Template *tpnt, void *esp_dev) +__initfunc(int detect_one_esp +(Scsi_Host_Template *tpnt, struct linux_sbus_device *esp_dev, struct linux_sbus_device *espdma, + struct linux_sbus *sbus, int id, int hme)) { + struct devid_cookie dcookie; struct Sparc_ESP *esp, *elink; struct Scsi_Host *esp_host; - + 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 esp_node, i; + 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++; + esp->esp_id = id; /* Put into the chain of esp chips detected */ if(espchain) { @@ -513,20 +679,147 @@ struct Sparc_ESP* esp_allocate(Scsi_Host_Template *tpnt, void *esp_dev) } esp->next = 0; - return esp; -} + /* Get misc. prom information */ +#define ESP_IS_MY_DVMA(esp, dma) \ + (!dma->SBus_dev || \ + ((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); + return -1; + } + if (dlink->allocated){ + printk ("esp%d: can't use my espdma\n", + esp->esp_id); + scsi_unregister (esp_host); + return -1; + } + 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; + +#ifndef __sparc_v9__ + if (sparc_cpu_model != sun4d) { + /* 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, 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 { + dcookie.real_dev_id = esp; + dcookie.bus_cookie = esp_dev; + if (request_irq(esp->ehost->irq, esp_intr_4d, + (SA_SHIRQ | SA_DCOOKIE), + "Sparc ESP SCSI", &dcookie)) + panic("Cannot acquire ESP irq line"); + printk("esp%d: INO[%x] IRQ %d ", esp->esp_id, dcookie.ret_ino, esp->ehost->irq); + esp->ehost->irq = esp->irq = dcookie.ret_ino; + } +#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, 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 + + /* 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 = (!esp->edev->my_bus) ? 7 : + 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 "); -/* 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. */ /* This is getting messy but it has to be done @@ -574,9 +867,15 @@ void esp_initialize(struct Sparc_ESP *esp) * This entails the smallest and largest sync * period we could ever handle on this ESP. */ - - fmhz = esp->cfreq; + fmhz = prom_getintdefault(esp->prom_node, + "clock-frequency", + -1); + if(fmhz==-1) + fmhz = (!esp->edev->my_bus) ? 0 : + prom_getintdefault(esp->edev->my_bus->prom_node, + "clock-frequency", + -1); if(fmhz <= (5000000)) ccf = 0; else @@ -603,18 +902,32 @@ void esp_initialize(struct Sparc_ESP *esp) 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); + 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; + } + if (esp->edev->my_bus) { + bsizes_more = prom_getintdefault(esp->edev->my_bus->prom_node, + "burst-sizes", 0xff); + if(bsizes_more != 0xff) + bsizes &= bsizes_more; + } - /* Fill in ehost data */ - esp->ehost->base = (unsigned char *) eregs; - esp->ehost->this_id = esp->scsi_id; - esp->ehost->irq = esp->irq; + if(bsizes == 0xff || (bsizes & DMA_BURST16)==0 || + (bsizes & DMA_BURST32)==0) + bsizes = (DMA_BURST32 - 1); - /* SCSI id mask */ - esp->scsi_id_mask = (1 << esp->scsi_id); + esp->bursts = bsizes; /* Probe the revision of this esp */ esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7)); @@ -633,7 +946,7 @@ void esp_initialize(struct Sparc_ESP *esp) esp->erev = esp100a; } else { int target; - + for(target=0; target<8; target++) esp->config3[target] = 0; eregs->esp_cfg3 = 0; @@ -649,12 +962,12 @@ void esp_initialize(struct Sparc_ESP *esp) } } } - + /* 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; @@ -672,8 +985,87 @@ void esp_initialize(struct Sparc_ESP *esp) /* Reset the thing before we try anything... */ esp_bootup_reset(esp, eregs); - - esps_in_use++; + + return 0; +} + +/* Detecting ESP chips on the machine. This is the simple and easy + * version. + */ + +#ifdef CONFIG_SUN4 + +#include <asm/sun4paddr.h> + +__initfunc(int esp_detect(Scsi_Host_Template *tpnt)) +{ + static struct linux_sbus_device esp_dev; + int esps_in_use = 0; + + espchain = 0; + + memset (&esp_dev, 0, sizeof(esp_dev)); + esp_dev.reg_addrs[0].phys_addr = SUN4_300_ESP_PHYSADDR; + esp_dev.irqs[0].pri = 4; + + if (!detect_one_esp(tpnt, &esp_dev, NULL, NULL, 0, 0)) + esps_in_use++; + printk("ESP: Total of 1 ESP hosts found, %d actually in use.\n", esps_in_use); + esps_running = esps_in_use; + return esps_in_use; +} + +#else /* !CONFIG_SUN4 */ + +__initfunc(int esp_detect(Scsi_Host_Template *tpnt)) +{ + struct linux_sbus *sbus; + struct linux_sbus_device *esp_dev, *sbdev_iter; + int nesps = 0, esps_in_use = 0; + + espchain = 0; + if(!SBus_chain) { +#ifdef CONFIG_PCI + return 0; +#else + panic("No SBUS in esp_detect()"); +#endif + } + 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? */ + } + } + + if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0) + continue; + + 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; } #endif /* !CONFIG_SUN4 */ @@ -694,8 +1086,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: @@ -774,9 +1164,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; @@ -794,7 +1181,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: @@ -822,7 +1208,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)) @@ -947,7 +1332,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; @@ -956,7 +1342,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. */ @@ -1006,9 +1392,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 @@ -1043,7 +1427,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. @@ -1061,7 +1444,7 @@ do_sync_known: esp->snip = 0; goto do_sync_known; } -#endif + /* We've talked to this guy before, * but never negotiated. Let's try, * need to attempt WIDE first, before @@ -1165,36 +1548,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); } } @@ -1202,6 +1587,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. */ @@ -1209,9 +1595,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)); @@ -1222,11 +1606,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 @@ -1236,10 +1623,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; @@ -1254,7 +1642,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) @@ -1267,9 +1655,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; @@ -1285,8 +1671,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 @@ -1294,10 +1680,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", @@ -1341,12 +1725,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. @@ -1354,20 +1739,23 @@ int esp_abort(Scsi_Cmnd *SCptr) * in the driver and timeout because the eventual phase change * will cause the ESP to (eventually) give an interrupt. */ + save_and_cli(flags); if(esp->current_SC == SCptr) { esp->cur_msgout[0] = ABORT; esp->msgout_len = 1; esp->msgout_ctr = 0; esp_cmd(esp, eregs, ESP_CMD_SATN); + restore_flags(flags); return SCSI_ABORT_PENDING; } + restore_flags(flags); /* 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) { @@ -1382,7 +1770,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; } } @@ -1412,7 +1800,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; @@ -1426,20 +1814,24 @@ static void esp_done(struct Sparc_ESP *esp, int error) Scsi_Cmnd *done_SC; if(esp->current_SC) { + unsigned long flags; + done_SC = esp->current_SC; esp->current_SC = NULL; /* 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 @@ -1448,9 +1840,13 @@ static void esp_done(struct Sparc_ESP *esp, int error) done_SC->result = error; done_SC->scsi_done(done_SC); + save_and_cli(flags); + /* Bus is free, issue any commands in the queue. */ if(esp->issue_SC && !esp->current_SC) esp_exec_cmd(esp); + + restore_flags(flags); } else { /* Panic is safe as current_SC is null so we may still * be able to accept more commands to sync disk buffers. @@ -1468,15 +1864,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) { @@ -1490,7 +1893,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; @@ -1526,7 +1929,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); @@ -1540,13 +1943,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) { @@ -1572,15 +1975,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) { @@ -1607,8 +2010,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); @@ -1618,13 +2113,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; @@ -1632,7 +2127,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; @@ -1644,7 +2139,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); @@ -1666,7 +2161,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. */ @@ -1693,14 +2188,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; @@ -1709,7 +2203,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; @@ -1739,7 +2233,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; @@ -1759,7 +2253,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; @@ -1788,7 +2282,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)) @@ -1801,15 +2296,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_ @@ -1830,8 +2336,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; @@ -1841,21 +2347,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); } @@ -1864,14 +2377,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) { @@ -1886,18 +2397,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. @@ -1979,10 +2488,6 @@ static inline int esp_do_data_finale(struct Sparc_ESP *esp, ESPLOG(("esp%d: use_sg=%d ptr=%p this_residual=%d\n", esp->esp_id, SCptr->use_sg, SCptr->SCp.ptr, SCptr->SCp.this_residual)); - ESPLOG(("esp%d: Forcing async for target %d\n", esp->esp_id, - SCptr->target)); - SCptr->device->borken = 1; - SCptr->device->sync = 0; bytes_sent = 0; } @@ -2008,13 +2513,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", @@ -2025,15 +2530,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... */ @@ -2100,8 +2605,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; @@ -2125,8 +2630,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)) @@ -2176,15 +2680,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) { @@ -2194,8 +2698,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 @@ -2249,7 +2761,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) { @@ -2258,13 +2770,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 @@ -2279,13 +2791,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); } } @@ -2293,7 +2805,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; @@ -2303,49 +2816,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 @@ -2353,7 +2858,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; @@ -2403,7 +2908,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; @@ -2415,9 +2921,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 @@ -2425,7 +2930,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 & @@ -2568,7 +3073,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? */ @@ -2663,7 +3168,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? */ @@ -2689,7 +3195,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) { @@ -2807,7 +3314,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; @@ -2863,8 +3371,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--; @@ -2876,7 +3383,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 @@ -2905,7 +3412,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 @@ -2978,12 +3485,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) { @@ -3023,7 +3531,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) { @@ -3036,7 +3544,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) { @@ -3056,16 +3564,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++) @@ -3074,35 +3584,38 @@ 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 { - unsigned char tmp; esp_cmd(esp, eregs, ESP_CMD_FLUSH); - tmp = *esp->esp_scmdp++; + eregs->esp_fdata = *esp->esp_scmdp++; esp->esp_scmdleft--; - eregs->esp_fdata = tmp; esp_cmd(esp, eregs, ESP_CMD_TI); } 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) { @@ -3115,71 +3628,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; @@ -3200,12 +3693,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); @@ -3247,24 +3751,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: @@ -3272,48 +3777,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", @@ -3323,20 +3828,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); @@ -3375,7 +3877,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 @@ -3390,13 +3891,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. */ @@ -3441,7 +3940,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 @@ -3468,9 +3967,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)); @@ -3493,13 +3992,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)); @@ -3518,11 +4017,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: @@ -3537,14 +4036,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); @@ -3553,13 +4053,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); @@ -3589,49 +4091,36 @@ 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) -{ - unsigned long flags; - - spin_lock_irqsave(&io_request_lock, flags); - esp_intr(irq, dev_id, pregs); - spin_unlock_irqrestore(&io_request_lock, flags); -} - #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; + unsigned long flags; int again; /* Handle all ESP interrupts showing at this IRQ level. */ + spin_lock_irqsave(&io_request_lock, flags); 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; @@ -3648,28 +4137,50 @@ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) spin_lock_irqsave(&io_request_lock, flags); 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); - return; + DMA_INTSON(esp->dregs); + goto out; } } } +out: + spin_unlock_irqrestore(&io_request_lock, flags); } #endif -#else +static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs) +{ + struct Sparc_ESP *esp = dev_id; + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + if(DMA_IRQ_P(esp->dregs)) { + DMA_INTSOFF(esp->dregs); + + ESPIRQ(("I[%d:%d](", smp_processor_id(), esp->esp_id)); + esp_handle(esp); + ESPIRQ((")")); + + DMA_INTSON(esp->dregs); + } + spin_unlock_irqrestore(&io_request_lock, flags); +} + +#else /* __sparc_v9__ */ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) { struct Sparc_ESP *esp = dev_id; + unsigned long flags; + spin_lock_irqsave(&io_request_lock, flags); if(DMA_IRQ_P(esp->dregs)) { DMA_INTSOFF(esp->dregs); @@ -3681,3 +4192,4 @@ static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs) } spin_unlock_irqrestore(&io_request_lock, flags); } +#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) */ |