patch-2.1.101 linux/drivers/scsi/esp.c
Next file: linux/drivers/scsi/fastlane.c
Previous file: linux/drivers/scsi/cyberstormII.h
Back to the patch index
Back to the overall index
- Lines: 835
- Date:
Fri May 8 00:22:12 1998
- Orig file:
v2.1.100/linux/drivers/scsi/esp.c
- Orig date:
Tue Apr 14 14:29:22 1998
diff -u --recursive --new-file v2.1.100/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c
@@ -173,7 +173,9 @@
/* 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);
+#ifndef __sparc_v9__
+static void esp_intr_4d(int irq, void *dev_id, struct pt_regs *pregs);
+#endif
/* Debugging routines */
struct esp_cmdstrings {
@@ -641,25 +643,385 @@
trash = eregs->esp_intrpt;
}
-/* Detecting ESP chips on the machine. This is the simple and easy
- * version.
- */
-__initfunc(int esp_detect(Scsi_Host_Template *tpnt))
+__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))
{
-#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");
+ 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 = id;
+
+ /* 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) \
+ (!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 ");
+
+ /* Check out the clock properties of the chip. */
+
+ /* 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 = (!esp->edev->my_bus) ? 0 :
+ 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;
+ }
+ 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;
+ }
+
+ 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 {
+ 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;
+ }
+ esp->prevmsgout = esp->prevmsgin = 0;
+ esp->msgout_len = esp->msgin_len = 0;
+
+ /* Reset the thing before we try anything... */
+ esp_bootup_reset(esp, eregs);
+
+ 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) {
@@ -693,320 +1055,10 @@
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);
+
+ if (detect_one_esp(tpnt, esp_dev, espdma, sbus, nesps++, hme) < 0)
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;
-
-#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
-
- /* 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 ");
-
- /* Check out the clock properties of the chip. */
-
- /* 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 {
- 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;
- }
- 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 */
@@ -1016,6 +1068,8 @@
return esps_in_use;
}
+#endif /* !CONFIG_SUN4 */
+
/* The info function will return whatever useful
* information the developer sees fit. If not provided, then
* the name field will be used instead.
@@ -4040,24 +4094,17 @@
return;
}
-static 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__
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) {
@@ -4077,14 +4124,17 @@
}
if(again)
goto repeat;
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
#else
/* For SMP we only service one ESP on the list list at our IRQ level! */
static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
{
struct Sparc_ESP *esp;
+ unsigned long flags;
/* Handle all ESP interrupts showing at this IRQ level. */
+ spin_lock_irqsave(&io_request_lock, flags);
for_each_esp(esp) {
if(((esp)->irq & 0xf) == irq) {
if(DMA_IRQ_P(esp->dregs)) {
@@ -4096,19 +4146,41 @@
ESPIRQ((")"));
DMA_INTSON(esp->dregs);
- return;
+ goto out;
}
}
}
+out:
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
#endif
+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);
@@ -4118,6 +4190,6 @@
DMA_INTSON(esp->dregs);
}
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
-
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov