mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-11-01 08:58:07 +00:00
53dce332db
As a temporary measure, the code to implement PIO transfers was duplicated in zorro_esp and mac_esp. Now that it has stabilized move the common code into the core driver but don't build it unless needed. This replaces the inline assembler with more portable writesb() calls. Optimizing the m68k writesb() implementation is a separate patch. [mkp: applied by hand] Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Tested-by: Stan Johnson <userm57@yahoo.com> Tested-by: Michael Schmitz <schmitzmic@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
954 lines
25 KiB
C
954 lines
25 KiB
C
// 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 <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 <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 > 0xFFFF ? 0xFFFF : 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 = zorro_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_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);
|
|
}
|
|
|
|
esp->ops = zdd->esp_ops;
|
|
|
|
if (ioaddr > 0xffffff)
|
|
esp->regs = ioremap_nocache(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_nocache(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);
|