| // SPDX-License-Identifier: GPL-2.0 | |
| /* | |
| * ESP front-end for Amiga ZORRO SCSI systems. | |
| * | |
| * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) | |
| * | |
| * Copyright (C) 2011,2018 Michael Schmitz (schmitz@debian.org) for | |
| * migration to ESP SCSI core | |
| * | |
| * Copyright (C) 2013 Tuomas Vainikka (tuomas.vainikka@aalto.fi) for | |
| * Blizzard 1230 DMA and probe function fixes | |
| */ | |
| /* | |
| * 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 <alanh@fairlite.demon.co.uk> | |
| * plus modifications of the 53c7xx.c driver to support the Amiga. | |
| * | |
| * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org> | |
| */ | |
| #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 <linux/pgtable.h> | |
| #include <asm/page.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 <schmitz@debian.org>"); | |
| MODULE_DESCRIPTION("Amiga Zorro NCR5C9x (ESP) driver"); | |
| MODULE_LICENSE("GPL"); | |
| /* per-board register layout definitions */ | |
| /* Blizzard 1230 DMA interface */ | |
| struct blz1230_dma_registers { | |
| unsigned char dma_addr; /* DMA address [0x0000] */ | |
| unsigned char dmapad2[0x7fff]; | |
| unsigned char dma_latch; /* DMA latch [0x8000] */ | |
| }; | |
| /* Blizzard 1230II DMA interface */ | |
| struct blz1230II_dma_registers { | |
| unsigned char dma_addr; /* DMA address [0x0000] */ | |
| unsigned char dmapad2[0xf]; | |
| unsigned char dma_latch; /* DMA latch [0x0010] */ | |
| }; | |
| /* Blizzard 2060 DMA interface */ | |
| struct blz2060_dma_registers { | |
| unsigned char dma_led_ctrl; /* DMA led control [0x000] */ | |
| unsigned char dmapad1[0x0f]; | |
| unsigned char dma_addr0; /* DMA address (MSB) [0x010] */ | |
| unsigned char dmapad2[0x03]; | |
| unsigned char dma_addr1; /* DMA address [0x014] */ | |
| unsigned char dmapad3[0x03]; | |
| unsigned char dma_addr2; /* DMA address [0x018] */ | |
| unsigned char dmapad4[0x03]; | |
| unsigned char dma_addr3; /* DMA address (LSB) [0x01c] */ | |
| }; | |
| /* DMA control bits */ | |
| #define DMA_WRITE 0x80000000 | |
| /* Cyberstorm DMA interface */ | |
| struct cyber_dma_registers { | |
| unsigned char dma_addr0; /* DMA address (MSB) [0x000] */ | |
| unsigned char dmapad1[1]; | |
| unsigned char dma_addr1; /* DMA address [0x002] */ | |
| unsigned char dmapad2[1]; | |
| unsigned char dma_addr2; /* DMA address [0x004] */ | |
| unsigned char dmapad3[1]; | |
| unsigned char dma_addr3; /* DMA address (LSB) [0x006] */ | |
| unsigned char dmapad4[0x3fb]; | |
| 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 { | |
| unsigned char cond_reg; /* DMA cond (ro) [0x000] */ | |
| #define ctrl_reg cond_reg /* DMA control (wo) [0x000] */ | |
| unsigned char dmapad4[0x3f]; | |
| unsigned char dma_addr0; /* DMA address (MSB) [0x040] */ | |
| unsigned char dmapad1[3]; | |
| unsigned char dma_addr1; /* DMA address [0x044] */ | |
| unsigned char dmapad2[3]; | |
| unsigned char dma_addr2; /* DMA address [0x048] */ | |
| unsigned char dmapad3[3]; | |
| unsigned char dma_addr3; /* DMA address (LSB) [0x04c] */ | |
| }; | |
| /* Fastlane DMA interface */ | |
| struct fastlane_dma_registers { | |
| unsigned char cond_reg; /* DMA status (ro) [0x0000] */ | |
| #define ctrl_reg cond_reg /* DMA control (wo) [0x0000] */ | |
| char dmapad1[0x3f]; | |
| 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* */ | |
| void __iomem *board_base; /* virtual address (Zorro III board) */ | |
| int zorro3; /* board is Zorro III */ | |
| unsigned char ctrl_data; /* shadow copy of ctrl_reg */ | |
| }; | |
| /* | |
| * 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 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) | |
| { | |
| struct cyber_dma_registers __iomem *dregs = esp->dma_regs; | |
| unsigned char dma_status = readb(&dregs->cond_reg); | |
| /* It's important to check the DMA IRQ bit in the correct way! */ | |
| return ((zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR) && | |
| (dma_status & CYBER_DMA_HNDL_INTR)); | |
| } | |
| static int fastlane_esp_irq_pending(struct esp *esp) | |
| { | |
| struct fastlane_dma_registers __iomem *dregs = esp->dma_regs; | |
| unsigned char dma_status; | |
| dma_status = readb(&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 > (1U << 16) ? (1U << 16) : dma_len; | |
| } | |
| static u32 fastlane_esp_dma_length_limit(struct esp *esp, u32 dma_addr, | |
| u32 dma_len) | |
| { | |
| /* The old driver used 0xfffc as limit, so do that here too */ | |
| return dma_len > 0xfffc ? 0xfffc : 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 = dev_get_drvdata(esp->dev); | |
| struct fastlane_dma_registers __iomem *dregs = esp->dma_regs; | |
| unsigned char *ctrl_data = &zep->ctrl_data; | |
| *ctrl_data = (*ctrl_data & FASTLANE_DMA_MASK); | |
| writeb(0, &dregs->clear_strobe); | |
| z_writel(0, zep->board_base); | |
| } | |
| /* 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 blz1230_dma_registers __iomem *dregs = esp->dma_regs; | |
| u8 phase = esp->sreg & ESP_STAT_PMASK; | |
| /* | |
| * Use PIO if transferring message bytes to esp->command_block_dma. | |
| * PIO requires a virtual address, so substitute esp->command_block | |
| * for addr. | |
| */ | |
| if (phase == ESP_MIP && addr == esp->command_block_dma) { | |
| esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, | |
| dma_count, write, cmd); | |
| return; | |
| } | |
| /* Clear the results of a possible prior esp->ops->send_dma_cmd() */ | |
| esp->send_cmd_error = 0; | |
| esp->send_cmd_residual = 0; | |
| 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; | |
| writeb((addr >> 24) & 0xff, &dregs->dma_latch); | |
| writeb((addr >> 24) & 0xff, &dregs->dma_addr); | |
| writeb((addr >> 16) & 0xff, &dregs->dma_addr); | |
| writeb((addr >> 8) & 0xff, &dregs->dma_addr); | |
| writeb(addr & 0xff, &dregs->dma_addr); | |
| 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); | |
| 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 blz1230II_dma_registers __iomem *dregs = esp->dma_regs; | |
| u8 phase = esp->sreg & ESP_STAT_PMASK; | |
| /* Use PIO if transferring message bytes to esp->command_block_dma */ | |
| if (phase == ESP_MIP && addr == esp->command_block_dma) { | |
| esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, | |
| dma_count, write, cmd); | |
| return; | |
| } | |
| esp->send_cmd_error = 0; | |
| esp->send_cmd_residual = 0; | |
| 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; | |
| writeb((addr >> 24) & 0xff, &dregs->dma_latch); | |
| writeb((addr >> 16) & 0xff, &dregs->dma_addr); | |
| writeb((addr >> 8) & 0xff, &dregs->dma_addr); | |
| writeb(addr & 0xff, &dregs->dma_addr); | |
| 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); | |
| 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 blz2060_dma_registers __iomem *dregs = esp->dma_regs; | |
| u8 phase = esp->sreg & ESP_STAT_PMASK; | |
| /* Use PIO if transferring message bytes to esp->command_block_dma */ | |
| if (phase == ESP_MIP && addr == esp->command_block_dma) { | |
| esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, | |
| dma_count, write, cmd); | |
| return; | |
| } | |
| esp->send_cmd_error = 0; | |
| esp->send_cmd_residual = 0; | |
| 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; | |
| writeb(addr & 0xff, &dregs->dma_addr3); | |
| writeb((addr >> 8) & 0xff, &dregs->dma_addr2); | |
| writeb((addr >> 16) & 0xff, &dregs->dma_addr1); | |
| writeb((addr >> 24) & 0xff, &dregs->dma_addr0); | |
| 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); | |
| 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 = dev_get_drvdata(esp->dev); | |
| struct cyber_dma_registers __iomem *dregs = esp->dma_regs; | |
| u8 phase = esp->sreg & ESP_STAT_PMASK; | |
| unsigned char *ctrl_data = &zep->ctrl_data; | |
| /* Use PIO if transferring message bytes to esp->command_block_dma */ | |
| if (phase == ESP_MIP && addr == esp->command_block_dma) { | |
| esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, | |
| dma_count, write, cmd); | |
| return; | |
| } | |
| esp->send_cmd_error = 0; | |
| esp->send_cmd_residual = 0; | |
| zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); | |
| zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); | |
| 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; | |
| } | |
| writeb((addr >> 24) & 0xff, &dregs->dma_addr0); | |
| writeb((addr >> 16) & 0xff, &dregs->dma_addr1); | |
| writeb((addr >> 8) & 0xff, &dregs->dma_addr2); | |
| writeb(addr & 0xff, &dregs->dma_addr3); | |
| if (write) | |
| *ctrl_data &= ~(CYBER_DMA_WRITE); | |
| else | |
| *ctrl_data |= CYBER_DMA_WRITE; | |
| *ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */ | |
| writeb(*ctrl_data, &dregs->ctrl_reg); | |
| 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 cyberII_dma_registers __iomem *dregs = esp->dma_regs; | |
| u8 phase = esp->sreg & ESP_STAT_PMASK; | |
| /* Use PIO if transferring message bytes to esp->command_block_dma */ | |
| if (phase == ESP_MIP && addr == esp->command_block_dma) { | |
| esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, | |
| dma_count, write, cmd); | |
| return; | |
| } | |
| esp->send_cmd_error = 0; | |
| esp->send_cmd_residual = 0; | |
| zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); | |
| zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); | |
| 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; | |
| } | |
| writeb((addr >> 24) & 0xff, &dregs->dma_addr0); | |
| writeb((addr >> 16) & 0xff, &dregs->dma_addr1); | |
| writeb((addr >> 8) & 0xff, &dregs->dma_addr2); | |
| writeb(addr & 0xff, &dregs->dma_addr3); | |
| 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 = dev_get_drvdata(esp->dev); | |
| struct fastlane_dma_registers __iomem *dregs = esp->dma_regs; | |
| u8 phase = esp->sreg & ESP_STAT_PMASK; | |
| unsigned char *ctrl_data = &zep->ctrl_data; | |
| /* Use PIO if transferring message bytes to esp->command_block_dma */ | |
| if (phase == ESP_MIP && addr == esp->command_block_dma) { | |
| esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, | |
| dma_count, write, cmd); | |
| return; | |
| } | |
| esp->send_cmd_error = 0; | |
| esp->send_cmd_residual = 0; | |
| zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); | |
| zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); | |
| 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; | |
| } | |
| writeb(0, &dregs->clear_strobe); | |
| z_writel(addr, ((addr & 0x00ffffff) + zep->board_base)); | |
| 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); | |
| } | |
| writeb(*ctrl_data, &dregs->ctrl_reg); | |
| scsi_esp_cmd(esp, cmd); | |
| } | |
| static int zorro_esp_dma_error(struct esp *esp) | |
| { | |
| return esp->send_cmd_error; | |
| } | |
| /* per-board ESP driver ops */ | |
| static const struct esp_driver_ops blz1230_esp_ops = { | |
| .esp_write8 = zorro_esp_write8, | |
| .esp_read8 = zorro_esp_read8, | |
| .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_blz1230_dma_cmd, | |
| .dma_error = zorro_esp_dma_error, | |
| }; | |
| static const struct esp_driver_ops blz1230II_esp_ops = { | |
| .esp_write8 = zorro_esp_write8, | |
| .esp_read8 = zorro_esp_read8, | |
| .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_blz1230II_dma_cmd, | |
| .dma_error = zorro_esp_dma_error, | |
| }; | |
| static const struct esp_driver_ops blz2060_esp_ops = { | |
| .esp_write8 = zorro_esp_write8, | |
| .esp_read8 = zorro_esp_read8, | |
| .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 const struct esp_driver_ops cyber_esp_ops = { | |
| .esp_write8 = zorro_esp_write8, | |
| .esp_read8 = zorro_esp_read8, | |
| .irq_pending = cyber_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_cyber_dma_cmd, | |
| .dma_error = zorro_esp_dma_error, | |
| }; | |
| static const struct esp_driver_ops cyberII_esp_ops = { | |
| .esp_write8 = zorro_esp_write8, | |
| .esp_read8 = zorro_esp_read8, | |
| .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_cyberII_dma_cmd, | |
| .dma_error = zorro_esp_dma_error, | |
| }; | |
| static const struct esp_driver_ops fastlane_esp_ops = { | |
| .esp_write8 = zorro_esp_write8, | |
| .esp_read8 = zorro_esp_read8, | |
| .irq_pending = fastlane_esp_irq_pending, | |
| .dma_length_limit = fastlane_esp_dma_length_limit, | |
| .reset_dma = zorro_esp_reset_dma, | |
| .dma_drain = zorro_esp_dma_drain, | |
| .dma_invalidate = fastlane_esp_dma_invalidate, | |
| .send_dma_cmd = zorro_esp_send_fastlane_dma_cmd, | |
| .dma_error = zorro_esp_dma_error, | |
| }; | |
| /* Zorro driver config data */ | |
| struct zorro_driver_data { | |
| const char *name; | |
| unsigned long offset; | |
| unsigned long dma_offset; | |
| int absolute; /* offset is absolute address */ | |
| int scsi_option; | |
| const struct esp_driver_ops *esp_ops; | |
| }; | |
| /* board types */ | |
| enum { | |
| ZORRO_BLZ1230, | |
| ZORRO_BLZ1230II, | |
| ZORRO_BLZ2060, | |
| ZORRO_CYBER, | |
| ZORRO_CYBERII, | |
| ZORRO_FASTLANE, | |
| }; | |
| /* per-board config data */ | |
| static const struct zorro_driver_data zorro_esp_boards[] = { | |
| [ZORRO_BLZ1230] = { | |
| .name = "Blizzard 1230", | |
| .offset = 0x8000, | |
| .dma_offset = 0x10000, | |
| .scsi_option = 1, | |
| .esp_ops = &blz1230_esp_ops, | |
| }, | |
| [ZORRO_BLZ1230II] = { | |
| .name = "Blizzard 1230II", | |
| .offset = 0x10000, | |
| .dma_offset = 0x10021, | |
| .scsi_option = 1, | |
| .esp_ops = &blz1230II_esp_ops, | |
| }, | |
| [ZORRO_BLZ2060] = { | |
| .name = "Blizzard 2060", | |
| .offset = 0x1ff00, | |
| .dma_offset = 0x1ffe0, | |
| .esp_ops = &blz2060_esp_ops, | |
| }, | |
| [ZORRO_CYBER] = { | |
| .name = "CyberStormI", | |
| .offset = 0xf400, | |
| .dma_offset = 0xf800, | |
| .esp_ops = &cyber_esp_ops, | |
| }, | |
| [ZORRO_CYBERII] = { | |
| .name = "CyberStormII", | |
| .offset = 0x1ff03, | |
| .dma_offset = 0x1ff43, | |
| .scsi_option = 1, | |
| .esp_ops = &cyberII_esp_ops, | |
| }, | |
| [ZORRO_FASTLANE] = { | |
| .name = "Fastlane", | |
| .offset = 0x1000001, | |
| .dma_offset = 0x1000041, | |
| .esp_ops = &fastlane_esp_ops, | |
| }, | |
| }; | |
| static const struct zorro_device_id zorro_esp_zorro_tbl[] = { | |
| { /* Blizzard 1230 IV */ | |
| .id = ZORRO_ID(PHASE5, 0x11, 0), | |
| .driver_data = ZORRO_BLZ1230, | |
| }, | |
| { /* Blizzard 1230 II (Zorro II) or Fastlane (Zorro III) */ | |
| .id = ZORRO_ID(PHASE5, 0x0B, 0), | |
| .driver_data = ZORRO_BLZ1230II, | |
| }, | |
| { /* Blizzard 2060 */ | |
| .id = ZORRO_ID(PHASE5, 0x18, 0), | |
| .driver_data = ZORRO_BLZ2060, | |
| }, | |
| { /* Cyberstorm */ | |
| .id = ZORRO_ID(PHASE5, 0x0C, 0), | |
| .driver_data = ZORRO_CYBER, | |
| }, | |
| { /* Cyberstorm II */ | |
| .id = ZORRO_ID(PHASE5, 0x19, 0), | |
| .driver_data = ZORRO_CYBERII, | |
| }, | |
| { } | |
| }; | |
| MODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl); | |
| static int zorro_esp_probe(struct zorro_dev *z, | |
| const struct zorro_device_id *ent) | |
| { | |
| const struct scsi_host_template *tpnt = &scsi_esp_template; | |
| struct Scsi_Host *host; | |
| struct esp *esp; | |
| const struct zorro_driver_data *zdd; | |
| struct zorro_esp_priv *zep; | |
| unsigned long board, ioaddr, dmaaddr; | |
| int err; | |
| board = zorro_resource_start(z); | |
| zdd = &zorro_esp_boards[ent->driver_data]; | |
| pr_info("%s found at address 0x%lx.\n", zdd->name, board); | |
| zep = kzalloc_obj(*zep); | |
| 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) { | |
| if (board > 0xffffff) | |
| zep->zorro3 = 1; | |
| } 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->driver_data == ZORRO_BLZ1230II) { | |
| pr_info("%s at address 0x%lx is Fastlane Z3, fixing data!\n", | |
| zdd->name, board); | |
| zdd = &zorro_esp_boards[ZORRO_FASTLANE]; | |
| } | |
| 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; | |
| } | |
| 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->esp = esp; | |
| dev_set_drvdata(esp->dev, zep); | |
| /* additional setup required for Fastlane */ | |
| if (zep->zorro3 && ent->driver_data == ZORRO_BLZ1230II) { | |
| /* map full address space up to ESP base for DMA */ | |
| zep->board_base = ioremap(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); | |
| } | |
| esp->ops = zdd->esp_ops; | |
| if (ioaddr > 0xffffff) | |
| esp->regs = ioremap(ioaddr, 0x20); | |
| else | |
| /* ZorroII address space remapped nocache by early startup */ | |
| esp->regs = ZTWO_VADDR(ioaddr); | |
| if (!esp->regs) { | |
| err = -ENOMEM; | |
| goto fail_unmap_fastlane; | |
| } | |
| esp->fifo_reg = esp->regs + ESP_FDATA * 4; | |
| /* 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(dmaaddr, | |
| sizeof(struct fastlane_dma_registers)); | |
| } else | |
| /* ZorroII address space remapped nocache by early startup */ | |
| esp->dma_regs = 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); | |
| if (err) { | |
| err = -ENOMEM; | |
| goto fail_free_irq; | |
| } | |
| 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) | |
| { | |
| struct zorro_esp_priv *zep = dev_get_drvdata(&z->dev); | |
| struct esp *esp = zep->esp; | |
| struct Scsi_Host *host = esp->host; | |
| scsi_esp_unregister(esp); | |
| 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); |