forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
960 lines
25 KiB
960 lines
25 KiB
// SPDX-License-Identifier: GPL-2.0 |
|
/* |
|
* 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 |
|
*/ |
|
/* |
|
* 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 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 <[email protected]>"); |
|
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, |
|
}, |
|
{ 0 } |
|
}; |
|
MODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl); |
|
|
|
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; |
|
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(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) { |
|
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);
|
|
|