162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ESP front-end for Amiga ZORRO SCSI systems. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2011,2018 Michael Schmitz (schmitz@debian.org) for 862306a36Sopenharmony_ci * migration to ESP SCSI core 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Copyright (C) 2013 Tuomas Vainikka (tuomas.vainikka@aalto.fi) for 1162306a36Sopenharmony_ci * Blizzard 1230 DMA and probe function fixes 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * ZORRO bus code from: 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci/* 1762306a36Sopenharmony_ci * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux. 1862306a36Sopenharmony_ci * Amiga MacroSystemUS WarpEngine SCSI controller. 1962306a36Sopenharmony_ci * Amiga Technologies/DKB A4091 SCSI controller. 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk> 2262306a36Sopenharmony_ci * plus modifications of the 53c7xx.c driver to support the Amiga. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org> 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <linux/module.h> 3062306a36Sopenharmony_ci#include <linux/init.h> 3162306a36Sopenharmony_ci#include <linux/interrupt.h> 3262306a36Sopenharmony_ci#include <linux/dma-mapping.h> 3362306a36Sopenharmony_ci#include <linux/scatterlist.h> 3462306a36Sopenharmony_ci#include <linux/delay.h> 3562306a36Sopenharmony_ci#include <linux/zorro.h> 3662306a36Sopenharmony_ci#include <linux/slab.h> 3762306a36Sopenharmony_ci#include <linux/pgtable.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#include <asm/page.h> 4062306a36Sopenharmony_ci#include <asm/cacheflush.h> 4162306a36Sopenharmony_ci#include <asm/amigahw.h> 4262306a36Sopenharmony_ci#include <asm/amigaints.h> 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#include <scsi/scsi_host.h> 4562306a36Sopenharmony_ci#include <scsi/scsi_transport_spi.h> 4662306a36Sopenharmony_ci#include <scsi/scsi_device.h> 4762306a36Sopenharmony_ci#include <scsi/scsi_tcq.h> 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#include "esp_scsi.h" 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ciMODULE_AUTHOR("Michael Schmitz <schmitz@debian.org>"); 5262306a36Sopenharmony_ciMODULE_DESCRIPTION("Amiga Zorro NCR5C9x (ESP) driver"); 5362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* per-board register layout definitions */ 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* Blizzard 1230 DMA interface */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct blz1230_dma_registers { 6062306a36Sopenharmony_ci unsigned char dma_addr; /* DMA address [0x0000] */ 6162306a36Sopenharmony_ci unsigned char dmapad2[0x7fff]; 6262306a36Sopenharmony_ci unsigned char dma_latch; /* DMA latch [0x8000] */ 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* Blizzard 1230II DMA interface */ 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistruct blz1230II_dma_registers { 6862306a36Sopenharmony_ci unsigned char dma_addr; /* DMA address [0x0000] */ 6962306a36Sopenharmony_ci unsigned char dmapad2[0xf]; 7062306a36Sopenharmony_ci unsigned char dma_latch; /* DMA latch [0x0010] */ 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* Blizzard 2060 DMA interface */ 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cistruct blz2060_dma_registers { 7662306a36Sopenharmony_ci unsigned char dma_led_ctrl; /* DMA led control [0x000] */ 7762306a36Sopenharmony_ci unsigned char dmapad1[0x0f]; 7862306a36Sopenharmony_ci unsigned char dma_addr0; /* DMA address (MSB) [0x010] */ 7962306a36Sopenharmony_ci unsigned char dmapad2[0x03]; 8062306a36Sopenharmony_ci unsigned char dma_addr1; /* DMA address [0x014] */ 8162306a36Sopenharmony_ci unsigned char dmapad3[0x03]; 8262306a36Sopenharmony_ci unsigned char dma_addr2; /* DMA address [0x018] */ 8362306a36Sopenharmony_ci unsigned char dmapad4[0x03]; 8462306a36Sopenharmony_ci unsigned char dma_addr3; /* DMA address (LSB) [0x01c] */ 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* DMA control bits */ 8862306a36Sopenharmony_ci#define DMA_WRITE 0x80000000 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/* Cyberstorm DMA interface */ 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistruct cyber_dma_registers { 9362306a36Sopenharmony_ci unsigned char dma_addr0; /* DMA address (MSB) [0x000] */ 9462306a36Sopenharmony_ci unsigned char dmapad1[1]; 9562306a36Sopenharmony_ci unsigned char dma_addr1; /* DMA address [0x002] */ 9662306a36Sopenharmony_ci unsigned char dmapad2[1]; 9762306a36Sopenharmony_ci unsigned char dma_addr2; /* DMA address [0x004] */ 9862306a36Sopenharmony_ci unsigned char dmapad3[1]; 9962306a36Sopenharmony_ci unsigned char dma_addr3; /* DMA address (LSB) [0x006] */ 10062306a36Sopenharmony_ci unsigned char dmapad4[0x3fb]; 10162306a36Sopenharmony_ci unsigned char cond_reg; /* DMA cond (ro) [0x402] */ 10262306a36Sopenharmony_ci#define ctrl_reg cond_reg /* DMA control (wo) [0x402] */ 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci/* DMA control bits */ 10662306a36Sopenharmony_ci#define CYBER_DMA_WRITE 0x40 /* DMA direction. 1 = write */ 10762306a36Sopenharmony_ci#define CYBER_DMA_Z3 0x20 /* 16 (Z2) or 32 (CHIP/Z3) bit DMA transfer */ 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci/* DMA status bits */ 11062306a36Sopenharmony_ci#define CYBER_DMA_HNDL_INTR 0x80 /* DMA IRQ pending? */ 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci/* The CyberStorm II DMA interface */ 11362306a36Sopenharmony_cistruct cyberII_dma_registers { 11462306a36Sopenharmony_ci unsigned char cond_reg; /* DMA cond (ro) [0x000] */ 11562306a36Sopenharmony_ci#define ctrl_reg cond_reg /* DMA control (wo) [0x000] */ 11662306a36Sopenharmony_ci unsigned char dmapad4[0x3f]; 11762306a36Sopenharmony_ci unsigned char dma_addr0; /* DMA address (MSB) [0x040] */ 11862306a36Sopenharmony_ci unsigned char dmapad1[3]; 11962306a36Sopenharmony_ci unsigned char dma_addr1; /* DMA address [0x044] */ 12062306a36Sopenharmony_ci unsigned char dmapad2[3]; 12162306a36Sopenharmony_ci unsigned char dma_addr2; /* DMA address [0x048] */ 12262306a36Sopenharmony_ci unsigned char dmapad3[3]; 12362306a36Sopenharmony_ci unsigned char dma_addr3; /* DMA address (LSB) [0x04c] */ 12462306a36Sopenharmony_ci}; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci/* Fastlane DMA interface */ 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistruct fastlane_dma_registers { 12962306a36Sopenharmony_ci unsigned char cond_reg; /* DMA status (ro) [0x0000] */ 13062306a36Sopenharmony_ci#define ctrl_reg cond_reg /* DMA control (wo) [0x0000] */ 13162306a36Sopenharmony_ci char dmapad1[0x3f]; 13262306a36Sopenharmony_ci unsigned char clear_strobe; /* DMA clear (wo) [0x0040] */ 13362306a36Sopenharmony_ci}; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci/* 13662306a36Sopenharmony_ci * The controller registers can be found in the Z2 config area at these 13762306a36Sopenharmony_ci * offsets: 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_ci#define FASTLANE_ESP_ADDR 0x1000001 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/* DMA status bits */ 14262306a36Sopenharmony_ci#define FASTLANE_DMA_MINT 0x80 14362306a36Sopenharmony_ci#define FASTLANE_DMA_IACT 0x40 14462306a36Sopenharmony_ci#define FASTLANE_DMA_CREQ 0x20 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/* DMA control bits */ 14762306a36Sopenharmony_ci#define FASTLANE_DMA_FCODE 0xa0 14862306a36Sopenharmony_ci#define FASTLANE_DMA_MASK 0xf3 14962306a36Sopenharmony_ci#define FASTLANE_DMA_WRITE 0x08 /* 1 = write */ 15062306a36Sopenharmony_ci#define FASTLANE_DMA_ENABLE 0x04 /* Enable DMA */ 15162306a36Sopenharmony_ci#define FASTLANE_DMA_EDI 0x02 /* Enable DMA IRQ ? */ 15262306a36Sopenharmony_ci#define FASTLANE_DMA_ESI 0x01 /* Enable SCSI IRQ */ 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/* 15562306a36Sopenharmony_ci * private data used for driver 15662306a36Sopenharmony_ci */ 15762306a36Sopenharmony_cistruct zorro_esp_priv { 15862306a36Sopenharmony_ci struct esp *esp; /* our ESP instance - for Scsi_host* */ 15962306a36Sopenharmony_ci void __iomem *board_base; /* virtual address (Zorro III board) */ 16062306a36Sopenharmony_ci int zorro3; /* board is Zorro III */ 16162306a36Sopenharmony_ci unsigned char ctrl_data; /* shadow copy of ctrl_reg */ 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/* 16562306a36Sopenharmony_ci * On all implementations except for the Oktagon, padding between ESP 16662306a36Sopenharmony_ci * registers is three bytes. 16762306a36Sopenharmony_ci * On Oktagon, it is one byte - use a different accessor there. 16862306a36Sopenharmony_ci * 16962306a36Sopenharmony_ci * Oktagon needs PDMA - currently unsupported! 17062306a36Sopenharmony_ci */ 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic void zorro_esp_write8(struct esp *esp, u8 val, unsigned long reg) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci writeb(val, esp->regs + (reg * 4UL)); 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic u8 zorro_esp_read8(struct esp *esp, unsigned long reg) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci return readb(esp->regs + (reg * 4UL)); 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic int zorro_esp_irq_pending(struct esp *esp) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci /* check ESP status register; DMA has no status reg. */ 18562306a36Sopenharmony_ci if (zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR) 18662306a36Sopenharmony_ci return 1; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci return 0; 18962306a36Sopenharmony_ci} 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_cistatic int cyber_esp_irq_pending(struct esp *esp) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci struct cyber_dma_registers __iomem *dregs = esp->dma_regs; 19462306a36Sopenharmony_ci unsigned char dma_status = readb(&dregs->cond_reg); 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci /* It's important to check the DMA IRQ bit in the correct way! */ 19762306a36Sopenharmony_ci return ((zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR) && 19862306a36Sopenharmony_ci (dma_status & CYBER_DMA_HNDL_INTR)); 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic int fastlane_esp_irq_pending(struct esp *esp) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci struct fastlane_dma_registers __iomem *dregs = esp->dma_regs; 20462306a36Sopenharmony_ci unsigned char dma_status; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci dma_status = readb(&dregs->cond_reg); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci if (dma_status & FASTLANE_DMA_IACT) 20962306a36Sopenharmony_ci return 0; /* not our IRQ */ 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* Return non-zero if ESP requested IRQ */ 21262306a36Sopenharmony_ci return ( 21362306a36Sopenharmony_ci (dma_status & FASTLANE_DMA_CREQ) && 21462306a36Sopenharmony_ci (!(dma_status & FASTLANE_DMA_MINT)) && 21562306a36Sopenharmony_ci (zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)); 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_cistatic u32 zorro_esp_dma_length_limit(struct esp *esp, u32 dma_addr, 21962306a36Sopenharmony_ci u32 dma_len) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci return dma_len > (1U << 16) ? (1U << 16) : dma_len; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic u32 fastlane_esp_dma_length_limit(struct esp *esp, u32 dma_addr, 22562306a36Sopenharmony_ci u32 dma_len) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci /* The old driver used 0xfffc as limit, so do that here too */ 22862306a36Sopenharmony_ci return dma_len > 0xfffc ? 0xfffc : dma_len; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic void zorro_esp_reset_dma(struct esp *esp) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci /* nothing to do here */ 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic void zorro_esp_dma_drain(struct esp *esp) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci /* nothing to do here */ 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic void zorro_esp_dma_invalidate(struct esp *esp) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci /* nothing to do here */ 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_cistatic void fastlane_esp_dma_invalidate(struct esp *esp) 24762306a36Sopenharmony_ci{ 24862306a36Sopenharmony_ci struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev); 24962306a36Sopenharmony_ci struct fastlane_dma_registers __iomem *dregs = esp->dma_regs; 25062306a36Sopenharmony_ci unsigned char *ctrl_data = &zep->ctrl_data; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci *ctrl_data = (*ctrl_data & FASTLANE_DMA_MASK); 25362306a36Sopenharmony_ci writeb(0, &dregs->clear_strobe); 25462306a36Sopenharmony_ci z_writel(0, zep->board_base); 25562306a36Sopenharmony_ci} 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci/* Blizzard 1230/60 SCSI-IV DMA */ 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic void zorro_esp_send_blz1230_dma_cmd(struct esp *esp, u32 addr, 26062306a36Sopenharmony_ci u32 esp_count, u32 dma_count, int write, u8 cmd) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci struct blz1230_dma_registers __iomem *dregs = esp->dma_regs; 26362306a36Sopenharmony_ci u8 phase = esp->sreg & ESP_STAT_PMASK; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci /* 26662306a36Sopenharmony_ci * Use PIO if transferring message bytes to esp->command_block_dma. 26762306a36Sopenharmony_ci * PIO requires a virtual address, so substitute esp->command_block 26862306a36Sopenharmony_ci * for addr. 26962306a36Sopenharmony_ci */ 27062306a36Sopenharmony_ci if (phase == ESP_MIP && addr == esp->command_block_dma) { 27162306a36Sopenharmony_ci esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, 27262306a36Sopenharmony_ci dma_count, write, cmd); 27362306a36Sopenharmony_ci return; 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci /* Clear the results of a possible prior esp->ops->send_dma_cmd() */ 27762306a36Sopenharmony_ci esp->send_cmd_error = 0; 27862306a36Sopenharmony_ci esp->send_cmd_residual = 0; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci if (write) 28162306a36Sopenharmony_ci /* DMA receive */ 28262306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 28362306a36Sopenharmony_ci DMA_FROM_DEVICE); 28462306a36Sopenharmony_ci else 28562306a36Sopenharmony_ci /* DMA send */ 28662306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 28762306a36Sopenharmony_ci DMA_TO_DEVICE); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci addr >>= 1; 29062306a36Sopenharmony_ci if (write) 29162306a36Sopenharmony_ci addr &= ~(DMA_WRITE); 29262306a36Sopenharmony_ci else 29362306a36Sopenharmony_ci addr |= DMA_WRITE; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci writeb((addr >> 24) & 0xff, &dregs->dma_latch); 29662306a36Sopenharmony_ci writeb((addr >> 24) & 0xff, &dregs->dma_addr); 29762306a36Sopenharmony_ci writeb((addr >> 16) & 0xff, &dregs->dma_addr); 29862306a36Sopenharmony_ci writeb((addr >> 8) & 0xff, &dregs->dma_addr); 29962306a36Sopenharmony_ci writeb(addr & 0xff, &dregs->dma_addr); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci scsi_esp_cmd(esp, ESP_CMD_DMA); 30262306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); 30362306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci scsi_esp_cmd(esp, cmd); 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci/* Blizzard 1230-II DMA */ 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic void zorro_esp_send_blz1230II_dma_cmd(struct esp *esp, u32 addr, 31162306a36Sopenharmony_ci u32 esp_count, u32 dma_count, int write, u8 cmd) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci struct blz1230II_dma_registers __iomem *dregs = esp->dma_regs; 31462306a36Sopenharmony_ci u8 phase = esp->sreg & ESP_STAT_PMASK; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* Use PIO if transferring message bytes to esp->command_block_dma */ 31762306a36Sopenharmony_ci if (phase == ESP_MIP && addr == esp->command_block_dma) { 31862306a36Sopenharmony_ci esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, 31962306a36Sopenharmony_ci dma_count, write, cmd); 32062306a36Sopenharmony_ci return; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci esp->send_cmd_error = 0; 32462306a36Sopenharmony_ci esp->send_cmd_residual = 0; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (write) 32762306a36Sopenharmony_ci /* DMA receive */ 32862306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 32962306a36Sopenharmony_ci DMA_FROM_DEVICE); 33062306a36Sopenharmony_ci else 33162306a36Sopenharmony_ci /* DMA send */ 33262306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 33362306a36Sopenharmony_ci DMA_TO_DEVICE); 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_ci addr >>= 1; 33662306a36Sopenharmony_ci if (write) 33762306a36Sopenharmony_ci addr &= ~(DMA_WRITE); 33862306a36Sopenharmony_ci else 33962306a36Sopenharmony_ci addr |= DMA_WRITE; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci writeb((addr >> 24) & 0xff, &dregs->dma_latch); 34262306a36Sopenharmony_ci writeb((addr >> 16) & 0xff, &dregs->dma_addr); 34362306a36Sopenharmony_ci writeb((addr >> 8) & 0xff, &dregs->dma_addr); 34462306a36Sopenharmony_ci writeb(addr & 0xff, &dregs->dma_addr); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci scsi_esp_cmd(esp, ESP_CMD_DMA); 34762306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); 34862306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci scsi_esp_cmd(esp, cmd); 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci/* Blizzard 2060 DMA */ 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic void zorro_esp_send_blz2060_dma_cmd(struct esp *esp, u32 addr, 35662306a36Sopenharmony_ci u32 esp_count, u32 dma_count, int write, u8 cmd) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci struct blz2060_dma_registers __iomem *dregs = esp->dma_regs; 35962306a36Sopenharmony_ci u8 phase = esp->sreg & ESP_STAT_PMASK; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci /* Use PIO if transferring message bytes to esp->command_block_dma */ 36262306a36Sopenharmony_ci if (phase == ESP_MIP && addr == esp->command_block_dma) { 36362306a36Sopenharmony_ci esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, 36462306a36Sopenharmony_ci dma_count, write, cmd); 36562306a36Sopenharmony_ci return; 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci esp->send_cmd_error = 0; 36962306a36Sopenharmony_ci esp->send_cmd_residual = 0; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci if (write) 37262306a36Sopenharmony_ci /* DMA receive */ 37362306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 37462306a36Sopenharmony_ci DMA_FROM_DEVICE); 37562306a36Sopenharmony_ci else 37662306a36Sopenharmony_ci /* DMA send */ 37762306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 37862306a36Sopenharmony_ci DMA_TO_DEVICE); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci addr >>= 1; 38162306a36Sopenharmony_ci if (write) 38262306a36Sopenharmony_ci addr &= ~(DMA_WRITE); 38362306a36Sopenharmony_ci else 38462306a36Sopenharmony_ci addr |= DMA_WRITE; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci writeb(addr & 0xff, &dregs->dma_addr3); 38762306a36Sopenharmony_ci writeb((addr >> 8) & 0xff, &dregs->dma_addr2); 38862306a36Sopenharmony_ci writeb((addr >> 16) & 0xff, &dregs->dma_addr1); 38962306a36Sopenharmony_ci writeb((addr >> 24) & 0xff, &dregs->dma_addr0); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci scsi_esp_cmd(esp, ESP_CMD_DMA); 39262306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); 39362306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci scsi_esp_cmd(esp, cmd); 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci/* Cyberstorm I DMA */ 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic void zorro_esp_send_cyber_dma_cmd(struct esp *esp, u32 addr, 40162306a36Sopenharmony_ci u32 esp_count, u32 dma_count, int write, u8 cmd) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev); 40462306a36Sopenharmony_ci struct cyber_dma_registers __iomem *dregs = esp->dma_regs; 40562306a36Sopenharmony_ci u8 phase = esp->sreg & ESP_STAT_PMASK; 40662306a36Sopenharmony_ci unsigned char *ctrl_data = &zep->ctrl_data; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci /* Use PIO if transferring message bytes to esp->command_block_dma */ 40962306a36Sopenharmony_ci if (phase == ESP_MIP && addr == esp->command_block_dma) { 41062306a36Sopenharmony_ci esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, 41162306a36Sopenharmony_ci dma_count, write, cmd); 41262306a36Sopenharmony_ci return; 41362306a36Sopenharmony_ci } 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci esp->send_cmd_error = 0; 41662306a36Sopenharmony_ci esp->send_cmd_residual = 0; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); 41962306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci if (write) { 42262306a36Sopenharmony_ci /* DMA receive */ 42362306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 42462306a36Sopenharmony_ci DMA_FROM_DEVICE); 42562306a36Sopenharmony_ci addr &= ~(1); 42662306a36Sopenharmony_ci } else { 42762306a36Sopenharmony_ci /* DMA send */ 42862306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 42962306a36Sopenharmony_ci DMA_TO_DEVICE); 43062306a36Sopenharmony_ci addr |= 1; 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci writeb((addr >> 24) & 0xff, &dregs->dma_addr0); 43462306a36Sopenharmony_ci writeb((addr >> 16) & 0xff, &dregs->dma_addr1); 43562306a36Sopenharmony_ci writeb((addr >> 8) & 0xff, &dregs->dma_addr2); 43662306a36Sopenharmony_ci writeb(addr & 0xff, &dregs->dma_addr3); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci if (write) 43962306a36Sopenharmony_ci *ctrl_data &= ~(CYBER_DMA_WRITE); 44062306a36Sopenharmony_ci else 44162306a36Sopenharmony_ci *ctrl_data |= CYBER_DMA_WRITE; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci *ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */ 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci writeb(*ctrl_data, &dregs->ctrl_reg); 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci scsi_esp_cmd(esp, cmd); 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci/* Cyberstorm II DMA */ 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_cistatic void zorro_esp_send_cyberII_dma_cmd(struct esp *esp, u32 addr, 45362306a36Sopenharmony_ci u32 esp_count, u32 dma_count, int write, u8 cmd) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci struct cyberII_dma_registers __iomem *dregs = esp->dma_regs; 45662306a36Sopenharmony_ci u8 phase = esp->sreg & ESP_STAT_PMASK; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci /* Use PIO if transferring message bytes to esp->command_block_dma */ 45962306a36Sopenharmony_ci if (phase == ESP_MIP && addr == esp->command_block_dma) { 46062306a36Sopenharmony_ci esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, 46162306a36Sopenharmony_ci dma_count, write, cmd); 46262306a36Sopenharmony_ci return; 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci esp->send_cmd_error = 0; 46662306a36Sopenharmony_ci esp->send_cmd_residual = 0; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); 46962306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci if (write) { 47262306a36Sopenharmony_ci /* DMA receive */ 47362306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 47462306a36Sopenharmony_ci DMA_FROM_DEVICE); 47562306a36Sopenharmony_ci addr &= ~(1); 47662306a36Sopenharmony_ci } else { 47762306a36Sopenharmony_ci /* DMA send */ 47862306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 47962306a36Sopenharmony_ci DMA_TO_DEVICE); 48062306a36Sopenharmony_ci addr |= 1; 48162306a36Sopenharmony_ci } 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci writeb((addr >> 24) & 0xff, &dregs->dma_addr0); 48462306a36Sopenharmony_ci writeb((addr >> 16) & 0xff, &dregs->dma_addr1); 48562306a36Sopenharmony_ci writeb((addr >> 8) & 0xff, &dregs->dma_addr2); 48662306a36Sopenharmony_ci writeb(addr & 0xff, &dregs->dma_addr3); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci scsi_esp_cmd(esp, cmd); 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci/* Fastlane DMA */ 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_cistatic void zorro_esp_send_fastlane_dma_cmd(struct esp *esp, u32 addr, 49462306a36Sopenharmony_ci u32 esp_count, u32 dma_count, int write, u8 cmd) 49562306a36Sopenharmony_ci{ 49662306a36Sopenharmony_ci struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev); 49762306a36Sopenharmony_ci struct fastlane_dma_registers __iomem *dregs = esp->dma_regs; 49862306a36Sopenharmony_ci u8 phase = esp->sreg & ESP_STAT_PMASK; 49962306a36Sopenharmony_ci unsigned char *ctrl_data = &zep->ctrl_data; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci /* Use PIO if transferring message bytes to esp->command_block_dma */ 50262306a36Sopenharmony_ci if (phase == ESP_MIP && addr == esp->command_block_dma) { 50362306a36Sopenharmony_ci esp_send_pio_cmd(esp, (u32)esp->command_block, esp_count, 50462306a36Sopenharmony_ci dma_count, write, cmd); 50562306a36Sopenharmony_ci return; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci esp->send_cmd_error = 0; 50962306a36Sopenharmony_ci esp->send_cmd_residual = 0; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); 51262306a36Sopenharmony_ci zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci if (write) { 51562306a36Sopenharmony_ci /* DMA receive */ 51662306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 51762306a36Sopenharmony_ci DMA_FROM_DEVICE); 51862306a36Sopenharmony_ci addr &= ~(1); 51962306a36Sopenharmony_ci } else { 52062306a36Sopenharmony_ci /* DMA send */ 52162306a36Sopenharmony_ci dma_sync_single_for_device(esp->dev, addr, esp_count, 52262306a36Sopenharmony_ci DMA_TO_DEVICE); 52362306a36Sopenharmony_ci addr |= 1; 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci writeb(0, &dregs->clear_strobe); 52762306a36Sopenharmony_ci z_writel(addr, ((addr & 0x00ffffff) + zep->board_base)); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci if (write) { 53062306a36Sopenharmony_ci *ctrl_data = (*ctrl_data & FASTLANE_DMA_MASK) | 53162306a36Sopenharmony_ci FASTLANE_DMA_ENABLE; 53262306a36Sopenharmony_ci } else { 53362306a36Sopenharmony_ci *ctrl_data = ((*ctrl_data & FASTLANE_DMA_MASK) | 53462306a36Sopenharmony_ci FASTLANE_DMA_ENABLE | 53562306a36Sopenharmony_ci FASTLANE_DMA_WRITE); 53662306a36Sopenharmony_ci } 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci writeb(*ctrl_data, &dregs->ctrl_reg); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci scsi_esp_cmd(esp, cmd); 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cistatic int zorro_esp_dma_error(struct esp *esp) 54462306a36Sopenharmony_ci{ 54562306a36Sopenharmony_ci return esp->send_cmd_error; 54662306a36Sopenharmony_ci} 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci/* per-board ESP driver ops */ 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistatic const struct esp_driver_ops blz1230_esp_ops = { 55162306a36Sopenharmony_ci .esp_write8 = zorro_esp_write8, 55262306a36Sopenharmony_ci .esp_read8 = zorro_esp_read8, 55362306a36Sopenharmony_ci .irq_pending = zorro_esp_irq_pending, 55462306a36Sopenharmony_ci .dma_length_limit = zorro_esp_dma_length_limit, 55562306a36Sopenharmony_ci .reset_dma = zorro_esp_reset_dma, 55662306a36Sopenharmony_ci .dma_drain = zorro_esp_dma_drain, 55762306a36Sopenharmony_ci .dma_invalidate = zorro_esp_dma_invalidate, 55862306a36Sopenharmony_ci .send_dma_cmd = zorro_esp_send_blz1230_dma_cmd, 55962306a36Sopenharmony_ci .dma_error = zorro_esp_dma_error, 56062306a36Sopenharmony_ci}; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistatic const struct esp_driver_ops blz1230II_esp_ops = { 56362306a36Sopenharmony_ci .esp_write8 = zorro_esp_write8, 56462306a36Sopenharmony_ci .esp_read8 = zorro_esp_read8, 56562306a36Sopenharmony_ci .irq_pending = zorro_esp_irq_pending, 56662306a36Sopenharmony_ci .dma_length_limit = zorro_esp_dma_length_limit, 56762306a36Sopenharmony_ci .reset_dma = zorro_esp_reset_dma, 56862306a36Sopenharmony_ci .dma_drain = zorro_esp_dma_drain, 56962306a36Sopenharmony_ci .dma_invalidate = zorro_esp_dma_invalidate, 57062306a36Sopenharmony_ci .send_dma_cmd = zorro_esp_send_blz1230II_dma_cmd, 57162306a36Sopenharmony_ci .dma_error = zorro_esp_dma_error, 57262306a36Sopenharmony_ci}; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic const struct esp_driver_ops blz2060_esp_ops = { 57562306a36Sopenharmony_ci .esp_write8 = zorro_esp_write8, 57662306a36Sopenharmony_ci .esp_read8 = zorro_esp_read8, 57762306a36Sopenharmony_ci .irq_pending = zorro_esp_irq_pending, 57862306a36Sopenharmony_ci .dma_length_limit = zorro_esp_dma_length_limit, 57962306a36Sopenharmony_ci .reset_dma = zorro_esp_reset_dma, 58062306a36Sopenharmony_ci .dma_drain = zorro_esp_dma_drain, 58162306a36Sopenharmony_ci .dma_invalidate = zorro_esp_dma_invalidate, 58262306a36Sopenharmony_ci .send_dma_cmd = zorro_esp_send_blz2060_dma_cmd, 58362306a36Sopenharmony_ci .dma_error = zorro_esp_dma_error, 58462306a36Sopenharmony_ci}; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_cistatic const struct esp_driver_ops cyber_esp_ops = { 58762306a36Sopenharmony_ci .esp_write8 = zorro_esp_write8, 58862306a36Sopenharmony_ci .esp_read8 = zorro_esp_read8, 58962306a36Sopenharmony_ci .irq_pending = cyber_esp_irq_pending, 59062306a36Sopenharmony_ci .dma_length_limit = zorro_esp_dma_length_limit, 59162306a36Sopenharmony_ci .reset_dma = zorro_esp_reset_dma, 59262306a36Sopenharmony_ci .dma_drain = zorro_esp_dma_drain, 59362306a36Sopenharmony_ci .dma_invalidate = zorro_esp_dma_invalidate, 59462306a36Sopenharmony_ci .send_dma_cmd = zorro_esp_send_cyber_dma_cmd, 59562306a36Sopenharmony_ci .dma_error = zorro_esp_dma_error, 59662306a36Sopenharmony_ci}; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic const struct esp_driver_ops cyberII_esp_ops = { 59962306a36Sopenharmony_ci .esp_write8 = zorro_esp_write8, 60062306a36Sopenharmony_ci .esp_read8 = zorro_esp_read8, 60162306a36Sopenharmony_ci .irq_pending = zorro_esp_irq_pending, 60262306a36Sopenharmony_ci .dma_length_limit = zorro_esp_dma_length_limit, 60362306a36Sopenharmony_ci .reset_dma = zorro_esp_reset_dma, 60462306a36Sopenharmony_ci .dma_drain = zorro_esp_dma_drain, 60562306a36Sopenharmony_ci .dma_invalidate = zorro_esp_dma_invalidate, 60662306a36Sopenharmony_ci .send_dma_cmd = zorro_esp_send_cyberII_dma_cmd, 60762306a36Sopenharmony_ci .dma_error = zorro_esp_dma_error, 60862306a36Sopenharmony_ci}; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_cistatic const struct esp_driver_ops fastlane_esp_ops = { 61162306a36Sopenharmony_ci .esp_write8 = zorro_esp_write8, 61262306a36Sopenharmony_ci .esp_read8 = zorro_esp_read8, 61362306a36Sopenharmony_ci .irq_pending = fastlane_esp_irq_pending, 61462306a36Sopenharmony_ci .dma_length_limit = fastlane_esp_dma_length_limit, 61562306a36Sopenharmony_ci .reset_dma = zorro_esp_reset_dma, 61662306a36Sopenharmony_ci .dma_drain = zorro_esp_dma_drain, 61762306a36Sopenharmony_ci .dma_invalidate = fastlane_esp_dma_invalidate, 61862306a36Sopenharmony_ci .send_dma_cmd = zorro_esp_send_fastlane_dma_cmd, 61962306a36Sopenharmony_ci .dma_error = zorro_esp_dma_error, 62062306a36Sopenharmony_ci}; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci/* Zorro driver config data */ 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_cistruct zorro_driver_data { 62562306a36Sopenharmony_ci const char *name; 62662306a36Sopenharmony_ci unsigned long offset; 62762306a36Sopenharmony_ci unsigned long dma_offset; 62862306a36Sopenharmony_ci int absolute; /* offset is absolute address */ 62962306a36Sopenharmony_ci int scsi_option; 63062306a36Sopenharmony_ci const struct esp_driver_ops *esp_ops; 63162306a36Sopenharmony_ci}; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci/* board types */ 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_cienum { 63662306a36Sopenharmony_ci ZORRO_BLZ1230, 63762306a36Sopenharmony_ci ZORRO_BLZ1230II, 63862306a36Sopenharmony_ci ZORRO_BLZ2060, 63962306a36Sopenharmony_ci ZORRO_CYBER, 64062306a36Sopenharmony_ci ZORRO_CYBERII, 64162306a36Sopenharmony_ci ZORRO_FASTLANE, 64262306a36Sopenharmony_ci}; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci/* per-board config data */ 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cistatic const struct zorro_driver_data zorro_esp_boards[] = { 64762306a36Sopenharmony_ci [ZORRO_BLZ1230] = { 64862306a36Sopenharmony_ci .name = "Blizzard 1230", 64962306a36Sopenharmony_ci .offset = 0x8000, 65062306a36Sopenharmony_ci .dma_offset = 0x10000, 65162306a36Sopenharmony_ci .scsi_option = 1, 65262306a36Sopenharmony_ci .esp_ops = &blz1230_esp_ops, 65362306a36Sopenharmony_ci }, 65462306a36Sopenharmony_ci [ZORRO_BLZ1230II] = { 65562306a36Sopenharmony_ci .name = "Blizzard 1230II", 65662306a36Sopenharmony_ci .offset = 0x10000, 65762306a36Sopenharmony_ci .dma_offset = 0x10021, 65862306a36Sopenharmony_ci .scsi_option = 1, 65962306a36Sopenharmony_ci .esp_ops = &blz1230II_esp_ops, 66062306a36Sopenharmony_ci }, 66162306a36Sopenharmony_ci [ZORRO_BLZ2060] = { 66262306a36Sopenharmony_ci .name = "Blizzard 2060", 66362306a36Sopenharmony_ci .offset = 0x1ff00, 66462306a36Sopenharmony_ci .dma_offset = 0x1ffe0, 66562306a36Sopenharmony_ci .esp_ops = &blz2060_esp_ops, 66662306a36Sopenharmony_ci }, 66762306a36Sopenharmony_ci [ZORRO_CYBER] = { 66862306a36Sopenharmony_ci .name = "CyberStormI", 66962306a36Sopenharmony_ci .offset = 0xf400, 67062306a36Sopenharmony_ci .dma_offset = 0xf800, 67162306a36Sopenharmony_ci .esp_ops = &cyber_esp_ops, 67262306a36Sopenharmony_ci }, 67362306a36Sopenharmony_ci [ZORRO_CYBERII] = { 67462306a36Sopenharmony_ci .name = "CyberStormII", 67562306a36Sopenharmony_ci .offset = 0x1ff03, 67662306a36Sopenharmony_ci .dma_offset = 0x1ff43, 67762306a36Sopenharmony_ci .scsi_option = 1, 67862306a36Sopenharmony_ci .esp_ops = &cyberII_esp_ops, 67962306a36Sopenharmony_ci }, 68062306a36Sopenharmony_ci [ZORRO_FASTLANE] = { 68162306a36Sopenharmony_ci .name = "Fastlane", 68262306a36Sopenharmony_ci .offset = 0x1000001, 68362306a36Sopenharmony_ci .dma_offset = 0x1000041, 68462306a36Sopenharmony_ci .esp_ops = &fastlane_esp_ops, 68562306a36Sopenharmony_ci }, 68662306a36Sopenharmony_ci}; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_cistatic const struct zorro_device_id zorro_esp_zorro_tbl[] = { 68962306a36Sopenharmony_ci { /* Blizzard 1230 IV */ 69062306a36Sopenharmony_ci .id = ZORRO_ID(PHASE5, 0x11, 0), 69162306a36Sopenharmony_ci .driver_data = ZORRO_BLZ1230, 69262306a36Sopenharmony_ci }, 69362306a36Sopenharmony_ci { /* Blizzard 1230 II (Zorro II) or Fastlane (Zorro III) */ 69462306a36Sopenharmony_ci .id = ZORRO_ID(PHASE5, 0x0B, 0), 69562306a36Sopenharmony_ci .driver_data = ZORRO_BLZ1230II, 69662306a36Sopenharmony_ci }, 69762306a36Sopenharmony_ci { /* Blizzard 2060 */ 69862306a36Sopenharmony_ci .id = ZORRO_ID(PHASE5, 0x18, 0), 69962306a36Sopenharmony_ci .driver_data = ZORRO_BLZ2060, 70062306a36Sopenharmony_ci }, 70162306a36Sopenharmony_ci { /* Cyberstorm */ 70262306a36Sopenharmony_ci .id = ZORRO_ID(PHASE5, 0x0C, 0), 70362306a36Sopenharmony_ci .driver_data = ZORRO_CYBER, 70462306a36Sopenharmony_ci }, 70562306a36Sopenharmony_ci { /* Cyberstorm II */ 70662306a36Sopenharmony_ci .id = ZORRO_ID(PHASE5, 0x19, 0), 70762306a36Sopenharmony_ci .driver_data = ZORRO_CYBERII, 70862306a36Sopenharmony_ci }, 70962306a36Sopenharmony_ci { 0 } 71062306a36Sopenharmony_ci}; 71162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_cistatic int zorro_esp_probe(struct zorro_dev *z, 71462306a36Sopenharmony_ci const struct zorro_device_id *ent) 71562306a36Sopenharmony_ci{ 71662306a36Sopenharmony_ci const struct scsi_host_template *tpnt = &scsi_esp_template; 71762306a36Sopenharmony_ci struct Scsi_Host *host; 71862306a36Sopenharmony_ci struct esp *esp; 71962306a36Sopenharmony_ci const struct zorro_driver_data *zdd; 72062306a36Sopenharmony_ci struct zorro_esp_priv *zep; 72162306a36Sopenharmony_ci unsigned long board, ioaddr, dmaaddr; 72262306a36Sopenharmony_ci int err; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci board = zorro_resource_start(z); 72562306a36Sopenharmony_ci zdd = &zorro_esp_boards[ent->driver_data]; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci pr_info("%s found at address 0x%lx.\n", zdd->name, board); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci zep = kzalloc(sizeof(*zep), GFP_KERNEL); 73062306a36Sopenharmony_ci if (!zep) { 73162306a36Sopenharmony_ci pr_err("Can't allocate device private data!\n"); 73262306a36Sopenharmony_ci return -ENOMEM; 73362306a36Sopenharmony_ci } 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci /* let's figure out whether we have a Zorro II or Zorro III board */ 73662306a36Sopenharmony_ci if ((z->rom.er_Type & ERT_TYPEMASK) == ERT_ZORROIII) { 73762306a36Sopenharmony_ci if (board > 0xffffff) 73862306a36Sopenharmony_ci zep->zorro3 = 1; 73962306a36Sopenharmony_ci } else { 74062306a36Sopenharmony_ci /* 74162306a36Sopenharmony_ci * Even though most of these boards identify as Zorro II, 74262306a36Sopenharmony_ci * they are in fact CPU expansion slot boards and have full 74362306a36Sopenharmony_ci * access to all of memory. Fix up DMA bitmask here. 74462306a36Sopenharmony_ci */ 74562306a36Sopenharmony_ci z->dev.coherent_dma_mask = DMA_BIT_MASK(32); 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci /* 74962306a36Sopenharmony_ci * If Zorro III and ID matches Fastlane, our device table entry 75062306a36Sopenharmony_ci * contains data for the Blizzard 1230 II board which does share the 75162306a36Sopenharmony_ci * same ID. Fix up device table entry here. 75262306a36Sopenharmony_ci * TODO: Some Cyberstom060 boards also share this ID but would need 75362306a36Sopenharmony_ci * to use the Cyberstorm I driver data ... we catch this by checking 75462306a36Sopenharmony_ci * for presence of ESP chip later, but don't try to fix up yet. 75562306a36Sopenharmony_ci */ 75662306a36Sopenharmony_ci if (zep->zorro3 && ent->driver_data == ZORRO_BLZ1230II) { 75762306a36Sopenharmony_ci pr_info("%s at address 0x%lx is Fastlane Z3, fixing data!\n", 75862306a36Sopenharmony_ci zdd->name, board); 75962306a36Sopenharmony_ci zdd = &zorro_esp_boards[ZORRO_FASTLANE]; 76062306a36Sopenharmony_ci } 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci if (zdd->absolute) { 76362306a36Sopenharmony_ci ioaddr = zdd->offset; 76462306a36Sopenharmony_ci dmaaddr = zdd->dma_offset; 76562306a36Sopenharmony_ci } else { 76662306a36Sopenharmony_ci ioaddr = board + zdd->offset; 76762306a36Sopenharmony_ci dmaaddr = board + zdd->dma_offset; 76862306a36Sopenharmony_ci } 76962306a36Sopenharmony_ci 77062306a36Sopenharmony_ci if (!zorro_request_device(z, zdd->name)) { 77162306a36Sopenharmony_ci pr_err("cannot reserve region 0x%lx, abort\n", 77262306a36Sopenharmony_ci board); 77362306a36Sopenharmony_ci err = -EBUSY; 77462306a36Sopenharmony_ci goto fail_free_zep; 77562306a36Sopenharmony_ci } 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci host = scsi_host_alloc(tpnt, sizeof(struct esp)); 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci if (!host) { 78062306a36Sopenharmony_ci pr_err("No host detected; board configuration problem?\n"); 78162306a36Sopenharmony_ci err = -ENOMEM; 78262306a36Sopenharmony_ci goto fail_release_device; 78362306a36Sopenharmony_ci } 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci host->base = ioaddr; 78662306a36Sopenharmony_ci host->this_id = 7; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci esp = shost_priv(host); 78962306a36Sopenharmony_ci esp->host = host; 79062306a36Sopenharmony_ci esp->dev = &z->dev; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci esp->scsi_id = host->this_id; 79362306a36Sopenharmony_ci esp->scsi_id_mask = (1 << esp->scsi_id); 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci esp->cfreq = 40000000; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci zep->esp = esp; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci dev_set_drvdata(esp->dev, zep); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci /* additional setup required for Fastlane */ 80262306a36Sopenharmony_ci if (zep->zorro3 && ent->driver_data == ZORRO_BLZ1230II) { 80362306a36Sopenharmony_ci /* map full address space up to ESP base for DMA */ 80462306a36Sopenharmony_ci zep->board_base = ioremap(board, FASTLANE_ESP_ADDR - 1); 80562306a36Sopenharmony_ci if (!zep->board_base) { 80662306a36Sopenharmony_ci pr_err("Cannot allocate board address space\n"); 80762306a36Sopenharmony_ci err = -ENOMEM; 80862306a36Sopenharmony_ci goto fail_free_host; 80962306a36Sopenharmony_ci } 81062306a36Sopenharmony_ci /* initialize DMA control shadow register */ 81162306a36Sopenharmony_ci zep->ctrl_data = (FASTLANE_DMA_FCODE | 81262306a36Sopenharmony_ci FASTLANE_DMA_EDI | FASTLANE_DMA_ESI); 81362306a36Sopenharmony_ci } 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_ci esp->ops = zdd->esp_ops; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci if (ioaddr > 0xffffff) 81862306a36Sopenharmony_ci esp->regs = ioremap(ioaddr, 0x20); 81962306a36Sopenharmony_ci else 82062306a36Sopenharmony_ci /* ZorroII address space remapped nocache by early startup */ 82162306a36Sopenharmony_ci esp->regs = ZTWO_VADDR(ioaddr); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci if (!esp->regs) { 82462306a36Sopenharmony_ci err = -ENOMEM; 82562306a36Sopenharmony_ci goto fail_unmap_fastlane; 82662306a36Sopenharmony_ci } 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci esp->fifo_reg = esp->regs + ESP_FDATA * 4; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci /* Check whether a Blizzard 12x0 or CyberstormII really has SCSI */ 83162306a36Sopenharmony_ci if (zdd->scsi_option) { 83262306a36Sopenharmony_ci zorro_esp_write8(esp, (ESP_CONFIG1_PENABLE | 7), ESP_CFG1); 83362306a36Sopenharmony_ci if (zorro_esp_read8(esp, ESP_CFG1) != (ESP_CONFIG1_PENABLE|7)) { 83462306a36Sopenharmony_ci err = -ENODEV; 83562306a36Sopenharmony_ci goto fail_unmap_regs; 83662306a36Sopenharmony_ci } 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci if (zep->zorro3) { 84062306a36Sopenharmony_ci /* 84162306a36Sopenharmony_ci * Only Fastlane Z3 for now - add switch for correct struct 84262306a36Sopenharmony_ci * dma_registers size if adding any more 84362306a36Sopenharmony_ci */ 84462306a36Sopenharmony_ci esp->dma_regs = ioremap(dmaaddr, 84562306a36Sopenharmony_ci sizeof(struct fastlane_dma_registers)); 84662306a36Sopenharmony_ci } else 84762306a36Sopenharmony_ci /* ZorroII address space remapped nocache by early startup */ 84862306a36Sopenharmony_ci esp->dma_regs = ZTWO_VADDR(dmaaddr); 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci if (!esp->dma_regs) { 85162306a36Sopenharmony_ci err = -ENOMEM; 85262306a36Sopenharmony_ci goto fail_unmap_regs; 85362306a36Sopenharmony_ci } 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci esp->command_block = dma_alloc_coherent(esp->dev, 16, 85662306a36Sopenharmony_ci &esp->command_block_dma, 85762306a36Sopenharmony_ci GFP_KERNEL); 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci if (!esp->command_block) { 86062306a36Sopenharmony_ci err = -ENOMEM; 86162306a36Sopenharmony_ci goto fail_unmap_dma_regs; 86262306a36Sopenharmony_ci } 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci host->irq = IRQ_AMIGA_PORTS; 86562306a36Sopenharmony_ci err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, 86662306a36Sopenharmony_ci "Amiga Zorro ESP", esp); 86762306a36Sopenharmony_ci if (err < 0) { 86862306a36Sopenharmony_ci err = -ENODEV; 86962306a36Sopenharmony_ci goto fail_free_command_block; 87062306a36Sopenharmony_ci } 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci /* register the chip */ 87362306a36Sopenharmony_ci err = scsi_esp_register(esp); 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci if (err) { 87662306a36Sopenharmony_ci err = -ENOMEM; 87762306a36Sopenharmony_ci goto fail_free_irq; 87862306a36Sopenharmony_ci } 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci return 0; 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_cifail_free_irq: 88362306a36Sopenharmony_ci free_irq(host->irq, esp); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_cifail_free_command_block: 88662306a36Sopenharmony_ci dma_free_coherent(esp->dev, 16, 88762306a36Sopenharmony_ci esp->command_block, 88862306a36Sopenharmony_ci esp->command_block_dma); 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_cifail_unmap_dma_regs: 89162306a36Sopenharmony_ci if (zep->zorro3) 89262306a36Sopenharmony_ci iounmap(esp->dma_regs); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_cifail_unmap_regs: 89562306a36Sopenharmony_ci if (ioaddr > 0xffffff) 89662306a36Sopenharmony_ci iounmap(esp->regs); 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_cifail_unmap_fastlane: 89962306a36Sopenharmony_ci if (zep->zorro3) 90062306a36Sopenharmony_ci iounmap(zep->board_base); 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_cifail_free_host: 90362306a36Sopenharmony_ci scsi_host_put(host); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_cifail_release_device: 90662306a36Sopenharmony_ci zorro_release_device(z); 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_cifail_free_zep: 90962306a36Sopenharmony_ci kfree(zep); 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci return err; 91262306a36Sopenharmony_ci} 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_cistatic void zorro_esp_remove(struct zorro_dev *z) 91562306a36Sopenharmony_ci{ 91662306a36Sopenharmony_ci struct zorro_esp_priv *zep = dev_get_drvdata(&z->dev); 91762306a36Sopenharmony_ci struct esp *esp = zep->esp; 91862306a36Sopenharmony_ci struct Scsi_Host *host = esp->host; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci scsi_esp_unregister(esp); 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci free_irq(host->irq, esp); 92362306a36Sopenharmony_ci dma_free_coherent(esp->dev, 16, 92462306a36Sopenharmony_ci esp->command_block, 92562306a36Sopenharmony_ci esp->command_block_dma); 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci if (zep->zorro3) { 92862306a36Sopenharmony_ci iounmap(zep->board_base); 92962306a36Sopenharmony_ci iounmap(esp->dma_regs); 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci if (host->base > 0xffffff) 93362306a36Sopenharmony_ci iounmap(esp->regs); 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci scsi_host_put(host); 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci zorro_release_device(z); 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci kfree(zep); 94062306a36Sopenharmony_ci} 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_cistatic struct zorro_driver zorro_esp_driver = { 94362306a36Sopenharmony_ci .name = KBUILD_MODNAME, 94462306a36Sopenharmony_ci .id_table = zorro_esp_zorro_tbl, 94562306a36Sopenharmony_ci .probe = zorro_esp_probe, 94662306a36Sopenharmony_ci .remove = zorro_esp_remove, 94762306a36Sopenharmony_ci}; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_cistatic int __init zorro_esp_scsi_init(void) 95062306a36Sopenharmony_ci{ 95162306a36Sopenharmony_ci return zorro_register_driver(&zorro_esp_driver); 95262306a36Sopenharmony_ci} 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_cistatic void __exit zorro_esp_scsi_exit(void) 95562306a36Sopenharmony_ci{ 95662306a36Sopenharmony_ci zorro_unregister_driver(&zorro_esp_driver); 95762306a36Sopenharmony_ci} 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_cimodule_init(zorro_esp_scsi_init); 96062306a36Sopenharmony_cimodule_exit(zorro_esp_scsi_exit); 961