-/* $Id: esp.c,v 1.101 2002/01/15 06:48:55 davem Exp $
- * esp.c: EnhancedScsiProcessor Sun SCSI driver code.
+/* esp.c: ESP Sun SCSI driver.
*
- * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 1998, 2006 David S. Miller (davem@davemloft.net)
*/
/* TODO:
* 3) Add tagged queueing.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
-#include "scsi.h"
-#include "hosts.h"
#include "esp.h"
#include <asm/sbus.h>
#include <asm/oplib.h>
#include <asm/io.h>
#include <asm/irq.h>
-
#ifndef __sparc_v9__
#include <asm/machines.h>
#include <asm/idprom.h>
#endif
-#include <linux/module.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+#define DRV_VERSION "1.101"
#define DEBUG_ESP
/* #define DEBUG_ESP_HME */
/*5*/ do_intr_end
};
-/* The master ring of all esp hosts we are managing in this driver. */
-static struct esp *espchain;
-static spinlock_t espchain_lock = SPIN_LOCK_UNLOCKED;
-static int esps_running = 0;
-
/* Forward declarations. */
-static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+static irqreturn_t esp_intr(int irq, void *dev_id);
/* Debugging routines */
struct esp_cmdstrings {
}
#ifdef DEBUG_STATE_MACHINE
-static inline void esp_advance_phase(Scsi_Cmnd *s, int newphase)
+static inline void esp_advance_phase(struct scsi_cmnd *s, int newphase)
{
ESPLOG(("<%s>", phase_string(newphase)));
s->SCp.sent_command = s->SCp.phase;
* Note that these are per-ESP queues, not global queues like
* the aha152x driver uses.
*/
-static inline void append_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
+static inline void append_SC(struct scsi_cmnd **SC, struct scsi_cmnd *new_SC)
{
- Scsi_Cmnd *end;
+ struct scsi_cmnd *end;
new_SC->host_scribble = (unsigned char *) NULL;
if (!*SC)
*SC = new_SC;
else {
- for (end=*SC;end->host_scribble;end=(Scsi_Cmnd *)end->host_scribble)
+ for (end=*SC;end->host_scribble;end=(struct scsi_cmnd *)end->host_scribble)
;
end->host_scribble = (unsigned char *) new_SC;
}
}
-static inline void prepend_SC(Scsi_Cmnd **SC, Scsi_Cmnd *new_SC)
+static inline void prepend_SC(struct scsi_cmnd **SC, struct scsi_cmnd *new_SC)
{
new_SC->host_scribble = (unsigned char *) *SC;
*SC = new_SC;
}
-static inline Scsi_Cmnd *remove_first_SC(Scsi_Cmnd **SC)
+static inline struct scsi_cmnd *remove_first_SC(struct scsi_cmnd **SC)
{
- Scsi_Cmnd *ptr;
+ struct scsi_cmnd *ptr;
ptr = *SC;
if (ptr)
- *SC = (Scsi_Cmnd *) (*SC)->host_scribble;
+ *SC = (struct scsi_cmnd *) (*SC)->host_scribble;
return ptr;
}
-static inline Scsi_Cmnd *remove_SC(Scsi_Cmnd **SC, int target, int lun)
+static inline struct scsi_cmnd *remove_SC(struct scsi_cmnd **SC, int target, int lun)
{
- Scsi_Cmnd *ptr, *prev;
+ struct scsi_cmnd *ptr, *prev;
for (ptr = *SC, prev = NULL;
ptr && ((ptr->device->id != target) || (ptr->device->lun != lun));
- prev = ptr, ptr = (Scsi_Cmnd *) ptr->host_scribble)
+ prev = ptr, ptr = (struct scsi_cmnd *) ptr->host_scribble)
;
if (ptr) {
if (prev)
prev->host_scribble=ptr->host_scribble;
else
- *SC=(Scsi_Cmnd *)ptr->host_scribble;
+ *SC=(struct scsi_cmnd *)ptr->host_scribble;
}
return ptr;
}
sbus_readb(esp->eregs + ESP_INTRPT);
}
-static void esp_chain_add(struct esp *esp)
-{
- spin_lock_irq(&espchain_lock);
- if (espchain) {
- struct esp *elink = espchain;
- while (elink->next)
- elink = elink->next;
- elink->next = esp;
- } else {
- espchain = esp;
- }
- esp->next = NULL;
- spin_unlock_irq(&espchain_lock);
-}
-
-static void esp_chain_del(struct esp *esp)
-{
- spin_lock_irq(&espchain_lock);
- if (espchain == esp) {
- espchain = esp->next;
- } else {
- struct esp *elink = espchain;
- while (elink->next != esp)
- elink = elink->next;
- elink->next = esp->next;
- }
- esp->next = NULL;
- spin_unlock_irq(&espchain_lock);
-}
-
static int __init esp_find_dvma(struct esp *esp, struct sbus_dev *dma_sdev)
{
struct sbus_dev *sdev = esp->sdev;
* sanely maintain.
*/
if (request_irq(esp->ehost->irq, esp_intr,
- SA_SHIRQ, "ESP SCSI", esp)) {
+ IRQF_SHARED, "ESP SCSI", esp)) {
printk("esp%d: Cannot acquire irq line\n",
esp->esp_id);
return -1;
}
- printk("esp%d: IRQ %s ", esp->esp_id,
- __irq_itoa(esp->ehost->irq));
+ printk("esp%d: IRQ %d ", esp->esp_id,
+ esp->ehost->irq);
return 0;
}
static void __init esp_get_scsi_id(struct esp *esp)
{
struct sbus_dev *sdev = esp->sdev;
+ struct device_node *dp = sdev->ofdev.node;
- esp->scsi_id = prom_getintdefault(esp->prom_node,
- "initiator-id",
- -1);
+ esp->scsi_id = of_getintprop_default(dp,
+ "initiator-id",
+ -1);
if (esp->scsi_id == -1)
- esp->scsi_id = prom_getintdefault(esp->prom_node,
- "scsi-initiator-id",
- -1);
+ esp->scsi_id = of_getintprop_default(dp,
+ "scsi-initiator-id",
+ -1);
if (esp->scsi_id == -1)
esp->scsi_id = (sdev->bus == NULL) ? 7 :
- prom_getintdefault(sdev->bus->prom_node,
- "scsi-initiator-id",
- 7);
+ of_getintprop_default(sdev->bus->ofdev.node,
+ "scsi-initiator-id",
+ 7);
esp->ehost->this_id = esp->scsi_id;
esp->scsi_id_mask = (1 << esp->scsi_id);
esp->prev_hme_dmacsr = 0xffffffff;
}
-static int __init detect_one_esp(Scsi_Host_Template *tpnt, struct sbus_dev *esp_dev,
- struct sbus_dev *espdma, struct sbus_bus *sbus,
- int id, int hme)
+static int __init detect_one_esp(struct scsi_host_template *tpnt,
+ struct device *dev,
+ struct sbus_dev *esp_dev,
+ struct sbus_dev *espdma,
+ struct sbus_bus *sbus,
+ int hme)
{
- struct Scsi_Host *esp_host = scsi_register(tpnt, sizeof(struct esp));
+ static int instance;
+ struct Scsi_Host *esp_host = scsi_host_alloc(tpnt, sizeof(struct esp));
struct esp *esp;
- if (!esp_host) {
- printk("ESP: Cannot register SCSI host\n");
- return -1;
- }
+ if (!esp_host)
+ return -ENOMEM;
+
if (hme)
esp_host->max_id = 16;
esp = (struct esp *) esp_host->hostdata;
esp->ehost = esp_host;
esp->sdev = esp_dev;
- esp->esp_id = id;
+ esp->esp_id = instance;
esp->prom_node = esp_dev->prom_node;
prom_getstring(esp->prom_node, "name", esp->prom_name,
sizeof(esp->prom_name));
- esp_chain_add(esp);
if (esp_find_dvma(esp, espdma) < 0)
goto fail_unlink;
if (esp_map_regs(esp, hme) < 0) {
esp_bootup_reset(esp);
+ if (scsi_add_host(esp_host, dev))
+ goto fail_free_irq;
+
+ dev_set_drvdata(&esp_dev->ofdev.dev, esp);
+
+ scsi_scan_host(esp_host);
+ instance++;
+
return 0;
+fail_free_irq:
+ free_irq(esp->ehost->irq, esp);
+
fail_unmap_cmdarea:
sbus_free_consistent(esp->sdev, 16,
(void *) esp->esp_command,
esp->dma->allocated = 0;
fail_unlink:
- esp_chain_del(esp);
- scsi_unregister(esp_host);
+ scsi_host_put(esp_host);
return -1;
}
/* Detecting ESP chips on the machine. This is the simple and easy
* version.
*/
+static int __devexit esp_remove_common(struct esp *esp)
+{
+ unsigned int irq = esp->ehost->irq;
+
+ scsi_remove_host(esp->ehost);
+
+ ESP_INTSOFF(esp->dregs);
+#if 0
+ esp_reset_dma(esp);
+ esp_reset_esp(esp);
+#endif
+
+ free_irq(irq, esp);
+ sbus_free_consistent(esp->sdev, 16,
+ (void *) esp->esp_command, esp->esp_command_dvma);
+ sbus_iounmap(esp->eregs, ESP_REG_SIZE);
+ esp->dma->allocated = 0;
+
+ scsi_host_put(esp->ehost);
+
+ return 0;
+}
+
#ifdef CONFIG_SUN4
#include <asm/sun4paddr.h>
-static int __init esp_detect(Scsi_Host_Template *tpnt)
-{
- static struct sbus_dev esp_dev;
- int esps_in_use = 0;
-
- espchain = 0;
+static struct sbus_dev sun4_esp_dev;
+static int __init esp_sun4_probe(struct scsi_host_template *tpnt)
+{
if (sun4_esp_physaddr) {
- memset (&esp_dev, 0, sizeof(esp_dev));
- esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
- esp_dev.irqs[0] = 4;
- esp_dev.resource[0].start = sun4_esp_physaddr;
- esp_dev.resource[0].end = sun4_esp_physaddr + ESP_REG_SIZE - 1;
- esp_dev.resource[0].flags = IORESOURCE_IO;
-
- 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;
+ memset(&sun4_esp_dev, 0, sizeof(sun4_esp_dev));
+ sun4_esp_dev.reg_addrs[0].phys_addr = sun4_esp_physaddr;
+ sun4_esp_dev.irqs[0] = 4;
+ sun4_esp_dev.resource[0].start = sun4_esp_physaddr;
+ sun4_esp_dev.resource[0].end =
+ sun4_esp_physaddr + ESP_REG_SIZE - 1;
+ sun4_esp_dev.resource[0].flags = IORESOURCE_IO;
+
+ return detect_one_esp(tpnt, NULL,
+ &sun4_esp_dev, NULL, NULL, 0);
}
- return esps_in_use;
+ return 0;
}
-#else /* !CONFIG_SUN4 */
-
-static int __init esp_detect(Scsi_Host_Template *tpnt)
+static int __devexit esp_sun4_remove(void)
{
- struct sbus_bus *sbus;
- struct sbus_dev *esp_dev, *sbdev_iter;
- int nesps = 0, esps_in_use = 0;
+ struct of_device *dev = &sun4_esp_dev.ofdev;
+ struct esp *esp = dev_get_drvdata(&dev->dev);
- espchain = 0;
- if (!sbus_root) {
-#ifdef CONFIG_PCI
- return 0;
-#else
- panic("No SBUS in esp_detect()");
-#endif
- }
- for_each_sbus(sbus) {
- for_each_sbusdev(sbdev_iter, sbus) {
- struct sbus_dev *espdma = NULL;
- 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;
+ return esp_remove_common(esp);
}
-#endif /* !CONFIG_SUN4 */
+#else /* !CONFIG_SUN4 */
-/*
- */
-static int esp_release(struct Scsi_Host *host)
+static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match)
{
- struct esp *esp = (struct esp *) host->hostdata;
+ struct sbus_dev *sdev = to_sbus_device(&dev->dev);
+ struct device_node *dp = dev->node;
+ struct sbus_dev *dma_sdev = NULL;
+ int hme = 0;
+
+ if (dp->parent &&
+ (!strcmp(dp->parent->name, "espdma") ||
+ !strcmp(dp->parent->name, "dma")))
+ dma_sdev = sdev->parent;
+ else if (!strcmp(dp->name, "SUNW,fas")) {
+ dma_sdev = sdev;
+ hme = 1;
+ }
- ESP_INTSOFF(esp->dregs);
-#if 0
- esp_reset_dma(esp);
- esp_reset_esp(esp);
-#endif
+ return detect_one_esp(match->data, &dev->dev,
+ sdev, dma_sdev, sdev->bus, hme);
+}
- free_irq(esp->ehost->irq, esp);
- sbus_free_consistent(esp->sdev, 16,
- (void *) esp->esp_command, esp->esp_command_dvma);
- sbus_iounmap(esp->eregs, ESP_REG_SIZE);
- esp->dma->allocated = 0;
- esp_chain_del(esp);
+static int __devexit esp_sbus_remove(struct of_device *dev)
+{
+ struct esp *esp = dev_get_drvdata(&dev->dev);
- return 0;
+ return esp_remove_common(esp);
}
+#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.
static int esp_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
int length, int inout)
{
- struct esp *esp;
+ struct esp *esp = (struct esp *) host->hostdata;
if (inout)
return -EINVAL; /* not yet */
- for_each_esp(esp) {
- if (esp->ehost == host)
- break;
- }
- if (!esp)
- return -EINVAL;
-
if (start)
*start = buffer;
return esp_host_info(esp, buffer, offset, length);
}
-static void esp_get_dmabufs(struct esp *esp, Scsi_Cmnd *sp)
+static void esp_get_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
{
if (sp->use_sg == 0) {
sp->SCp.this_residual = sp->request_bufflen;
if (sp->request_bufflen) {
sp->SCp.have_data_in = sbus_map_single(esp->sdev, sp->SCp.buffer,
sp->SCp.this_residual,
- scsi_to_sbus_dma_dir(sp->sc_data_direction));
+ sp->sc_data_direction);
sp->SCp.ptr = (char *) ((unsigned long)sp->SCp.have_data_in);
} else {
sp->SCp.ptr = NULL;
}
} else {
- sp->SCp.buffer = (struct scatterlist *) sp->buffer;
+ sp->SCp.buffer = (struct scatterlist *) sp->request_buffer;
sp->SCp.buffers_residual = sbus_map_sg(esp->sdev,
sp->SCp.buffer,
sp->use_sg,
- scsi_to_sbus_dma_dir(sp->sc_data_direction));
+ sp->sc_data_direction);
sp->SCp.this_residual = sg_dma_len(sp->SCp.buffer);
sp->SCp.ptr = (char *) ((unsigned long)sg_dma_address(sp->SCp.buffer));
}
}
-static void esp_release_dmabufs(struct esp *esp, Scsi_Cmnd *sp)
+static void esp_release_dmabufs(struct esp *esp, struct scsi_cmnd *sp)
{
if (sp->use_sg) {
- sbus_unmap_sg(esp->sdev, sp->buffer, sp->use_sg,
- scsi_to_sbus_dma_dir(sp->sc_data_direction));
+ sbus_unmap_sg(esp->sdev, sp->request_buffer, sp->use_sg,
+ sp->sc_data_direction);
} else if (sp->request_bufflen) {
sbus_unmap_single(esp->sdev,
sp->SCp.have_data_in,
sp->request_bufflen,
- scsi_to_sbus_dma_dir(sp->sc_data_direction));
+ sp->sc_data_direction);
}
}
-static void esp_restore_pointers(struct esp *esp, Scsi_Cmnd *sp)
+static void esp_restore_pointers(struct esp *esp, struct scsi_cmnd *sp)
{
struct esp_pointers *ep = &esp->data_pointers[sp->device->id];
sp->SCp.buffers_residual = ep->saved_buffers_residual;
}
-static void esp_save_pointers(struct esp *esp, Scsi_Cmnd *sp)
+static void esp_save_pointers(struct esp *esp, struct scsi_cmnd *sp)
{
struct esp_pointers *ep = &esp->data_pointers[sp->device->id];
* case where we could see an interrupt is where we have disconnected
* commands active and they are trying to reselect us.
*/
-static inline void esp_check_cmd(struct esp *esp, Scsi_Cmnd *sp)
+static inline void esp_check_cmd(struct esp *esp, struct scsi_cmnd *sp)
{
switch (sp->cmd_len) {
case 6:
static void esp_exec_cmd(struct esp *esp)
{
- Scsi_Cmnd *SCptr;
- Scsi_Device *SDptr;
+ struct scsi_cmnd *SCptr;
+ struct scsi_device *SDptr;
struct esp_device *esp_dev;
volatile u8 *cmdp = esp->esp_command;
u8 the_esp_command;
}
/* Queue a SCSI command delivered from the mid-level Linux SCSI code. */
-static int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+static int esp_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
{
struct esp *esp;
}
/* Dump driver state. */
-static void esp_dump_cmd(Scsi_Cmnd *SCptr)
+static void esp_dump_cmd(struct scsi_cmnd *SCptr)
{
ESPLOG(("[tgt<%02x> lun<%02x> "
"pphase<%s> cphase<%s>]",
static void esp_dump_state(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
#ifdef DEBUG_ESP_CMDS
int i;
#endif
ESPLOG(("esp%d: disconnected ", esp->esp_id));
while (SCptr) {
esp_dump_cmd(SCptr);
- SCptr = (Scsi_Cmnd *) SCptr->host_scribble;
+ SCptr = (struct scsi_cmnd *) SCptr->host_scribble;
}
ESPLOG(("\n"));
}
/* Abort a command. The host_lock is acquired by caller. */
-static int esp_abort(Scsi_Cmnd *SCptr)
+static int esp_abort(struct scsi_cmnd *SCptr)
{
struct esp *esp = (struct esp *) SCptr->device->host->hostdata;
int don;
ESP_INTSOFF(esp->dregs);
}
if (esp->issue_SC) {
- Scsi_Cmnd **prev, *this;
+ struct scsi_cmnd **prev, *this;
for (prev = (&esp->issue_SC), this = esp->issue_SC;
this != NULL;
- prev = (Scsi_Cmnd **) &(this->host_scribble),
- this = (Scsi_Cmnd *) this->host_scribble) {
+ prev = (struct scsi_cmnd **) &(this->host_scribble),
+ this = (struct scsi_cmnd *) this->host_scribble) {
if (this == SCptr) {
- *prev = (Scsi_Cmnd *) this->host_scribble;
+ *prev = (struct scsi_cmnd *) this->host_scribble;
this->host_scribble = NULL;
esp_release_dmabufs(esp, this);
*/
static int esp_finish_reset(struct esp *esp)
{
- Scsi_Cmnd *sp = esp->current_SC;
+ struct scsi_cmnd *sp = esp->current_SC;
/* Clean up currently executing command, if any. */
if (sp != NULL) {
*
* The host_lock is acquired by caller.
*/
-static int esp_reset(Scsi_Cmnd *SCptr)
+static int esp_reset(struct scsi_cmnd *SCptr)
{
struct esp *esp = (struct esp *) SCptr->device->host->hostdata;
+ spin_lock_irq(esp->ehost->host_lock);
(void) esp_do_resetbus(esp);
-
spin_unlock_irq(esp->ehost->host_lock);
wait_event(esp->reset_queue, (esp->resetting_bus == 0));
- spin_lock_irq(esp->ehost->host_lock);
-
return SUCCESS;
}
/* Internal ESP done function. */
static void esp_done(struct esp *esp, int error)
{
- Scsi_Cmnd *done_SC = esp->current_SC;
+ struct scsi_cmnd *done_SC = esp->current_SC;
esp->current_SC = NULL;
/* 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 esp *esp, Scsi_Cmnd *scp,
+static inline int skipahead1(struct esp *esp, struct scsi_cmnd *scp,
int prev_phase, int new_phase)
{
if (scp->SCp.sent_command != prev_phase)
return do_intr_end;
}
-static inline int skipahead2(struct esp *esp, Scsi_Cmnd *scp,
+static inline int skipahead2(struct esp *esp, struct scsi_cmnd *scp,
int prev_phase1, int prev_phase2, int new_phase)
{
if (scp->SCp.sent_command != prev_phase1 &&
dma_invalidate(esp);
}
-static int dma_can_transfer(struct esp *esp, Scsi_Cmnd *sp)
+static int dma_can_transfer(struct esp *esp, struct scsi_cmnd *sp)
{
__u32 base, end, sz;
* tell the ESP to eat the extraneous byte so that we can proceed
* to the next phase.
*/
-static int esp100_sync_hwbug(struct esp *esp, Scsi_Cmnd *sp, int fifocnt)
+static int esp100_sync_hwbug(struct esp *esp, struct scsi_cmnd *sp, int fifocnt)
{
/* Do not touch this piece of code. */
if ((!(esp->erev == esp100)) ||
/* 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 esp *esp, Scsi_Cmnd *sp)
+static inline void esp_connect(struct esp *esp, struct scsi_cmnd *sp)
{
struct esp_device *esp_dev = sp->device->hostdata;
/* This will place the current working command back into the issue queue
* if we are to receive a reselection amidst a selection attempt.
*/
-static inline void esp_reconnect(struct esp *esp, Scsi_Cmnd *sp)
+static inline void esp_reconnect(struct esp *esp, struct scsi_cmnd *sp)
{
if (!esp->disconnected_SC)
ESPLOG(("esp%d: Weird, being reselected but disconnected "
"command queue is empty.\n", esp->esp_id));
esp->snip = 0;
- esp->current_SC = 0;
+ esp->current_SC = NULL;
sp->SCp.phase = not_issued;
append_SC(&esp->issue_SC, sp);
}
return rval - fifo_count;
}
-static inline void advance_sg(Scsi_Cmnd *sp)
+static inline void advance_sg(struct scsi_cmnd *sp)
{
++sp->SCp.buffer;
--sp->SCp.buffers_residual;
*/
static int esp_do_data(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
int thisphase, hmuch;
ESPDATA(("esp_do_data: "));
/* See how successful the data transfer was. */
static int esp_do_data_finale(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
struct esp_device *esp_dev = SCptr->device->hostdata;
int bogus_data = 0, bytes_sent = 0, fifocnt, ecount = 0;
* a tape, we don't want to go into a loop re-negotiating
* synchronous capabilities over and over.
*/
-static int esp_should_clear_sync(Scsi_Cmnd *sp)
+static int esp_should_clear_sync(struct scsi_cmnd *sp)
{
- u8 cmd1 = sp->cmnd[0];
- u8 cmd2 = sp->data_cmnd[0];
+ u8 cmd = sp->cmnd[0];
/* These cases are for spinning up a disk and
* waiting for that spinup to complete.
*/
- if (cmd1 == START_STOP ||
- cmd2 == START_STOP)
+ if (cmd == START_STOP)
return 0;
- if (cmd1 == TEST_UNIT_READY ||
- cmd2 == TEST_UNIT_READY)
+ if (cmd == TEST_UNIT_READY)
return 0;
/* One more special case for SCSI tape drives,
* completion of a rewind or tape load operation.
*/
if (sp->device->type == TYPE_TAPE) {
- if (cmd1 == MODE_SENSE ||
- cmd2 == MODE_SENSE)
+ if (cmd == MODE_SENSE)
return 0;
}
*/
static int esp_do_freebus(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
struct esp_device *esp_dev = SCptr->device->hostdata;
int rval;
*/
static int esp_bad_reconnect(struct esp *esp)
{
- Scsi_Cmnd *sp;
+ struct scsi_cmnd *sp;
ESPLOG(("esp%d: Eieeee, reconnecting unknown command!\n",
esp->esp_id));
ESPLOG(("esp%d: issue_SC[", esp->esp_id));
while (sp) {
ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
- sp = (Scsi_Cmnd *) sp->host_scribble;
+ sp = (struct scsi_cmnd *) sp->host_scribble;
}
ESPLOG(("]\n"));
sp = esp->current_SC;
ESPLOG(("esp%d: disconnected_SC[", esp->esp_id));
while (sp) {
ESPLOG(("<%02x,%02x>", sp->device->id, sp->device->lun));
- sp = (Scsi_Cmnd *) sp->host_scribble;
+ sp = (struct scsi_cmnd *) sp->host_scribble;
}
ESPLOG(("]\n"));
return do_reset_bus;
static int esp_do_reconnect(struct esp *esp)
{
int lun, target;
- Scsi_Cmnd *SCptr;
+ struct scsi_cmnd *SCptr;
/* Check for all bogus conditions first. */
target = reconnect_target(esp);
*/
static int esp_do_status(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
int intr, rval;
rval = skipahead1(esp, SCptr, in_the_dark, in_status);
static int esp_disconnect_amidst_phases(struct esp *esp)
{
- Scsi_Cmnd *sp = esp->current_SC;
+ struct scsi_cmnd *sp = esp->current_SC;
struct esp_device *esp_dev = sp->device->hostdata;
/* This means real problems if we see this
/* First interrupt after exec'ing a cmd comes here. */
static int esp_select_complete(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
struct esp_device *esp_dev = SCptr->device->hostdata;
int cmd_bytes_sent, fcnt;
* this because so many initiators cannot cope with this occurring.
*/
static int target_with_ants_in_pants(struct esp *esp,
- Scsi_Cmnd *SCptr,
+ struct scsi_cmnd *SCptr,
struct esp_device *esp_dev)
{
if (esp_dev->sync || SCptr->device->borken) {
static int check_multibyte_msg(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
struct esp_device *esp_dev = SCptr->device->hostdata;
u8 regval = 0;
int message_out = 0;
static int esp_do_msgindone(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
int message_out = 0, it = 0, rval;
rval = skipahead1(esp, SCptr, in_msgin, in_msgindone);
static int esp_do_cmdbegin(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
esp_advance_phase(SCptr, in_cmdend);
if (esp->erev == fashme) {
/* This is the second tier in our dual-level SCSI state machine. */
static int esp_work_bus(struct esp *esp)
{
- Scsi_Cmnd *SCptr = esp->current_SC;
+ struct scsi_cmnd *SCptr = esp->current_SC;
unsigned int phase;
ESPBUS(("esp_work_bus: "));
}
static espfunc_t isvc_vector[] = {
- 0,
+ NULL,
esp_do_phase_determine,
esp_do_resetbus,
esp_finish_reset,
/* Main interrupt handler for an esp adapter. */
static void esp_handle(struct esp *esp)
{
- Scsi_Cmnd *SCptr;
+ struct scsi_cmnd *SCptr;
int what_next = do_intr_end;
SCptr = esp->current_SC;
}
/* Service only the ESP described by dev_id. */
-static irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+static irqreturn_t esp_intr(int irq, void *dev_id)
{
struct esp *esp = dev_id;
unsigned long flags;
return IRQ_HANDLED;
}
-static int esp_slave_alloc(Scsi_Device *SDptr)
+static int esp_slave_alloc(struct scsi_device *SDptr)
{
struct esp_device *esp_dev =
kmalloc(sizeof(struct esp_device), GFP_ATOMIC);
return 0;
}
-static void esp_slave_destroy(Scsi_Device *SDptr)
+static void esp_slave_destroy(struct scsi_device *SDptr)
{
struct esp *esp = (struct esp *) SDptr->host->hostdata;
SDptr->hostdata = NULL;
}
-static Scsi_Host_Template driver_template = {
- .proc_name = "esp",
- .proc_info = esp_proc_info,
- .name = "Sun ESP 100/100a/200",
- .detect = esp_detect,
+static struct scsi_host_template esp_template = {
+ .module = THIS_MODULE,
+ .name = "esp",
+ .info = esp_info,
.slave_alloc = esp_slave_alloc,
.slave_destroy = esp_slave_destroy,
- .release = esp_release,
- .info = esp_info,
.queuecommand = esp_queue,
.eh_abort_handler = esp_abort,
.eh_bus_reset_handler = esp_reset,
.sg_tablesize = SG_ALL,
.cmd_per_lun = 1,
.use_clustering = ENABLE_CLUSTERING,
+ .proc_name = "esp",
+ .proc_info = esp_proc_info,
};
-#include "scsi_module.c"
+#ifndef CONFIG_SUN4
+static struct of_device_id esp_match[] = {
+ {
+ .name = "SUNW,esp",
+ .data = &esp_template,
+ },
+ {
+ .name = "SUNW,fas",
+ .data = &esp_template,
+ },
+ {
+ .name = "esp",
+ .data = &esp_template,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, esp_match);
+
+static struct of_platform_driver esp_sbus_driver = {
+ .name = "esp",
+ .match_table = esp_match,
+ .probe = esp_sbus_probe,
+ .remove = __devexit_p(esp_sbus_remove),
+};
+#endif
+
+static int __init esp_init(void)
+{
+#ifdef CONFIG_SUN4
+ return esp_sun4_probe(&esp_template);
+#else
+ return of_register_driver(&esp_sbus_driver, &sbus_bus_type);
+#endif
+}
+
+static void __exit esp_exit(void)
+{
+#ifdef CONFIG_SUN4
+ esp_sun4_remove();
+#else
+ of_unregister_driver(&esp_sbus_driver);
+#endif
+}
+MODULE_DESCRIPTION("ESP Sun SCSI driver");
+MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+module_init(esp_init);
+module_exit(esp_exit);