From: tsbogend@alpha.franken.de (Thomas Bogendoerfer)
To: linux-scsi@vger.kernel.org
Cc: James.Bottomley@SteelEye.com, davem@davemloft.net
Subject: [PATCH] jazz_esp converted to use esp_core
Date: Mon, 21 May 2007 23:02:24 +0200 [thread overview]
Message-ID: <20070521210224.GA24573@alpha.franken.de> (raw)
Hi,
after chasing and fixing two jazz platform bugs and one MIPS dma mapping
bug, I finally succeeded in using the Dave's new esp_core (great work,
thank you Dave). Below is the patch.
Thomas.
Use new SCCI_ESP_CORE for JAZZ SCSS host adapter driver
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
---
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index d28c14e..62d62ab 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1532,6 +1532,7 @@ source "drivers/scsi/arm/Kconfig"
config JAZZ_ESP
bool "MIPS JAZZ FAS216 SCSI support"
depends on MACH_JAZZ && SCSI
+ select SCSI_ESP_CORE
help
This is the driver for the onboard SCSI host adapter of MIPS Magnum
4000, Acer PICA, Olivetti M700-10 and a few other identical OEM
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 51e884f..b348600 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -121,7 +121,7 @@ obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o
obj-$(CONFIG_SCSI_PPA) += ppa.o
obj-$(CONFIG_SCSI_IMM) += imm.o
-obj-$(CONFIG_JAZZ_ESP) += NCR53C9x.o jazz_esp.o
+obj-$(CONFIG_JAZZ_ESP) += jazz_esp.o
obj-$(CONFIG_SUN3X_ESP) += NCR53C9x.o sun3x_esp.o
obj-$(CONFIG_SCSI_FCAL) += fcal.o
obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
diff --git a/drivers/scsi/jazz_esp.c b/drivers/scsi/jazz_esp.c
index 19dd4b9..18f7d4e 100644
--- a/drivers/scsi/jazz_esp.c
+++ b/drivers/scsi/jazz_esp.c
@@ -1,307 +1,277 @@
-/*
- * jazz_esp.c: Driver for SCSI chip on Mips Magnum Boards (JAZZ architecture)
+/* jazz_esp.c: ESP front-end for MIPS JAZZ systems.
*
- * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- *
- * jazz_esp is based on David S. Miller's ESP driver and cyber_esp
+ * Copyright (C) 2007 Thomas Bogendörfer (tsbogend@alpha.frankende)
*/
-#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/delay.h>
#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "NCR53C9x.h"
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+
#include <asm/jazz.h>
#include <asm/jazzdma.h>
-#include <asm/dma.h>
-#include <asm/pgtable.h>
-
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
-static int dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_dump_state(struct NCR_ESP *esp);
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
-static void dma_ints_off(struct NCR_ESP *esp);
-static void dma_ints_on(struct NCR_ESP *esp);
-static int dma_irq_p(struct NCR_ESP *esp);
-static int dma_ports_p(struct NCR_ESP *esp);
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
-static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp);
-static void dma_advance_sg (struct scsi_cmnd *sp);
-static void dma_led_off(struct NCR_ESP *);
-static void dma_led_on(struct NCR_ESP *);
-
-
-static volatile unsigned char cmd_buffer[16];
- /* This is where all commands are put
- * before they are trasfered to the ESP chip
- * via PIO.
- */
-
-static int jazz_esp_release(struct Scsi_Host *shost)
-{
- if (shost->irq)
- free_irq(shost->irq, NULL);
- if (shost->dma_channel != 0xff)
- free_dma(shost->dma_channel);
- if (shost->io_port && shost->n_io_port)
- release_region(shost->io_port, shost->n_io_port);
- scsi_unregister(shost);
- return 0;
-}
+#include <scsi/scsi_host.h>
-/***************************************************************** Detection */
-static int jazz_esp_detect(struct scsi_host_template *tpnt)
-{
- struct NCR_ESP *esp;
- struct ConfigDev *esp_dev;
-
- /*
- * first assumption it is there:-)
- */
- if (1) {
- esp_dev = NULL;
- esp = esp_allocate(tpnt, esp_dev, 0);
-
- /* Do command transfer with programmed I/O */
- esp->do_pio_cmds = 1;
-
- /* Required functions */
- esp->dma_bytes_sent = &dma_bytes_sent;
- esp->dma_can_transfer = &dma_can_transfer;
- esp->dma_dump_state = &dma_dump_state;
- esp->dma_init_read = &dma_init_read;
- esp->dma_init_write = &dma_init_write;
- esp->dma_ints_off = &dma_ints_off;
- esp->dma_ints_on = &dma_ints_on;
- esp->dma_irq_p = &dma_irq_p;
- esp->dma_ports_p = &dma_ports_p;
- esp->dma_setup = &dma_setup;
-
- /* Optional functions */
- esp->dma_barrier = NULL;
- esp->dma_drain = NULL;
- esp->dma_invalidate = NULL;
- esp->dma_irq_entry = NULL;
- esp->dma_irq_exit = NULL;
- esp->dma_poll = NULL;
- esp->dma_reset = NULL;
- esp->dma_led_off = &dma_led_off;
- esp->dma_led_on = &dma_led_on;
-
- /* virtual DMA functions */
- esp->dma_mmu_get_scsi_one = &dma_mmu_get_scsi_one;
- esp->dma_mmu_get_scsi_sgl = &dma_mmu_get_scsi_sgl;
- esp->dma_mmu_release_scsi_one = &dma_mmu_release_scsi_one;
- esp->dma_mmu_release_scsi_sgl = &dma_mmu_release_scsi_sgl;
- esp->dma_advance_sg = &dma_advance_sg;
+#include "esp_scsi.h"
+#define DRV_MODULE_NAME "jazz_esp"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_VERSION "1.000"
+#define DRV_MODULE_RELDATE "May 19, 2007"
- /* SCSI chip speed */
- esp->cfreq = 40000000;
+static int __devinit esp_jazz_map_regs(struct esp *esp)
+{
+ struct platform_device *pdev = esp->dev;
+ struct resource *res;
- /*
- * we don't give the address of DMA channel, but the number
- * of DMA channel, so we can use the jazz DMA functions
- *
- */
- esp->dregs = (void *) JAZZ_SCSI_DMA;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
- /* ESP register base */
- esp->eregs = (struct ESP_regs *)(JAZZ_SCSI_BASE);
+ esp->regs = (void __iomem *)res->start;
+ if (!esp->regs)
+ return -ENOMEM;
- /* Set the command buffer */
- esp->esp_command = (volatile unsigned char *)cmd_buffer;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res)
+ return -ENODEV;
- /* get virtual dma address for command buffer */
- esp->esp_command_dvma = vdma_alloc(CPHYSADDR(cmd_buffer), sizeof (cmd_buffer));
-
- esp->irq = JAZZ_SCSI_IRQ;
- request_irq(JAZZ_SCSI_IRQ, esp_intr, IRQF_DISABLED, "JAZZ SCSI",
- esp->ehost);
-
- /*
- * FIXME, look if the scsi id is available from NVRAM
- */
- esp->scsi_id = 7;
-
- /* Check for differential SCSI-bus */
- /* What is this stuff? */
- esp->diff = 0;
+ esp->dma_regs = (void __iomem *)res->start;
- esp_initialize(esp);
-
- 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 0;
+ return 0;
}
-/************************************************************* DMA Functions */
-static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+static int __devinit esp_jazz_map_command_block(struct esp *esp)
{
- return fifo_count;
+ esp->command_block = dma_alloc_coherent(esp->dev, 16,
+ &esp->command_block_dma,
+ GFP_KERNEL);
+ if (!esp->command_block)
+ return -ENOMEM;
+ return 0;
}
-static int dma_can_transfer(struct NCR_ESP *esp, struct scsi_cmnd *sp)
+static int __devinit esp_jazz_register_irq(struct esp *esp)
{
- /*
- * maximum DMA size is 1MB
- */
- unsigned long sz = sp->SCp.this_residual;
- if(sz > 0x100000)
- sz = 0x100000;
- return sz;
+ struct Scsi_Host *host = esp->host;
+ struct platform_device *pdev = esp->dev;
+
+ host->irq = platform_get_irq(pdev, 0);
+ return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp);
}
-static void dma_dump_state(struct NCR_ESP *esp)
+static void __devinit esp_jazz_get_props(struct esp *esp)
{
-
- ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n",
- esp->esp_id, vdma_get_enable((int)esp->dregs), vdma_get_residue((int)esp->dregs)));
+ esp->scsi_id = 7;
+ esp->host->this_id = esp->scsi_id;
+ esp->scsi_id_mask = (1 << esp->scsi_id);
+ esp->cfreq = 40000000;
}
-static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+static void jazz_esp_write8(struct esp *esp, u8 val, unsigned long reg)
{
- dma_cache_wback_inv ((unsigned long)phys_to_virt(vdma_log2phys(vaddress)), length);
- vdma_disable ((int)esp->dregs);
- vdma_set_mode ((int)esp->dregs, DMA_MODE_READ);
- vdma_set_addr ((int)esp->dregs, vaddress);
- vdma_set_count ((int)esp->dregs, length);
- vdma_enable ((int)esp->dregs);
+ *(volatile u8 *)(esp->regs + reg) = val;
}
-static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+static u8 jazz_esp_read8(struct esp *esp, unsigned long reg)
{
- dma_cache_wback_inv ((unsigned long)phys_to_virt(vdma_log2phys(vaddress)), length);
- vdma_disable ((int)esp->dregs);
- vdma_set_mode ((int)esp->dregs, DMA_MODE_WRITE);
- vdma_set_addr ((int)esp->dregs, vaddress);
- vdma_set_count ((int)esp->dregs, length);
- vdma_enable ((int)esp->dregs);
+ return *(volatile u8 *)(esp->regs + reg);
}
-static void dma_ints_off(struct NCR_ESP *esp)
+static dma_addr_t jazz_esp_map_single(struct esp *esp, void *buf,
+ size_t sz, int dir)
{
- disable_irq(esp->irq);
+ return dma_map_single(esp->dev, buf, sz, dir);
}
-static void dma_ints_on(struct NCR_ESP *esp)
+static int jazz_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
{
- enable_irq(esp->irq);
+ return dma_map_sg(esp->dev, sg, num_sg, dir);
}
-static int dma_irq_p(struct NCR_ESP *esp)
+static void jazz_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+ size_t sz, int dir)
{
- return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
+ dma_unmap_single(esp->dev, addr, sz, dir);
}
-static int dma_ports_p(struct NCR_ESP *esp)
+static void jazz_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
{
- int enable = vdma_get_enable((int)esp->dregs);
-
- return (enable & R4030_CHNL_ENABLE);
+ dma_unmap_sg(esp->dev, sg, num_sg, dir);
}
-static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+static int jazz_esp_irq_pending(struct esp *esp)
{
- /*
- * On the Sparc, DMA_ST_WRITE means "move data from device to memory"
- * so when (write) is true, it actually means READ!
- */
- if(write){
- dma_init_read(esp, addr, count);
- } else {
- dma_init_write(esp, addr, count);
- }
+ if (jazz_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)
+ return 1;
+ return 0;
}
-static void dma_mmu_get_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
+static void jazz_esp_reset_dma(struct esp *esp)
{
- sp->SCp.have_data_in = vdma_alloc(CPHYSADDR(sp->SCp.buffer), sp->SCp.this_residual);
- sp->SCp.ptr = (char *)((unsigned long)sp->SCp.have_data_in);
+ vdma_disable ((int)esp->dma_regs);
}
-static void dma_mmu_get_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp)
+static void jazz_esp_dma_drain(struct esp *esp)
{
- int sz = sp->SCp.buffers_residual;
- struct scatterlist *sg = (struct scatterlist *) sp->SCp.buffer;
-
- while (sz >= 0) {
- sg[sz].dma_address = vdma_alloc(CPHYSADDR(page_address(sg[sz].page) + sg[sz].offset), sg[sz].length);
- sz--;
- }
- sp->SCp.ptr=(char *)(sp->SCp.buffer->dma_address);
-}
-
-static void dma_mmu_release_scsi_one (struct NCR_ESP *esp, struct scsi_cmnd *sp)
+ /* nothing to do */
+}
+
+static void jazz_esp_dma_invalidate(struct esp *esp)
{
- vdma_free(sp->SCp.have_data_in);
+ vdma_disable ((int)esp->dma_regs);
}
-static void dma_mmu_release_scsi_sgl (struct NCR_ESP *esp, struct scsi_cmnd *sp)
+static void jazz_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+ u32 dma_count, int write, u8 cmd)
{
- int sz = sp->use_sg - 1;
- struct scatterlist *sg = (struct scatterlist *)sp->request_buffer;
-
- while(sz >= 0) {
- vdma_free(sg[sz].dma_address);
- sz--;
- }
+ BUG_ON(!(cmd & ESP_CMD_DMA));
+
+ jazz_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ jazz_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ vdma_disable ((int)esp->dma_regs);
+ if (write)
+ vdma_set_mode ((int)esp->dma_regs, DMA_MODE_READ);
+ else
+ vdma_set_mode ((int)esp->dma_regs, DMA_MODE_WRITE);
+
+ vdma_set_addr ((int)esp->dma_regs, addr);
+ vdma_set_count ((int)esp->dma_regs, dma_count);
+ vdma_enable ((int)esp->dma_regs);
+
+ scsi_esp_cmd(esp, cmd);
}
-static void dma_advance_sg (struct scsi_cmnd *sp)
+static int jazz_esp_dma_error(struct esp *esp)
{
- sp->SCp.ptr = (char *)(sp->SCp.buffer->dma_address);
+ u32 enable = vdma_get_enable((int)esp->dma_regs);
+
+ if (enable & (R4030_MEM_INTR|R4030_ADDR_INTR))
+ return 1;
+
+ return 0;
}
-#define JAZZ_HDC_LED 0xe000d100 /* FIXME, find correct address */
+static const struct esp_driver_ops jazz_esp_ops = {
+ .esp_write8 = jazz_esp_write8,
+ .esp_read8 = jazz_esp_read8,
+ .map_single = jazz_esp_map_single,
+ .map_sg = jazz_esp_map_sg,
+ .unmap_single = jazz_esp_unmap_single,
+ .unmap_sg = jazz_esp_unmap_sg,
+ .irq_pending = jazz_esp_irq_pending,
+ .reset_dma = jazz_esp_reset_dma,
+ .dma_drain = jazz_esp_dma_drain,
+ .dma_invalidate = jazz_esp_dma_invalidate,
+ .send_dma_cmd = jazz_esp_send_dma_cmd,
+ .dma_error = jazz_esp_dma_error,
+};
-static void dma_led_off(struct NCR_ESP *esp)
+static int __devinit esp_jazz_probe(struct platform_device *dev)
{
-#if 0
- *(unsigned char *)JAZZ_HDC_LED = 0;
-#endif
+ struct scsi_host_template *tpnt = &scsi_esp_template;
+ struct Scsi_Host *host;
+ struct esp *esp;
+ int err;
+
+ host = scsi_host_alloc(tpnt, sizeof(struct esp));
+
+ err = -ENOMEM;
+ if (!host)
+ goto fail;
+
+ host->max_id = 8;
+ esp = host_to_esp(host);
+
+ esp->host = host;
+ esp->dev = dev;
+ esp->ops = &jazz_esp_ops;
+
+ err = esp_jazz_map_regs(esp);
+ if (err < 0)
+ goto fail_unlink;
+
+ err = esp_jazz_map_command_block(esp);
+ if (err < 0)
+ goto fail_unmap_regs;
+
+ err = esp_jazz_register_irq(esp);
+ if (err < 0)
+ goto fail_unmap_command_block;
+
+ esp_jazz_get_props(esp);
+
+ dev_set_drvdata(&dev->dev, esp);
+
+ err = scsi_esp_register(esp, &dev->dev);
+ if (err)
+ goto fail_free_irq;
+
+ return 0;
+
+fail_free_irq:
+ free_irq(host->irq, esp);
+fail_unmap_command_block:
+ dma_free_coherent(esp->dev, 16,
+ esp->command_block,
+ esp->command_block_dma);
+fail_unmap_regs:
+fail_unlink:
+ scsi_host_put(host);
+fail:
+ return err;
}
-static void dma_led_on(struct NCR_ESP *esp)
-{
-#if 0
- *(unsigned char *)JAZZ_HDC_LED = 1;
-#endif
+static int __devexit esp_jazz_remove(struct platform_device *dev)
+{
+ struct esp *esp = dev_get_drvdata(&dev->dev);
+ unsigned int irq = esp->host->irq;
+ u32 val;
+
+ scsi_esp_unregister(esp);
+
+ free_irq(irq, esp);
+ dma_free_coherent(esp->dev, 16,
+ esp->command_block,
+ esp->command_block_dma);
+
+ scsi_host_put(esp->host);
+
+ return 0;
}
-static struct scsi_host_template driver_template = {
- .proc_name = "jazz_esp",
- .proc_info = esp_proc_info,
- .name = "ESP 100/100a/200",
- .detect = jazz_esp_detect,
- .slave_alloc = esp_slave_alloc,
- .slave_destroy = esp_slave_destroy,
- .release = jazz_esp_release,
- .info = esp_info,
- .queuecommand = esp_queue,
- .eh_abort_handler = esp_abort,
- .eh_bus_reset_handler = esp_reset,
- .can_queue = 7,
- .this_id = 7,
- .sg_tablesize = SG_ALL,
- .cmd_per_lun = 1,
- .use_clustering = DISABLE_CLUSTERING,
+static struct platform_driver esp_jazz_driver = {
+ .probe = esp_jazz_probe,
+ .remove = __devexit_p(esp_jazz_remove),
+ .driver = {
+ .name = "jazz_esp",
+ },
};
-#include "scsi_module.c"
+
+static int __init jazz_esp_init(void)
+{
+ return platform_driver_register(&esp_jazz_driver);
+}
+
+static void __exit jazz_esp_exit(void)
+{
+ platform_driver_unregister(&esp_jazz_driver);
+}
+
+MODULE_DESCRIPTION("JAZZ ESP SCSI driver");
+MODULE_AUTHOR("Thomas Bogendoerfer (tsbogend@alpha.franken.de)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+module_init(jazz_esp_init);
+module_exit(jazz_esp_exit);
--
Crap can work. Given enough thrust pigs will fly, but it's not necessary a
good idea. [ RFC1925, 2.3 ]
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next reply other threads:[~2007-05-21 22:25 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-21 21:02 Thomas Bogendoerfer [this message]
2007-05-21 23:00 ` [PATCH] jazz_esp converted to use esp_core Christoph Hellwig
2007-05-21 23:14 ` Jeff Garzik
2007-05-21 23:41 ` David Miller
2007-05-21 23:45 ` Jeff Garzik
2007-05-21 23:54 ` David Miller
2007-05-22 8:04 ` Thomas Bogendoerfer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070521210224.GA24573@alpha.franken.de \
--to=tsbogend@alpha.franken.de \
--cc=James.Bottomley@SteelEye.com \
--cc=davem@davemloft.net \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.