summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qlogicpti.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
commit78c388aed2b7184182c08428db1de6c872d815f5 (patch)
tree4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /drivers/scsi/qlogicpti.c
parenteb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff)
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'drivers/scsi/qlogicpti.c')
-rw-r--r--drivers/scsi/qlogicpti.c252
1 files changed, 89 insertions, 163 deletions
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 37a929adb..c3d4102bf 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -564,6 +564,9 @@ static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti)
}
static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *regs);
+#ifndef __sparc_v9__
+static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs);
+#endif
/* Detect all PTI Qlogic ISP's in the machine. */
__initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
@@ -671,34 +674,30 @@ __initfunc(int qlogicpti_detect(Scsi_Host_Template *tpnt))
qpti_host->irq = qpti->irq = qpti->qdev->irqs[0];
-#ifndef __sparc_v9__
- /* Allocate the irq only if necessary. */
+ /* On Ultra and S{S1,C2}000 we must always call request_irq for each
+ * qpti, so that imap registers get setup etc.
+ * But irq values are different in that case anyway...
+ * Otherwise allocate the irq only if necessary.
+ */
for_each_qlogicpti(qlink) {
if((qlink != qpti) && (qpti->irq == qlink->irq)) {
goto qpti_irq_acquired; /* BASIC rulez */
}
}
- if(request_irq(qpti->qhost->irq, do_qlogicpti_intr_handler,
- SA_SHIRQ, "PTI Qlogic/ISP SCSI", NULL)) {
- printk("Cannot acquire PTI Qlogic/ISP irq line\n");
- /* XXX Unmap regs, unregister scsi host, free things. */
- continue;
- }
-qpti_irq_acquired:
- printk("qpti%d: IRQ %d ", qpti->qpti_id, qpti->qhost->irq);
-#else
- /* On Ultra we must always call request_irq for each
- * qpti, so that imap registers get setup etc.
- */
- if(request_irq(qpti->qhost->irq, do_qlogicpti_intr_handler,
+ if(request_irq(qpti->qhost->irq,
+#ifndef __sparc_v9__
+ (sparc_cpu_model == sun4m || sparc_cpu_model == sun4c) ?
+ do_qlogicpti_intr_handler_sun4m :
+#endif
+ do_qlogicpti_intr_handler,
SA_SHIRQ, "PTI Qlogic/ISP SCSI", qpti)) {
printk("Cannot acquire PTI Qlogic/ISP irq line\n");
/* XXX Unmap regs, unregister scsi host, free things. */
continue;
}
+qpti_irq_acquired:
printk("qpti%d: IRQ %s ",
qpti->qpti_id, __irq_itoa(qpti->qhost->irq));
-#endif
/* Figure out our scsi ID on the bus */
qpti->scsi_id = prom_getintdefault(qpti->prom_node,
@@ -809,8 +808,8 @@ const char *qlogicpti_info(struct Scsi_Host *host)
static char buf[80];
struct qlogicpti *qpti = (struct qlogicpti *) host->hostdata;
- sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %d regs at %08lx",
- host->irq, (unsigned long) qpti->qregs);
+ sprintf(buf, "PTI Qlogic,ISP SBUS SCSI irq %s regs at %08lx",
+ __irq_itoa(qpti->qhost->irq), (unsigned long) qpti->qregs);
return buf;
}
@@ -1068,162 +1067,89 @@ static int qlogicpti_return_status(struct Status_Entry *sts)
return (sts->scsi_status & STATUS_MASK) | (host_status << 16);
}
-#ifndef __sparc_v9__
-
-static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id,
- struct pt_regs *regs)
+static __inline__ int qlogicpti_intr_handler(struct qlogicpti *qpti)
{
- static int running = 0;
Scsi_Cmnd *Cmnd;
struct Status_Entry *sts;
- struct qlogicpti *qpti;
u_int in_ptr, out_ptr;
- int again;
-
- /* It is ok to take irq's on one qpti while the other
- * is amidst the processing of a reset.
- */
- running++;
-
-#if 0 /* XXX Investigate why resets cause this with one controller. */
- if(running > qptis_running)
- printk("qlogicpti_intr_handler: yieee, recursive interrupt!\n");
-#endif
-
- /* Handle all ISP interrupts showing */
-repeat:
- again = 0;
- for_each_qlogicpti(qpti) {
- if(qpti->qregs->sbus_stat & SBUS_STAT_RINT) {
- struct qlogicpti_regs *qregs = qpti->qregs;
-
- again = 1;
- in_ptr = qregs->mbox5;
- qregs->hcctrl = HCCTRL_CRIRQ;
- if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) {
- switch(qregs->mbox0) {
- case ASYNC_SCSI_BUS_RESET:
- case EXECUTION_TIMEOUT_RESET:
- qpti->send_marker = 1;
- break;
- case INVALID_COMMAND:
- case HOST_INTERFACE_ERROR:
- case COMMAND_ERROR:
- case COMMAND_PARAM_ERROR:
- break;
- }
- qregs->sbus_semaphore = 0;
- }
+ struct qlogicpti_regs *qregs;
- /* This looks like a network driver! */
- out_ptr = qpti->res_out_ptr;
- while(out_ptr != in_ptr) {
- sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
- out_ptr = NEXT_RES_PTR(out_ptr);
- Cmnd = (Scsi_Cmnd *) ((unsigned long)sts->handle);
- if(sts->completion_status == CS_RESET_OCCURRED ||
- sts->completion_status == CS_ABORTED ||
- (sts->status_flags & STF_BUS_RESET))
- qpti->send_marker = 1;
-
- if(sts->state_flags & SF_GOT_SENSE)
- memcpy(Cmnd->sense_buffer, sts->req_sense_data,
- sizeof(Cmnd->sense_buffer));
-
- if(sts->hdr.entry_type == ENTRY_STATUS)
- Cmnd->result = qlogicpti_return_status(sts);
- else
- Cmnd->result = DID_ERROR << 16;
-
- if(Cmnd->use_sg)
- mmu_release_scsi_sgl((struct mmu_sglist *)
- Cmnd->buffer,
- Cmnd->use_sg - 1,
- qpti->qdev->my_bus);
- else
- mmu_release_scsi_one((__u32)Cmnd->SCp.ptr,
- Cmnd->request_bufflen,
- qpti->qdev->my_bus);
-
- qpti->cmd_count[Cmnd->target]--;
- qregs->mbox5 = out_ptr;
- Cmnd->scsi_done(Cmnd);
- }
- qpti->res_out_ptr = out_ptr;
+ if(!(qpti->qregs->sbus_stat & SBUS_STAT_RINT))
+ return 0;
+
+ qregs = qpti->qregs;
+
+ in_ptr = qregs->mbox5;
+ qregs->hcctrl = HCCTRL_CRIRQ;
+ if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) {
+ switch(qregs->mbox0) {
+ case ASYNC_SCSI_BUS_RESET:
+ case EXECUTION_TIMEOUT_RESET:
+ qpti->send_marker = 1;
+ break;
+ case INVALID_COMMAND:
+ case HOST_INTERFACE_ERROR:
+ case COMMAND_ERROR:
+ case COMMAND_PARAM_ERROR:
+ break;
}
+ qregs->sbus_semaphore = 0;
}
- if(again)
- goto repeat;
- running--;
+
+ /* This looks like a network driver! */
+ out_ptr = qpti->res_out_ptr;
+ while(out_ptr != in_ptr) {
+ sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
+ out_ptr = NEXT_RES_PTR(out_ptr);
+ Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET);
+
+ if(sts->completion_status == CS_RESET_OCCURRED ||
+ sts->completion_status == CS_ABORTED ||
+ (sts->status_flags & STF_BUS_RESET))
+ qpti->send_marker = 1;
+
+ if(sts->state_flags & SF_GOT_SENSE)
+ memcpy(Cmnd->sense_buffer, sts->req_sense_data,
+ sizeof(Cmnd->sense_buffer));
+
+ if(sts->hdr.entry_type == ENTRY_STATUS)
+ Cmnd->result = qlogicpti_return_status(sts);
+ else
+ Cmnd->result = DID_ERROR << 16;
+
+ if(Cmnd->use_sg)
+ mmu_release_scsi_sgl((struct mmu_sglist *)
+ Cmnd->buffer,
+ Cmnd->use_sg - 1,
+ qpti->qdev->my_bus);
+ else
+ mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr),
+ Cmnd->request_bufflen,
+ qpti->qdev->my_bus);
+
+ qpti->cmd_count[Cmnd->target]--;
+ qregs->mbox5 = out_ptr;
+ Cmnd->scsi_done(Cmnd);
+ }
+ qpti->res_out_ptr = out_ptr;
+ return 1;
}
-#else /* __sparc_v9__ */
+#ifndef __sparc_v9__
-static __inline__ void qlogicpti_intr_handler(int irq, void *dev_id,
- struct pt_regs *regs)
+static void do_qlogicpti_intr_handler_sun4m(int irq, void *dev_id, struct pt_regs *regs)
{
- struct qlogicpti *qpti = dev_id;
- Scsi_Cmnd *Cmnd;
- struct Status_Entry *sts;
- u_int in_ptr, out_ptr;
-
- if(qpti->qregs->sbus_stat & SBUS_STAT_RINT) {
- struct qlogicpti_regs *qregs = qpti->qregs;
-
- in_ptr = qregs->mbox5;
- qregs->hcctrl = HCCTRL_CRIRQ;
- if(qregs->sbus_semaphore & SBUS_SEMAPHORE_LCK) {
- switch(qregs->mbox0) {
- case ASYNC_SCSI_BUS_RESET:
- case EXECUTION_TIMEOUT_RESET:
- qpti->send_marker = 1;
- break;
- case INVALID_COMMAND:
- case HOST_INTERFACE_ERROR:
- case COMMAND_ERROR:
- case COMMAND_PARAM_ERROR:
- break;
- }
- qregs->sbus_semaphore = 0;
- }
+ unsigned long flags;
+ struct qlogicpti *qpti;
+ int again;
- /* This looks like a network driver! */
- out_ptr = qpti->res_out_ptr;
- while(out_ptr != in_ptr) {
- sts = (struct Status_Entry *) &qpti->res_cpu[out_ptr];
- out_ptr = NEXT_RES_PTR(out_ptr);
- Cmnd = (Scsi_Cmnd *) (((unsigned long)sts->handle)+PAGE_OFFSET);
-
- if(sts->completion_status == CS_RESET_OCCURRED ||
- sts->completion_status == CS_ABORTED ||
- (sts->status_flags & STF_BUS_RESET))
- qpti->send_marker = 1;
-
- if(sts->state_flags & SF_GOT_SENSE)
- memcpy(Cmnd->sense_buffer, sts->req_sense_data,
- sizeof(Cmnd->sense_buffer));
-
- if(sts->hdr.entry_type == ENTRY_STATUS)
- Cmnd->result = qlogicpti_return_status(sts);
- else
- Cmnd->result = DID_ERROR << 16;
-
- if(Cmnd->use_sg)
- mmu_release_scsi_sgl((struct mmu_sglist *)
- Cmnd->buffer,
- Cmnd->use_sg - 1,
- qpti->qdev->my_bus);
- else
- mmu_release_scsi_one((__u32)((unsigned long)Cmnd->SCp.ptr),
- Cmnd->request_bufflen,
- qpti->qdev->my_bus);
-
- qpti->cmd_count[Cmnd->target]--;
- qregs->mbox5 = out_ptr;
- Cmnd->scsi_done(Cmnd);
- }
- qpti->res_out_ptr = out_ptr;
- }
+ spin_lock_irqsave(&io_request_lock, flags);
+ again = 0;
+ do {
+ for_each_qlogicpti(qpti)
+ again |= qlogicpti_intr_handler(qpti);
+ } while (again);
+ spin_unlock_irqrestore(&io_request_lock, flags);
}
#endif
@@ -1233,7 +1159,7 @@ static void do_qlogicpti_intr_handler(int irq, void *dev_id, struct pt_regs *reg
unsigned long flags;
spin_lock_irqsave(&io_request_lock, flags);
- qlogicpti_intr_handler(irq, dev_id, regs);
+ qlogicpti_intr_handler((struct qlogicpti *)dev_id);
spin_unlock_irqrestore(&io_request_lock, flags);
}