struct ccb ccb[AHA1542_MAILBOXES];
};
-static DEFINE_SPINLOCK(aha1542_lock);
-
static inline void aha1542_intr_reset(u16 base)
{
outb(IRST, CONTROL(base));
return true;
}
-/* This is a bit complicated, but we need to make sure that an interrupt
- routine does not send something out while we are in the middle of this.
- Fortunately, it is only at boot time that multi-byte messages
- are ever sent. */
static int aha1542_outb(unsigned int base, u8 val)
{
- unsigned long flags;
-
while (1) {
if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
return 1;
- spin_lock_irqsave(&aha1542_lock, flags);
- if (inb(STATUS(base)) & CDF) {
- spin_unlock_irqrestore(&aha1542_lock, flags);
+ if (inb(STATUS(base)) & CDF)
continue;
- }
outb(val, DATA(base));
- spin_unlock_irqrestore(&aha1542_lock, flags);
return 0;
}
}
static int aha1542_out(unsigned int base, u8 *buf, int len)
{
- unsigned long flags;
-
- spin_lock_irqsave(&aha1542_lock, flags);
while (len--) {
- if (!wait_mask(STATUS(base), CDF, 0, CDF, 0)) {
- spin_unlock_irqrestore(&aha1542_lock, flags);
+ if (!wait_mask(STATUS(base), CDF, 0, CDF, 0))
return 1;
- }
outb(*buf++, DATA(base));
}
- spin_unlock_irqrestore(&aha1542_lock, flags);
if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0))
return 1;
static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout)
{
- unsigned long flags;
-
- spin_lock_irqsave(&aha1542_lock, flags);
while (len--) {
- if (!wait_mask(STATUS(base), DF, DF, 0, timeout)) {
- spin_unlock_irqrestore(&aha1542_lock, flags);
+ if (!wait_mask(STATUS(base), DF, DF, 0, timeout))
return 1;
- }
*buf++ = inb(DATA(base));
}
- spin_unlock_irqrestore(&aha1542_lock, flags);
return 0;
}
return 1;
}
-/* A "high" level interrupt handler */
-static void aha1542_intr_handle(struct Scsi_Host *sh)
+static irqreturn_t aha1542_interrupt(int irq, void *dev_id)
{
+ struct Scsi_Host *sh = dev_id;
struct aha1542_hostdata *aha1542 = shost_priv(sh);
void (*my_done)(struct scsi_cmnd *) = NULL;
int errstatus, mbi, mbo, mbistatus;
#endif
number_serviced = 0;
- while (1 == 1) {
+ spin_lock_irqsave(sh->host_lock, flags);
+ while (1) {
flag = inb(INTRFLAGS(sh->io_port));
/* Check for unusual interrupts. If any of these happen, we should
}
aha1542_intr_reset(sh->io_port);
- spin_lock_irqsave(&aha1542_lock, flags);
mbi = aha1542->aha1542_last_mbi_used + 1;
if (mbi >= 2 * AHA1542_MAILBOXES)
mbi = AHA1542_MAILBOXES;
} while (mbi != aha1542->aha1542_last_mbi_used);
if (mb[mbi].status == 0) {
- spin_unlock_irqrestore(&aha1542_lock, flags);
+ spin_unlock_irqrestore(sh->host_lock, flags);
/* Hmm, no mail. Must have read it the last time around */
if (!number_serviced)
shost_printk(KERN_WARNING, sh, "interrupt received, but no mail.\n");
- return;
+ return IRQ_HANDLED;
};
mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb);
mbistatus = mb[mbi].status;
mb[mbi].status = 0;
aha1542->aha1542_last_mbi_used = mbi;
- spin_unlock_irqrestore(&aha1542_lock, flags);
#ifdef DEBUG
if (ccb[mbo].tarstat | ccb[mbo].hastat)
tmp_cmd = aha1542->int_cmds[mbo];
if (!tmp_cmd || !tmp_cmd->scsi_done) {
+ spin_unlock_irqrestore(sh->host_lock, flags);
shost_printk(KERN_WARNING, sh, "Unexpected interrupt\n");
shost_printk(KERN_WARNING, sh, "tarstat=%x, hastat=%x idlun=%x ccb#=%d\n", ccb[mbo].tarstat,
ccb[mbo].hastat, ccb[mbo].idlun, mbo);
- return;
+ return IRQ_HANDLED;
}
my_done = tmp_cmd->scsi_done;
kfree(tmp_cmd->host_scribble);
};
}
-/* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */
-static irqreturn_t do_aha1542_intr_handle(int dummy, void *dev_id)
+static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
{
- unsigned long flags;
- struct Scsi_Host *sh = dev_id;
-
- spin_lock_irqsave(sh->host_lock, flags);
- aha1542_intr_handle(sh);
- spin_unlock_irqrestore(sh->host_lock, flags);
- return IRQ_HANDLED;
-}
-
-static int aha1542_queuecommand_lck(struct scsi_cmnd *cmd, void (*done) (struct scsi_cmnd *))
-{
- struct Scsi_Host *sh = cmd->device->host;
struct aha1542_hostdata *aha1542 = shost_priv(sh);
u8 direction;
u8 target = cmd->device->id;
if (*cmd->cmnd == REQUEST_SENSE) {
/* Don't do the command - we have the sense data already */
cmd->result = 0;
- done(cmd);
+ cmd->scsi_done(cmd);
return 0;
}
#ifdef DEBUG
/* Use the outgoing mailboxes in a round-robin fashion, because this
is how the host adapter will scan for them */
- spin_lock_irqsave(&aha1542_lock, flags);
+ spin_lock_irqsave(sh->host_lock, flags);
mbo = aha1542->aha1542_last_mbo_used + 1;
if (mbo >= AHA1542_MAILBOXES)
mbo = 0;
screwing with this cdb. */
aha1542->aha1542_last_mbo_used = mbo;
- spin_unlock_irqrestore(&aha1542_lock, flags);
#ifdef DEBUG
- shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, done);
+ shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done);
#endif
any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
if (cptr == NULL) {
/* free the claimed mailbox slot */
aha1542->int_cmds[mbo] = NULL;
+ spin_unlock_irqrestore(sh->host_lock, flags);
return SCSI_MLQUEUE_HOST_BUSY;
}
scsi_for_each_sg(cmd, sg, sg_count, i) {
#ifdef DEBUG
print_hex_dump_bytes("sending: ", DUMP_PREFIX_NONE, &ccb[mbo], sizeof(ccb[mbo]) - 10);
+ printk("aha1542_queuecommand: now waiting for interrupt ");
#endif
-
- if (done) {
-#ifdef DEBUG
- printk("aha1542_queuecommand: now waiting for interrupt ");
-#endif
- cmd->scsi_done = done;
- mb[mbo].status = 1;
- aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
- } else
- printk("aha1542_queuecommand: done can't be NULL\n");
+ mb[mbo].status = 1;
+ aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
+ spin_unlock_irqrestore(sh->host_lock, flags);
return 0;
}
-static DEF_SCSI_QCMD(aha1542_queuecommand)
-
/* Initialize mailboxes */
static void setup_mailboxes(struct Scsi_Host *sh)
{
setup_mailboxes(sh);
- if (request_irq(sh->irq, do_aha1542_intr_handle, 0,
- "aha1542", sh)) {
+ if (request_irq(sh->irq, aha1542_interrupt, 0, "aha1542", sh)) {
shost_printk(KERN_ERR, sh, "Unable to allocate IRQ.\n");
goto unregister;
}
*/
static int aha1542_dev_reset(struct scsi_cmnd *cmd)
{
- struct aha1542_hostdata *aha1542 = shost_priv(cmd->device->host);
+ struct Scsi_Host *sh = cmd->device->host;
+ struct aha1542_hostdata *aha1542 = shost_priv(sh);
unsigned long flags;
struct mailbox *mb = aha1542->mb;
u8 target = cmd->device->id;
int mbo;
struct ccb *ccb = aha1542->ccb;
- spin_lock_irqsave(&aha1542_lock, flags);
+ spin_lock_irqsave(sh->host_lock, flags);
mbo = aha1542->aha1542_last_mbo_used + 1;
if (mbo >= AHA1542_MAILBOXES)
mbo = 0;
screwing with this cdb. */
aha1542->aha1542_last_mbo_used = mbo;
- spin_unlock_irqrestore(&aha1542_lock, flags);
any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */
* Now tell the 1542 to flush all pending commands for this
* target
*/
- aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI);
+ aha1542_outb(sh->io_port, CMD_START_SCSI);
+ spin_unlock_irqrestore(sh->host_lock, flags);
scmd_printk(KERN_WARNING, cmd,
"Trying device reset for target\n");
static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd)
{
- struct aha1542_hostdata *aha1542 = shost_priv(cmd->device->host);
+ struct Scsi_Host *sh = cmd->device->host;
+ struct aha1542_hostdata *aha1542 = shost_priv(sh);
+ unsigned long flags;
int i;
+ spin_lock_irqsave(sh->host_lock, flags);
/*
* This does a scsi reset for all devices on the bus.
* In principle, we could also reset the 1542 - should
*/
outb(reset_cmd, CONTROL(cmd->device->host->io_port));
- /*
- * Wait for the thing to settle down a bit. Unfortunately
- * this is going to basically lock up the machine while we
- * wait for this to complete. To be 100% correct, we need to
- * check for timeout, and if we are doing something like this
- * we are pretty desperate anyways.
- */
- ssleep(4);
- spin_lock_irq(cmd->device->host->host_lock);
-
if (!wait_mask(STATUS(cmd->device->host->io_port),
STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) {
- spin_unlock_irq(cmd->device->host->host_lock);
+ spin_unlock_irqrestore(sh->host_lock, flags);
return FAILED;
}
+
/*
* We need to do this too before the 1542 can interact with
* us again after host reset.
*/
if (reset_cmd & HRST)
setup_mailboxes(cmd->device->host);
+
/*
* Now try to pick up the pieces. For all pending commands,
* free any internal data structures, and basically clear things
}
}
- spin_unlock_irq(cmd->device->host->host_lock);
+ spin_unlock_irqrestore(sh->host_lock, flags);
return SUCCESS;
}