On Mon, 12 Mar 2018, Michael Schmitz wrote:
> diff --git a/drivers/scsi/zorro_esp.c b/drivers/scsi/zorro_esp.c
> new file mode 100644
> index 0000000..47053d1
> --- /dev/null
> +++ b/drivers/scsi/zorro_esp.c
> @@ -0,0 +1,1136 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* zorro_esp.c: ESP front-end for Amiga ZORRO SCSI systems.
> + *
> + * Copyright (C) 1996 Jesper Skov ([email protected])
> + *
> + * Copyright (C) 2011,2018 Michael Schmitz ([email protected]) for
> + * migration to ESP SCSI core
> + *
> + * Copyright (C) 2013 Tuomas Vainikka ([email protected]) for
> + * Blizzard 1230 DMA and probe function fixes
> + *
> + * Copyright (C) 2017 Finn Thain for PIO code from Mac ESP driver adapted
> here
> + */
> +/*
> + * ZORRO bus code from:
> + */
> +/*
> + * Detection routine for the NCR53c710 based Amiga SCSI Controllers for
> Linux.
> + * Amiga MacroSystemUS WarpEngine SCSI controller.
> + * Amiga Technologies/DKB A4091 SCSI controller.
> + *
> + * Written 1997 by Alan Hourihane <[email protected]>
> + * plus modifications of the 53c7xx.c driver to support the Amiga.
> + *
> + * Rewritten to use 53c700.c by Kars de Jong <[email protected]>
> + */
> +
> +#define KBUILD_MODNAME "zorro_esp"
You don't need to define this. The compiler should be invoked with
-DKBUILD_MODNAME='"zorro_esp"'
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/interrupt.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/scatterlist.h>
> +#include <linux/delay.h>
> +#include <linux/zorro.h>
> +#include <linux/slab.h>
> +
> +#include <asm/page.h>
> +#include <asm/pgtable.h>
> +#include <asm/cacheflush.h>
> +#include <asm/amigahw.h>
> +#include <asm/amigaints.h>
> +
> +#include <scsi/scsi_host.h>
> +#include <scsi/scsi_transport_spi.h>
> +#include <scsi/scsi_device.h>
> +#include <scsi/scsi_tcq.h>
> +
> +#include "esp_scsi.h"
> +
> +MODULE_AUTHOR("Michael Schmitz <[email protected]>");
> +MODULE_DESCRIPTION("Amiga Zorro NCR5C9x (ESP) driver");
> +MODULE_LICENSE("GPL");
> +
> +struct zorro_driver_data {
> + const char *name;
> + unsigned long offset;
> + unsigned long dma_offset;
> + int absolute; /* offset is absolute address */
> + int scsi_option;
> +};
> +
> +static struct zorro_driver_data cyberstormI_data = {
> + .name = "CyberStormI",
> + .offset = 0xf400,
> + .dma_offset = 0xf800,
> + .absolute = 0,
> + .scsi_option = 0,
> +};
> +
> +static struct zorro_driver_data cyberstormII_data = {
> + .name = "CyberStormII",
> + .offset = 0x1ff03,
> + .dma_offset = 0x1ff43,
> + .absolute = 0,
> + .scsi_option = 1,
> +};
> +
> +static struct zorro_driver_data blizzard2060_data = {
> + .name = "Blizzard 2060",
> + .offset = 0x1ff00,
> + .dma_offset = 0x1ffe0,
> + .absolute = 0,
> + .scsi_option = 0,
> +};
> +
> +static struct zorro_driver_data blizzard1230_data = {
> + .name = "Blizzard 1230",
> + .offset = 0x8000,
> + .dma_offset = 0x10000,
> + .absolute = 0,
> + .scsi_option = 1,
> +};
> +
> +static struct zorro_driver_data blizzard1230II_data = {
> + .name = "Blizzard 1230II",
> + .offset = 0x10000,
> + .dma_offset = 0x10021,
> + .absolute = 0,
> + .scsi_option = 1,
> +};
> +
> +static struct zorro_driver_data fastlanez3_data = {
> + .name = "Fastlane",
> + .offset = 0x1000001,
> + .dma_offset = 0x1000041,
> + .absolute = 0,
> + .scsi_option = 0,
> +};
> +
> +static struct zorro_device_id zorro_esp_zorro_tbl[] = {
> + {
> + .id = ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM,
> + .driver_data = (unsigned long)&cyberstormI_data,
> + },
> + {
> + .id = ZORRO_PROD_PHASE5_CYBERSTORM_MK_II,
> + .driver_data = (unsigned long)&cyberstormII_data,
> + },
> + {
> + .id = ZORRO_PROD_PHASE5_BLIZZARD_2060,
> + .driver_data = (unsigned long)&blizzard2060_data,
> + },
> + {
> + .id = ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260,
> + .driver_data = (unsigned long)&blizzard1230_data,
> + },
> + {
> + .id =
> ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060,
> + .driver_data = (unsigned long)&blizzard1230II_data,
> + },
> + { 0 }
> +};
> +MODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl);
> +
> +/* Blizzard 1230 DMA interface */
> +
> +struct blz1230_dma_registers {
> + volatile unsigned char dma_addr; /* DMA address [0x0000] */
> + unsigned char dmapad2[0x7fff];
> + volatile unsigned char dma_latch; /* DMA latch [0x8000] */
> +};
> +
> +/* Blizzard 1230II DMA interface */
> +
> +struct blz1230II_dma_registers {
> + volatile unsigned char dma_addr; /* DMA address [0x0000] */
> + unsigned char dmapad2[0xf];
> + volatile unsigned char dma_latch; /* DMA latch [0x0010] */
> +};
> +
> +/* Blizzard 2060 DMA interface */
> +
> +struct blz2060_dma_registers {
> + volatile unsigned char dma_led_ctrl; /* DMA led control [0x000] */
> + unsigned char dmapad1[0x0f];
> + volatile unsigned char dma_addr0; /* DMA address (MSB) [0x010] */
> + unsigned char dmapad2[0x03];
> + volatile unsigned char dma_addr1; /* DMA address [0x014] */
> + unsigned char dmapad3[0x03];
> + volatile unsigned char dma_addr2; /* DMA address [0x018] */
> + unsigned char dmapad4[0x03];
> + volatile unsigned char dma_addr3; /* DMA address (LSB) [0x01c] */
> +};
> +
> +/* DMA control bits */
> +#define DMA_WRITE 0x80000000
> +
> +/* Cyberstorm DMA interface */
> +
> +struct cyber_dma_registers {
> + volatile unsigned char dma_addr0; /* DMA address (MSB) [0x000] */
> + unsigned char dmapad1[1];
> + volatile unsigned char dma_addr1; /* DMA address [0x002] */
> + unsigned char dmapad2[1];
> + volatile unsigned char dma_addr2; /* DMA address [0x004] */
> + unsigned char dmapad3[1];
> + volatile unsigned char dma_addr3; /* DMA address (LSB) [0x006] */
> + unsigned char dmapad4[0x3fb];
> + volatile unsigned char cond_reg; /* DMA cond (ro) [0x402] */
> +#define ctrl_reg cond_reg /* DMA control (wo) [0x402] */
> +};
> +
> +/* DMA control bits */
> +#define CYBER_DMA_WRITE 0x40 /* DMA direction. 1 = write */
> +#define CYBER_DMA_Z3 0x20 /* 16 (Z2) or 32 (CHIP/Z3) bit DMA
> transfer */
> +
> +/* DMA status bits */
> +#define CYBER_DMA_HNDL_INTR 0x80 /* DMA IRQ pending? */
> +
> +/* The CyberStorm II DMA interface */
> +struct cyberII_dma_registers {
> + volatile unsigned char cond_reg; /* DMA cond (ro) [0x000] */
> +#define ctrl_reg cond_reg /* DMA control (wo) [0x000] */
> + unsigned char dmapad4[0x3f];
> + volatile unsigned char dma_addr0; /* DMA address (MSB) [0x040] */
> + unsigned char dmapad1[3];
> + volatile unsigned char dma_addr1; /* DMA address [0x044] */
> + unsigned char dmapad2[3];
> + volatile unsigned char dma_addr2; /* DMA address [0x048] */
> + unsigned char dmapad3[3];
> + volatile unsigned char dma_addr3; /* DMA address (LSB) [0x04c] */
> +};
> +
> +/* Fastlane DMA interface */
> +
> +struct fastlane_dma_registers {
> + volatile unsigned char cond_reg; /* DMA status (ro) [0x0000] */
> +#define ctrl_reg cond_reg /* DMA control (wo) [0x0000] */
> + unsigned char dmapad1[0x3f];
> + volatile unsigned char clear_strobe; /* DMA clear (wo) [0x0040] */
> +};
> +
> +/* The controller registers can be found in the Z2 config area at these
> + * offsets:
> + */
> +#define FASTLANE_ESP_ADDR 0x1000001
> +
> +/* DMA status bits */
> +#define FASTLANE_DMA_MINT 0x80
> +#define FASTLANE_DMA_IACT 0x40
> +#define FASTLANE_DMA_CREQ 0x20
> +
> +/* DMA control bits */
> +#define FASTLANE_DMA_FCODE 0xa0
> +#define FASTLANE_DMA_MASK 0xf3
> +#define FASTLANE_DMA_WRITE 0x08 /* 1 = write */
> +#define FASTLANE_DMA_ENABLE 0x04 /* Enable DMA */
> +#define FASTLANE_DMA_EDI 0x02 /* Enable DMA IRQ ? */
> +#define FASTLANE_DMA_ESI 0x01 /* Enable SCSI IRQ */
> +
> +/*
> + * private data used for driver
> + */
> +struct zorro_esp_priv {
> + struct esp *esp; /* our ESP instance - for Scsi_host* */
> + unsigned long *board_base; /* virtual address (Zorro III board) */
> + int error; /* PIO error flag */
> + int zorro3; /* board is Zorro III */
> + unsigned char ctrl_data; /* shadow copy of ctrl_reg */
> +};
> +
> +#define ZORRO_ESP_GET_PRIV(esp) ((struct zorro_esp_priv *) \
> + dev_get_drvdata(esp->dev))
> +
> +/*
> + * On all implementations except for the Oktagon, padding between ESP
> + * registers is three bytes.
> + * On Oktagon, it is one byte - use a different accessor there.
> + *
> + * Oktagon needs PDMA - currently unsupported!
> + */
> +
> +static void zorro_esp_write8(struct esp *esp, u8 val, unsigned long reg)
> +{
> + writeb(val, esp->regs + (reg * 4UL));
> +}
> +
> +static u8 zorro_esp_read8(struct esp *esp, unsigned long reg)
> +{
> + return readb(esp->regs + (reg * 4UL));
> +}
> +
> +static dma_addr_t zorro_esp_map_single(struct esp *esp, void *buf,
> + size_t sz, int dir)
> +{
> + return dma_map_single(esp->dev, buf, sz, dir);
> +}
> +
> +static int zorro_esp_map_sg(struct esp *esp, struct scatterlist *sg,
> + int num_sg, int dir)
> +{
> + return dma_map_sg(esp->dev, sg, num_sg, dir);
> +}
> +
> +static void zorro_esp_unmap_single(struct esp *esp, dma_addr_t addr,
> + size_t sz, int dir)
> +{
> + dma_unmap_single(esp->dev, addr, sz, dir);
> +}
> +
> +static void zorro_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
> + int num_sg, int dir)
> +{
> + dma_unmap_sg(esp->dev, sg, num_sg, dir);
> +}
> +
> +static int zorro_esp_irq_pending(struct esp *esp)
> +{
> + /* check ESP status register; DMA has no status reg. */
> +
> + if (zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)
> + return 1;
> +
> + return 0;
> +}
> +
> +static int cyber_esp_irq_pending(struct esp *esp)
> +{
> + /* It's important to check the DMA IRQ bit in the correct way! */
> + return ((zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR) &&
> + ((((struct cyber_dma_registers *)(esp->dma_regs))->cond_reg) &
> + CYBER_DMA_HNDL_INTR));
> + return 0;
> +}
> +
> +static int fastlane_esp_irq_pending(struct esp *esp)
> +{
> + struct fastlane_dma_registers *dregs =
> + (struct fastlane_dma_registers *) (esp->dma_regs);
> + unsigned char dma_status;
> +
> + dma_status = dregs->cond_reg;
> +
> + if (dma_status & FASTLANE_DMA_IACT)
> + return 0; /* not our IRQ */
> +
> + /* Return non-zero if ESP requested IRQ */
> + return (
> + (dma_status & FASTLANE_DMA_CREQ) &&
> + (!(dma_status & FASTLANE_DMA_MINT)) &&
> + (zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR));
> +}
> +
> +static u32 zorro_esp_dma_length_limit(struct esp *esp, u32 dma_addr,
> + u32 dma_len)
> +{
> + return dma_len > 0xFFFFFF ? 0xFFFFFF : dma_len;
> +}
> +
> +static void zorro_esp_reset_dma(struct esp *esp)
> +{
> + /* nothing to do here */
> +}
> +
> +static void zorro_esp_dma_drain(struct esp *esp)
> +{
> + /* nothing to do here */
> +}
> +
> +static void zorro_esp_dma_invalidate(struct esp *esp)
> +{
> + /* nothing to do here */
> +}
> +
> +static void fastlane_esp_dma_invalidate(struct esp *esp)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> + struct fastlane_dma_registers *dregs =
> + (struct fastlane_dma_registers *) (esp->dma_regs);
> + unsigned char *ctrl_data = &zep->ctrl_data;
> + unsigned long *t;
> +
> + *ctrl_data = (*ctrl_data & FASTLANE_DMA_MASK);
> + dregs->ctrl_reg = *ctrl_data;
> +
> + t = (unsigned long *)(zep->board_base);
> +
> + dregs->clear_strobe = 0;
> + *t = 0;
> +}
> +
> +/*
> + * Programmed IO routines follow.
> + */
> +
> +static inline unsigned int zorro_esp_wait_for_fifo(struct esp *esp)
> +{
> + int i = 500000;
> +
> + do {
> + unsigned int fbytes = zorro_esp_read8(esp, ESP_FFLAGS)
> + & ESP_FF_FBYTES;
> +
> + if (fbytes)
> + return fbytes;
> +
> + udelay(2);
> + } while (--i);
> +
> + pr_err("FIFO is empty (sreg %02x)\n",
> + zorro_esp_read8(esp, ESP_STATUS));
> + return 0;
> +}
> +
> +static inline int zorro_esp_wait_for_intr(struct esp *esp)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> + int i = 500000;
> +
> + do {
> + esp->sreg = zorro_esp_read8(esp, ESP_STATUS);
> + if (esp->sreg & ESP_STAT_INTR)
> + return 0;
> +
> + udelay(2);
> + } while (--i);
> +
> + pr_err("IRQ timeout (sreg %02x)\n", esp->sreg);
> + zep->error = 1;
> + return 1;
> +}
> +
> +#define ZORRO_ESP_PIO_LOOP(operands, reg1) \
> + { \
> + asm volatile ( \
> + "1: moveb " operands "\n" \
> + " subqw #1,%1 \n" \
> + " jbne 1b \n" \
> + : "+a" (addr), "+r" (reg1) \
> + : "a" (fifo)); \
> + }
> +
> +#define ZORRO_ESP_PIO_FILL(operands, reg1) \
> + { \
> + asm volatile ( \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " moveb " operands "\n" \
> + " subqw #8,%1 \n" \
> + " subqw #8,%1 \n" \
> + : "+a" (addr), "+r" (reg1) \
> + : "a" (fifo)); \
> + }
> +
> +#define ZORRO_ESP_FIFO_SIZE 16
> +
> +static void zorro_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
> + u32 dma_count, int write, u8 cmd)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> + u8 __iomem *fifo = esp->regs + ESP_FDATA * 16;
> + u8 phase = esp->sreg & ESP_STAT_PMASK;
> +
> + cmd &= ~ESP_CMD_DMA;
> +
> + /* We are passed DMA addresses i.e. physical addresses, but must use
> + * kernel virtual addresses here, so convert to virtual. This is easy
> + * enough for the case of residual bytes of an extended message in
> + * transfer - we know the address must be esp->command_block_dma.
> + * In other cases, more work is needed to find a mapping.
> + * Sidestep the issue by making sure we only end up here when using
> + * esp->command_block as transfer buffer.
> + */
> + if (addr == esp->command_block_dma)
> + addr = (u32) esp->command_block;
Since you've removed the alternative branch and phys_to_virt(), I suggest
you do this at function invocation... (see below)
> +
> + if (write) {
> + u8 *dst = (u8 *)addr;
> + u8 mask = ~(phase == ESP_MIP ? ESP_INTR_FDONE : ESP_INTR_BSERV);
> +
> + scsi_esp_cmd(esp, cmd);
> +
> + while (1) {
> + if (!zorro_esp_wait_for_fifo(esp))
> + break;
> +
> + *dst++ = zorro_esp_read8(esp, ESP_FDATA);
> + --esp_count;
> +
> + if (!esp_count)
> + break;
> +
> + if (zorro_esp_wait_for_intr(esp))
> + break;
> +
> + if ((esp->sreg & ESP_STAT_PMASK) != phase)
> + break;
> +
> + esp->ireg = zorro_esp_read8(esp, ESP_INTRPT);
> + if (esp->ireg & mask) {
> + zep->error = 1;
> + break;
> + }
> +
> + if (phase == ESP_MIP)
> + scsi_esp_cmd(esp, ESP_CMD_MOK);
> +
> + scsi_esp_cmd(esp, ESP_CMD_TI);
> + }
> + } else { /* unused, as long as we only handle MIP here */
> + scsi_esp_cmd(esp, ESP_CMD_FLUSH);
> +
> + if (esp_count >= ZORRO_ESP_FIFO_SIZE) {
> + ZORRO_ESP_PIO_FILL("%0@+,%2@", esp_count);
> + } else
> + ZORRO_ESP_PIO_LOOP("%0@+,%2@", esp_count);
> +
> + scsi_esp_cmd(esp, cmd);
> +
> + while (esp_count) {
> + unsigned int n;
> +
> + if (zorro_esp_wait_for_intr(esp))
> + break;
> +
> + if ((esp->sreg & ESP_STAT_PMASK) != phase)
> + break;
> +
> + esp->ireg = zorro_esp_read8(esp, ESP_INTRPT);
> + if (esp->ireg & ~ESP_INTR_BSERV) {
> + zep->error = 1;
> + break;
> + }
> +
> + n = ZORRO_ESP_FIFO_SIZE -
> + (zorro_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES);
> + if (n > esp_count)
> + n = esp_count;
> +
> + if (n == ZORRO_ESP_FIFO_SIZE) {
> + ZORRO_ESP_PIO_FILL("%0@+,%2@", esp_count);
> + } else {
> + esp_count -= n;
> + ZORRO_ESP_PIO_LOOP("%0@+,%2@", n);
> + }
> +
> + scsi_esp_cmd(esp, ESP_CMD_TI);
> + }
> + }
> +}
> +
> +// Blizzard 1230/60 SCSI-IV DMA
> +
> +static void zorro_esp_send_blz1230_dma_cmd(struct esp *esp, u32 addr,
> + u32 esp_count, u32 dma_count, int write, u8 cmd)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> + struct blz1230_dma_registers *dregs =
> + (struct blz1230_dma_registers *) (esp->dma_regs);
> + u8 phase = esp->sreg & ESP_STAT_PMASK;
> +
> + zep->error = 0;
> + /* Use PIO if transferring message bytes to esp->command_block_dma */
> + if (phase == ESP_MIP && addr == esp->command_block_dma) {
> + zorro_esp_send_pio_cmd(esp, addr, esp_count,
> + dma_count, write, cmd);
> + return;
> + }
... that is,
if (phase == ESP_MIP && addr == esp->command_block_dma) {
/* The virtual address is needed for PIO. Unfortunately we
* don't always know the virtual address, so this
* workaround is not as useful as it could be.
*/
zorro_esp_send_pio_cmd(esp, (u32)esp->command_block,
esp_count, dma_count, write, cmd);
return;
}
> +
> + if (write)
> + /* DMA receive */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_FROM_DEVICE);
> + else
> + /* DMA send */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_TO_DEVICE);
> +
> + addr >>= 1;
> + if (write)
> + addr &= ~(DMA_WRITE);
> + else
> + addr |= DMA_WRITE;
> +
> + dregs->dma_latch = (addr >> 24) & 0xff;
> + dregs->dma_addr = (addr >> 24) & 0xff;
> + dregs->dma_addr = (addr >> 16) & 0xff;
> + dregs->dma_addr = (addr >> 8) & 0xff;
> + dregs->dma_addr = addr & 0xff;
> +
> + scsi_esp_cmd(esp, ESP_CMD_DMA);
> + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
> + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
> + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
> +
> + scsi_esp_cmd(esp, cmd);
> +}
> +
> +// Blizzard 1230-II DMA
> +
> +static void zorro_esp_send_blz1230II_dma_cmd(struct esp *esp, u32 addr,
> + u32 esp_count, u32 dma_count, int write, u8 cmd)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> + struct blz1230II_dma_registers *dregs =
> + (struct blz1230II_dma_registers *) (esp->dma_regs);
> + u8 phase = esp->sreg & ESP_STAT_PMASK;
> +
> + zep->error = 0;
> + /* Use PIO if transferring message bytes to esp->command_block_dma */
> + if (phase == ESP_MIP && addr == esp->command_block_dma) {
> + zorro_esp_send_pio_cmd(esp, addr, esp_count,
> + dma_count, write, cmd);
> + return;
> + }
> +
> + if (write)
> + /* DMA receive */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_FROM_DEVICE);
> + else
> + /* DMA send */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_TO_DEVICE);
> +
> + addr >>= 1;
> + if (write)
> + addr &= ~(DMA_WRITE);
> + else
> + addr |= DMA_WRITE;
> +
> + dregs->dma_latch = (addr >> 24) & 0xff;
> + dregs->dma_addr = (addr >> 16) & 0xff;
> + dregs->dma_addr = (addr >> 8) & 0xff;
> + dregs->dma_addr = addr & 0xff;
> +
> + scsi_esp_cmd(esp, ESP_CMD_DMA);
> + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
> + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
> + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
> +
> + scsi_esp_cmd(esp, cmd);
> +}
> +
> +// Blizzard 2060 DMA
> +
> +static void zorro_esp_send_blz2060_dma_cmd(struct esp *esp, u32 addr,
> + u32 esp_count, u32 dma_count, int write, u8 cmd)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> + struct blz2060_dma_registers *dregs =
> + (struct blz2060_dma_registers *) (esp->dma_regs);
> + u8 phase = esp->sreg & ESP_STAT_PMASK;
> +
> + zep->error = 0;
> + /* Use PIO if transferring message bytes to esp->command_block_dma */
> + if (phase == ESP_MIP && addr == esp->command_block_dma) {
> + zorro_esp_send_pio_cmd(esp, addr, esp_count,
> + dma_count, write, cmd);
> + return;
> + }
> +
> + if (write)
> + /* DMA receive */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_FROM_DEVICE);
> + else
> + /* DMA send */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_TO_DEVICE);
> +
> + addr >>= 1;
> + if (write)
> + addr &= ~(DMA_WRITE);
> + else
> + addr |= DMA_WRITE;
> +
> + dregs->dma_addr3 = addr & 0xff;
> + dregs->dma_addr2 = (addr >> 8) & 0xff;
> + dregs->dma_addr1 = (addr >> 16) & 0xff;
> + dregs->dma_addr0 = (addr >> 24) & 0xff;
> +
> + scsi_esp_cmd(esp, ESP_CMD_DMA);
> + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
> + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
> + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
> +
> + scsi_esp_cmd(esp, cmd);
> +}
> +
> +// Cyberstorm I DMA
> +
> +static void zorro_esp_send_cyber_dma_cmd(struct esp *esp, u32 addr,
> + u32 esp_count, u32 dma_count, int write, u8 cmd)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> + struct cyber_dma_registers *dregs =
> + (struct cyber_dma_registers *) (esp->dma_regs);
> + u8 phase = esp->sreg & ESP_STAT_PMASK;
> + unsigned char *ctrl_data = &zep->ctrl_data;
> +
> + zep->error = 0;
> + /* Use PIO if transferring message bytes to esp->command_block_dma */
> + if (phase == ESP_MIP && addr == esp->command_block_dma) {
> + zorro_esp_send_pio_cmd(esp, addr, esp_count,
> + dma_count, write, cmd);
> + return;
> + }
> +
> + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
> + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
> + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
> +
> + if (write) {
> + /* DMA receive */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_FROM_DEVICE);
> + addr &= ~(1);
> + } else {
> + /* DMA send */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_TO_DEVICE);
> + addr |= 1;
> + }
> +
> + dregs->dma_addr0 = (addr >> 24) & 0xff;
> + dregs->dma_addr1 = (addr >> 16) & 0xff;
> + dregs->dma_addr2 = (addr >> 8) & 0xff;
> + dregs->dma_addr3 = addr & 0xff;
> +
> + if (write)
> + *ctrl_data &= ~(CYBER_DMA_WRITE);
> + else
> + *ctrl_data |= CYBER_DMA_WRITE;
> +
> + *ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */
> +
> + dregs->ctrl_reg = *ctrl_data;
> +
> + scsi_esp_cmd(esp, cmd);
> +}
> +
> +// Cyberstorm II DMA
> +
> +static void zorro_esp_send_cyberII_dma_cmd(struct esp *esp, u32 addr,
> + u32 esp_count, u32 dma_count, int write, u8 cmd)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> + struct cyberII_dma_registers *dregs =
> + (struct cyberII_dma_registers *) (esp->dma_regs);
> + u8 phase = esp->sreg & ESP_STAT_PMASK;
> +
> + zep->error = 0;
> + /* Use PIO if transferring message bytes to esp->command_block_dma */
> + if (phase == ESP_MIP && addr == esp->command_block_dma) {
> + zorro_esp_send_pio_cmd(esp, addr, esp_count,
> + dma_count, write, cmd);
> + return;
> + }
> +
> + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
> + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
> + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
> +
> + if (write) {
> + /* DMA receive */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_FROM_DEVICE);
> + addr &= ~(1);
> + } else {
> + /* DMA send */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_TO_DEVICE);
> + addr |= 1;
> + }
> +
> + dregs->dma_addr0 = (addr >> 24) & 0xff;
> + dregs->dma_addr1 = (addr >> 16) & 0xff;
> + dregs->dma_addr2 = (addr >> 8) & 0xff;
> + dregs->dma_addr3 = addr & 0xff;
> +
> + scsi_esp_cmd(esp, cmd);
> +}
> +
> +// Fastlane DMA
> +
> +static void zorro_esp_send_fastlane_dma_cmd(struct esp *esp, u32 addr,
> + u32 esp_count, u32 dma_count, int write, u8 cmd)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> + struct fastlane_dma_registers *dregs =
> + (struct fastlane_dma_registers *) (esp->dma_regs);
> + u8 phase = esp->sreg & ESP_STAT_PMASK;
> + unsigned char *ctrl_data = &zep->ctrl_data;
> + unsigned long *t;
> +
> + zep->error = 0;
> + /* Use PIO if transferring message bytes to esp->command_block_dma */
> + if (phase == ESP_MIP && addr == esp->command_block_dma) {
> + zorro_esp_send_pio_cmd(esp, addr, esp_count,
> + dma_count, write, cmd);
> + return;
> + }
> +
> + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
> + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
> + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
> +
> + if (write) {
> + /* DMA receive */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_FROM_DEVICE);
> + addr &= ~(1);
> + } else {
> + /* DMA send */
> + dma_sync_single_for_device(esp->dev, addr, esp_count,
> + DMA_TO_DEVICE);
> + addr |= 1;
> + }
> +
> + t = (unsigned long *)((addr & 0x00ffffff) + zep->board_base);
> +
> + dregs->clear_strobe = 0;
> + *t = addr;
> +
> + if (write) {
> + *ctrl_data = (*ctrl_data & FASTLANE_DMA_MASK) |
> + FASTLANE_DMA_ENABLE;
> + } else {
> + *ctrl_data = ((*ctrl_data & FASTLANE_DMA_MASK) |
> + FASTLANE_DMA_ENABLE |
> + FASTLANE_DMA_WRITE);
> + }
> +
> + dregs->ctrl_reg = *ctrl_data;
> +
> + scsi_esp_cmd(esp, cmd);
> +}
> +
> +static int zorro_esp_dma_error(struct esp *esp)
> +{
> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp);
> +
> + /* check for error in case we've been doing PIO */
> + if (zep->error == 1)
> + return 1;
> +
> + /* do nothing - there seems to be no way to check for DMA errors */
> + return 0;
> +}
> +
> +static struct esp_driver_ops zorro_esp_ops = {
> + .esp_write8 = zorro_esp_write8,
> + .esp_read8 = zorro_esp_read8,
> + .map_single = zorro_esp_map_single,
> + .map_sg = zorro_esp_map_sg,
> + .unmap_single = zorro_esp_unmap_single,
> + .unmap_sg = zorro_esp_unmap_sg,
> + .irq_pending = zorro_esp_irq_pending,
> + .dma_length_limit = zorro_esp_dma_length_limit,
> + .reset_dma = zorro_esp_reset_dma,
> + .dma_drain = zorro_esp_dma_drain,
> + .dma_invalidate = zorro_esp_dma_invalidate,
> + .send_dma_cmd = zorro_esp_send_blz2060_dma_cmd,
> + .dma_error = zorro_esp_dma_error,
> +};
> +
> +static int zorro_esp_probe(struct zorro_dev *z,
> + const struct zorro_device_id *ent)
> +{
> + struct scsi_host_template *tpnt = &scsi_esp_template;
> + struct Scsi_Host *host;
> + struct esp *esp;
> + struct zorro_driver_data *zdd;
> + struct zorro_esp_priv *zep;
> + unsigned long board, ioaddr, dmaaddr;
> + int err;
> +
> + board = zorro_resource_start(z);
> + zdd = (struct zorro_driver_data *)ent->driver_data;
> +
> + pr_info("%s found at address 0x%lx.\n", zdd->name, board);
> +
> + zep = kmalloc(sizeof(*zep), GFP_KERNEL);
> + if (!zep) {
> + pr_err("Can't allocate device private data!\n");
> + return -ENOMEM;
> + }
> +
> + /* let's figure out whether we have a Zorro II or Zorro III board */
> + if ((z->rom.er_Type & ERT_TYPEMASK) == ERT_ZORROIII) {
> + /* note this is a Zorro III board */
> + if (board > 0xffffff)
> + zep->zorro3 = 1;
The comment here seems to be redundant (?)
More importantly, I think you have to initialize zep->zorro3 = 0 in the
other branch, or else use kzalloc() instead of kmalloc() above.
> + } else
> + /* Even though most of these boards identify as Zorro II,
> + * they are in fact CPU expansion slot boards and have full
> + * access to all of memory. Fix up DMA bitmask here.
> + */
> + z->dev.coherent_dma_mask = DMA_BIT_MASK(32);
> +
> + /* If Zorro III and ID matches Fastlane, our device table entry
> + * contains data for the Blizzard 1230 II board which does share the
> + * same ID. Fix up device table entry here.
> + * TODO: Some Cyberstom060 boards also share this ID but would need
> + * to use the Cyberstorm I driver data ... we catch this by checking
> + * for presence of ESP chip later, but don't try to fix up yet.
> + */
> + if (zep->zorro3 && ent->id ==
> + ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060)
> {
> + pr_info("%s at address 0x%lx is Fastlane Z3, fixing data!\n",
> + zdd->name, board);
> + zdd = &fastlanez3_data;
> + }
> +
> + if (zdd->absolute) {
> + ioaddr = zdd->offset;
> + dmaaddr = zdd->dma_offset;
> + } else {
> + ioaddr = board + zdd->offset;
> + dmaaddr = board + zdd->dma_offset;
> + }
> +
> + if (!zorro_request_device(z, zdd->name)) {
> + pr_err("cannot reserve region 0x%lx, abort\n",
> + board);
> + err = -EBUSY;
> + goto fail_free_zep;
> + }
> +
> + /* Fill in the required pieces of hostdata */
Redundant comment?
> +
> + host = scsi_host_alloc(tpnt, sizeof(struct esp));
> +
> + if (!host) {
> + pr_err("No host detected; board configuration problem?\n");
> + err = -ENOMEM;
> + goto fail_release_device;
> + }
> +
> + host->base = ioaddr;
> + host->this_id = 7;
> +
> + esp = shost_priv(host);
> + esp->host = host;
> + esp->dev = &z->dev;
> +
> + esp->scsi_id = host->this_id;
> + esp->scsi_id_mask = (1 << esp->scsi_id);
> +
> + esp->cfreq = 40000000;
> +
> + zep->error = 0;
> + zep->esp = esp;
> +
> + dev_set_drvdata(esp->dev, zep);
> +
> + /* Switch to the correct the DMA routine and clock frequency. */
> + switch (ent->id) {
> + case ZORRO_PROD_PHASE5_BLIZZARD_2060:
> + zorro_esp_ops.send_dma_cmd = zorro_esp_send_blz2060_dma_cmd;
> + break;
> + case ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260:
> + zorro_esp_ops.send_dma_cmd = zorro_esp_send_blz1230_dma_cmd;
> + break;
> + case ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM:
> + zorro_esp_ops.send_dma_cmd = zorro_esp_send_cyber_dma_cmd;
> + zorro_esp_ops.irq_pending = cyber_esp_irq_pending;
> + break;
> + case ZORRO_PROD_PHASE5_CYBERSTORM_MK_II:
> + zorro_esp_ops.send_dma_cmd = zorro_esp_send_cyberII_dma_cmd;
> + break;
> + case
> ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060:
> + if (zep->zorro3) {
> + /* Fastlane Zorro III board */
> + /* map address space up to ESP address for DMA */
Same here?
> + zep->board_base = ioremap_nocache(board,
> + FASTLANE_ESP_ADDR-1);
> + if (!zep->board_base) {
> + pr_err("Cannot allocate board address space\n");
> + err = -ENOMEM;
> + goto fail_free_host;
> + }
> + /* initialize DMA control shadow register */
> + zep->ctrl_data = (FASTLANE_DMA_FCODE |
> + FASTLANE_DMA_EDI | FASTLANE_DMA_ESI);
> + zorro_esp_ops.send_dma_cmd =
> + zorro_esp_send_fastlane_dma_cmd;
> + zorro_esp_ops.irq_pending = fastlane_esp_irq_pending;
> + zorro_esp_ops.dma_invalidate =
> + fastlane_esp_dma_invalidate;
> + } else {
> + /* Blizzard 1230 II Zorro II board */
> + zorro_esp_ops.send_dma_cmd =
> + zorro_esp_send_blz1230II_dma_cmd;
> + }
> + break;
> + default:
> + /* Oh noes */
> + pr_err("Unsupported board!\n");
> + err = -ENODEV;
> + goto fail_free_host;
> + }
> +
> + esp->ops = &zorro_esp_ops;
> +
> + if (ioaddr > 0xffffff)
> + esp->regs = ioremap_nocache(ioaddr, 0x20);
> + else
> + esp->regs = (void __iomem *)ZTWO_VADDR(ioaddr);
> +
> + if (!esp->regs) {
> + err = -ENOMEM;
> + goto fail_unmap_fastlane;
> + }
> +
> + /* Check whether a Blizzard 12x0 or CyberstormII really has SCSI */
> + if (zdd->scsi_option) {
> + zorro_esp_write8(esp, (ESP_CONFIG1_PENABLE | 7), ESP_CFG1);
> + if (zorro_esp_read8(esp, ESP_CFG1) != (ESP_CONFIG1_PENABLE|7)) {
> + err = -ENODEV;
> + goto fail_unmap_regs;
> + }
> + }
> +
> + if (zep->zorro3) {
> + /* Only Fastlane Z3 for now - add switch for correct struct
> + * dma_registers size if adding any more
> + */
> + esp->dma_regs = ioremap_nocache(dmaaddr,
> + sizeof(struct fastlane_dma_registers));
> + } else
> + esp->dma_regs = (void __iomem *)ZTWO_VADDR(dmaaddr);
> +
> + if (!esp->dma_regs) {
> + err = -ENOMEM;
> + goto fail_unmap_regs;
> + }
> +
> + esp->command_block = dma_alloc_coherent(esp->dev, 16,
> + &esp->command_block_dma,
> + GFP_KERNEL);
> +
> + if (!esp->command_block) {
> + err = -ENOMEM;
> + goto fail_unmap_dma_regs;
> + }
> +
> + host->irq = IRQ_AMIGA_PORTS;
> + err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED,
> + "Amiga Zorro ESP", esp);
> + if (err < 0) {
> + err = -ENODEV;
> + goto fail_free_command_block;
> + }
> +
> + /* register the chip */
> + err = scsi_esp_register(esp, &z->dev);
> +
> + if (err) {
> + err = -ENOMEM;
> + goto fail_free_irq;
> + }
> +
> + //zorro_set_drvdata(z, host);
> +
Can that be deleted?
> + return 0;
> +
> +fail_free_irq:
> + free_irq(host->irq, esp);
> +
> +fail_free_command_block:
> + dma_free_coherent(esp->dev, 16,
> + esp->command_block,
> + esp->command_block_dma);
> +
> +fail_unmap_dma_regs:
> + if (zep->zorro3)
> + iounmap(esp->dma_regs);
> +
> +fail_unmap_regs:
> + if (ioaddr > 0xffffff)
> + iounmap(esp->regs);
> +
> +fail_unmap_fastlane:
> + if (zep->zorro3)
> + iounmap(zep->board_base);
> +
> +fail_free_host:
> + scsi_host_put(host);
> +
> +fail_release_device:
> + zorro_release_device(z);
> +
> +fail_free_zep:
> + kfree(zep);
> +
> + return err;
> +}
> +
> +static void zorro_esp_remove(struct zorro_dev *z)
> +{
> + /* equivalent to dev_get_drvdata(z->dev) */
If zorro_get_drvdata(z) needs a comment to explain it then why not just
write dev_get_drvdata(z->dev) instead?
That way you can omit the explanation, as the code is consistent with the
dev_set_drvdata(esp->dev, zep) and dev_get_drvdata(esp->dev) used
elsewhere.
> + struct zorro_esp_priv *zep = zorro_get_drvdata(z);
> + struct esp *esp = zep->esp;
> + struct Scsi_Host *host = esp->host;
> +
> + scsi_esp_unregister(esp);
> +
> + /* Disable interrupts. Perhaps use disable_irq instead ... */
> +
Can you clarify? free_irq() calls irq_shutdown()...
> + free_irq(host->irq, esp);
> + dma_free_coherent(esp->dev, 16,
> + esp->command_block,
> + esp->command_block_dma);
> +
> + if (zep->zorro3) {
> + iounmap(zep->board_base);
> + iounmap(esp->dma_regs);
> + }
> +
> + if (host->base > 0xffffff)
> + iounmap(esp->regs);
> +
> + scsi_host_put(host);
> +
> + zorro_release_device(z);
> +
> + kfree(zep);
> +}
> +
> +static struct zorro_driver zorro_esp_driver = {
> + .name = KBUILD_MODNAME,
> + .id_table = zorro_esp_zorro_tbl,
> + .probe = zorro_esp_probe,
> + .remove = zorro_esp_remove,
> +};
> +
> +static int __init zorro_esp_scsi_init(void)
> +{
> + return zorro_register_driver(&zorro_esp_driver);
> +}
> +
> +static void __exit zorro_esp_scsi_exit(void)
> +{
> + zorro_unregister_driver(&zorro_esp_driver);
> +}
> +
> +module_init(zorro_esp_scsi_init);
> +module_exit(zorro_esp_scsi_exit);
>
Thanks!
--