Hi Tuomas, oddly enough, it does. How embarrassing... Hope I got the names of the boards right this time. Thanks for spotting this! Cheers, Michael Am 14.03.2018 um 20:13 schrieb Vainikka Tuomas: > The config description lists 53c700 devices, not ESP devices? > > -Tuomas > ________________________________________ > From: linux-m68k-owner@xxxxxxxxxxxxxxx <linux-m68k-owner@xxxxxxxxxxxxxxx> on behalf of Michael Schmitz <schmitzmic@xxxxxxxxx> > Sent: 12 March 2018 09:26:40 > To: linux-scsi@xxxxxxxxxxxxxxx > Cc: linux-m68k@xxxxxxxxxxxxxxx; davem@xxxxxxxxxxxxx; geert@xxxxxxxxxxxxxx; fthain@xxxxxxxxxxxxxxxxxxx; Michael Schmitz; Michael Schmitz > Subject: [PATCH v3] m68k/amiga - Amiga Zorro NCR53C9x boards: new zorro_esp.c > > From: Michael Schmitz <schmitz@xxxxxxxxxx> > > New combined SCSI driver for all ESP based Zorro SCSI boards for > m68k Amiga. > > Code largely based on board specific parts of the old drivers (blz1230.c, > blz2060.c, cyberstorm.c, cyberstormII.c, fastlane.c which were removed > after the 2.6 kernel series for lack of maintenance) with contributions > by Tuomas Vainikka (TCQ bug tests and workaround) and Finn Thain (TCQ > bugfix by use of PIO in extended message in transfer). > > New Kconfig option and Makefile entries for new Amiga Zorro ESP SCSI > driver included in this patch. > > Use DMA transfers wherever possible, with board-specific DMA set-up > functions copied from the old driver code. Three byte reselection messages > do appear to cause DMA timeouts. So wire up a PIO transfer routine for > these instead. > > PIO code taken from mac_esp.c where the reselection timeout issue was > debugged and fixed first, with the following modifications: > > esp_reselect_with_tag explicitly sets esp->cmd_block_dma as target address > for the message bytes. Fixup to use kernel virtual address esp->cmd_block > in PIO transfer if DMA address is esp->cmd_block_dma. > > Signed-off-by: Michael Schmitz <schmitzmic@xxxxxxxxx> > > --- > > Changes since v1: > > Fixed issues raised by Finn Thain in initial code review: > > - use KBUILD_MODNAME for driver name string. > - use pr_fmt() for pr_* format prefix. > - clean up DMA error reporting: clear error flag before each DMA > operation, set error flag on PIO error. Don't test phase in dma_err hook. > - change confusing comment about semantics of read flag, add comments > indicating DMA direction to DMA setup hooks. > - drop spurious braces around switch clauses. > - lift cfreq setting out of ID switch clauses. > - fix indentation. > - fix error codes on probe fail. > - drop check for board ID when unmapping DMA regs in error handling: > the ioaddr > 0xffffff test already catches all cases where the DMA > registers were ioremapped. > - dynamically alloc zorro_private_data. > - fix use of driver_data field (don't mix host and zorro_esp_priv > pointers). Note: require esp pointer in zorro_esp_priv to find host > pointer! > - back out phase bits changes to pio_cmd !write branch introduced > to cope with ESP SELAS command. We don't use that code so keep > it in sync with Finn's version. > - use esp_ops.dma_length_limit() to limit transfer size. After review > of old driver code, use 0xffffff max transfer size throughout. > > Fixed issues raised by Geert Uytterhoven: > > - dynamically alloc zorro_private_data, store as device drvdata. > - store ctrl_data for CyberStormI in driver private data. > - use dma_sync_single_for_device() instead of cache_push/clear. > - handle case of duplicate board identity - check whether board is > Zorro III or Zorro II (use ROM resource data for this). Also fix > up DMA mask for Zorro II boards to 32 bits (these are really CPU > expansion slot boards). > - remove zorro3 field from driver_data struct (now in private data). > - add braces around ambiguous if - else construct. > - use named structs instead of array for board config data. > - use scsi_option driver data flag for boards with optional ESP. > > Other improvements and bugfixes > > - fix Zorro device table error (duplicate ID used, also raised > by Kars de Jong). > - error code fixup in error handling path. > - add separate DMA setup for Blizzard 1230 II board. > - add support for Cyberstorm II board. > - add register structs and DMA setup for Zorro III Fastlane board, > following logic from old fastlane.c driver. Wire up Fastlane DMA > and interrupt status routines, map the necessary low 24 bit board > address space used for DMA target address setting. Clean up DMA > register space ioremap() branch for Zorro III boards (currently > Fastlane only) to end confusion about what to do in error recovery. > - use esp_ops.fastlane_esp_dma_invalidate() on Fastlane (and skip > fastlane_esp_reset_dma() in DMA setup). > - credit Tuomas Vainikka for contributing Blizzard 1230 code (and > testing). > - clarify comment about unsupported Oktagon SCSI board. > - remove unused const definitions carried over from old driver. > > Changes since v2: > > Issues raised by Finn Thain: > > - add SPDX-License-Identifier. > - remove unused ratelimit.h. > - drop phys_to_virt() in PIO transfer routine, after ensuring PIO is only > used for message in transfers to esp->command_block. This obviates any > need for finding the virtual address corresponding to a DMA handle. > - drop BUG_ON(!(cmd & ESP_CMD_DMA)) assertion in DMA setup. Short of changes > to the core ESP driver, this can never trigger. > - make ioremap() of DMA address range conditional on zep->zorro3 and use > that same condition to unmap in error handling and driver exit. > Omit board ID test as we only support a single Zorro III board, and add > comment on what to do when adding support for more boards. > - free driver private data in driver exit. > - various whitespace related cleanup. > > --- > drivers/scsi/Kconfig | 16 + > drivers/scsi/Makefile | 1 + > drivers/scsi/zorro_esp.c | 1136 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 1153 insertions(+), 0 deletions(-) > create mode 100644 drivers/scsi/zorro_esp.c > > diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig > index 8a739b7..c7d337f 100644 > --- a/drivers/scsi/Kconfig > +++ b/drivers/scsi/Kconfig > @@ -1462,6 +1462,22 @@ config SCSI_ZORRO7XX > accelerator card for the Amiga 1200, > - the SCSI controller on the GVP Turbo 040/060 accelerator. > > +config SCSI_ZORRO_ESP > + tristate "Zorro ESP SCSI support" > + depends on ZORRO && SCSI > + select SCSI_SPI_ATTRS > + help > + Support for various ESP-based SCSI controllers on Zorro > + expansion boards for the Amiga. > + This includes: > + - the Amiga 4091 Zorro III SCSI-2 controller, > + - the MacroSystem Development's WarpEngine Amiga SCSI-2 controller > + (info at > + <http://www.lysator.liu.se/amiga/ar/guide/ar310.guide?FEATURE5>), > + - the SCSI controller on the Phase5 Blizzard PowerUP 603e+ > + accelerator card for the Amiga 1200, > + - the SCSI controller on the GVP Turbo 040/060 accelerator. > + > config ATARI_SCSI > tristate "Atari native SCSI support" > depends on ATARI && SCSI > diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile > index fcfd28d..6f13c03 100644 > --- a/drivers/scsi/Makefile > +++ b/drivers/scsi/Makefile > @@ -48,6 +48,7 @@ obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o > obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o > obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o > obj-$(CONFIG_SCSI_ZORRO7XX) += 53c700.o zorro7xx.o > +obj-$(CONFIG_SCSI_ZORRO_ESP) += esp_scsi.o zorro_esp.o > obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o > obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o > obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o > diff --git a/drivers/scsi/zorro_esp.c b/drivers/scsi/zorro_esp.c > new file mode 100644 > index 0000000..47053d1 > --- /dev/null > +++ b/drivers/scsi/zorro_esp.c > @@ -0,0 +1,1136 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* zorro_esp.c: ESP front-end for Amiga ZORRO SCSI systems. > + * > + * Copyright (C) 1996 Jesper Skov (jskov@xxxxxxxxxxxx) > + * > + * Copyright (C) 2011,2018 Michael Schmitz (schmitz@xxxxxxxxxx) for > + * migration to ESP SCSI core > + * > + * Copyright (C) 2013 Tuomas Vainikka (tuomas.vainikka@xxxxxxxx) for > + * Blizzard 1230 DMA and probe function fixes > + * > + * Copyright (C) 2017 Finn Thain for PIO code from Mac ESP driver adapted here > + */ > +/* > + * ZORRO bus code from: > + */ > +/* > + * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux. > + * Amiga MacroSystemUS WarpEngine SCSI controller. > + * Amiga Technologies/DKB A4091 SCSI controller. > + * > + * Written 1997 by Alan Hourihane <alanh@xxxxxxxxxxxxxxxxxxxx> > + * plus modifications of the 53c7xx.c driver to support the Amiga. > + * > + * Rewritten to use 53c700.c by Kars de Jong <jongk@xxxxxxxxxxxxxx> > + */ > + > +#define KBUILD_MODNAME "zorro_esp" > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt > + > +#include <linux/module.h> > +#include <linux/init.h> > +#include <linux/interrupt.h> > +#include <linux/dma-mapping.h> > +#include <linux/scatterlist.h> > +#include <linux/delay.h> > +#include <linux/zorro.h> > +#include <linux/slab.h> > + > +#include <asm/page.h> > +#include <asm/pgtable.h> > +#include <asm/cacheflush.h> > +#include <asm/amigahw.h> > +#include <asm/amigaints.h> > + > +#include <scsi/scsi_host.h> > +#include <scsi/scsi_transport_spi.h> > +#include <scsi/scsi_device.h> > +#include <scsi/scsi_tcq.h> > + > +#include "esp_scsi.h" > + > +MODULE_AUTHOR("Michael Schmitz <schmitz@xxxxxxxxxx>"); > +MODULE_DESCRIPTION("Amiga Zorro NCR5C9x (ESP) driver"); > +MODULE_LICENSE("GPL"); > + > +struct zorro_driver_data { > + const char *name; > + unsigned long offset; > + unsigned long dma_offset; > + int absolute; /* offset is absolute address */ > + int scsi_option; > +}; > + > +static struct zorro_driver_data cyberstormI_data = { > + .name = "CyberStormI", > + .offset = 0xf400, > + .dma_offset = 0xf800, > + .absolute = 0, > + .scsi_option = 0, > +}; > + > +static struct zorro_driver_data cyberstormII_data = { > + .name = "CyberStormII", > + .offset = 0x1ff03, > + .dma_offset = 0x1ff43, > + .absolute = 0, > + .scsi_option = 1, > +}; > + > +static struct zorro_driver_data blizzard2060_data = { > + .name = "Blizzard 2060", > + .offset = 0x1ff00, > + .dma_offset = 0x1ffe0, > + .absolute = 0, > + .scsi_option = 0, > +}; > + > +static struct zorro_driver_data blizzard1230_data = { > + .name = "Blizzard 1230", > + .offset = 0x8000, > + .dma_offset = 0x10000, > + .absolute = 0, > + .scsi_option = 1, > +}; > + > +static struct zorro_driver_data blizzard1230II_data = { > + .name = "Blizzard 1230II", > + .offset = 0x10000, > + .dma_offset = 0x10021, > + .absolute = 0, > + .scsi_option = 1, > +}; > + > +static struct zorro_driver_data fastlanez3_data = { > + .name = "Fastlane", > + .offset = 0x1000001, > + .dma_offset = 0x1000041, > + .absolute = 0, > + .scsi_option = 0, > +}; > + > +static struct zorro_device_id zorro_esp_zorro_tbl[] = { > + { > + .id = ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM, > + .driver_data = (unsigned long)&cyberstormI_data, > + }, > + { > + .id = ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, > + .driver_data = (unsigned long)&cyberstormII_data, > + }, > + { > + .id = ZORRO_PROD_PHASE5_BLIZZARD_2060, > + .driver_data = (unsigned long)&blizzard2060_data, > + }, > + { > + .id = ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260, > + .driver_data = (unsigned long)&blizzard1230_data, > + }, > + { > + .id = ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, > + .driver_data = (unsigned long)&blizzard1230II_data, > + }, > + { 0 } > +}; > +MODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl); > + > +/* Blizzard 1230 DMA interface */ > + > +struct blz1230_dma_registers { > + volatile unsigned char dma_addr; /* DMA address [0x0000] */ > + unsigned char dmapad2[0x7fff]; > + volatile unsigned char dma_latch; /* DMA latch [0x8000] */ > +}; > + > +/* Blizzard 1230II DMA interface */ > + > +struct blz1230II_dma_registers { > + volatile unsigned char dma_addr; /* DMA address [0x0000] */ > + unsigned char dmapad2[0xf]; > + volatile unsigned char dma_latch; /* DMA latch [0x0010] */ > +}; > + > +/* Blizzard 2060 DMA interface */ > + > +struct blz2060_dma_registers { > + volatile unsigned char dma_led_ctrl; /* DMA led control [0x000] */ > + unsigned char dmapad1[0x0f]; > + volatile unsigned char dma_addr0; /* DMA address (MSB) [0x010] */ > + unsigned char dmapad2[0x03]; > + volatile unsigned char dma_addr1; /* DMA address [0x014] */ > + unsigned char dmapad3[0x03]; > + volatile unsigned char dma_addr2; /* DMA address [0x018] */ > + unsigned char dmapad4[0x03]; > + volatile unsigned char dma_addr3; /* DMA address (LSB) [0x01c] */ > +}; > + > +/* DMA control bits */ > +#define DMA_WRITE 0x80000000 > + > +/* Cyberstorm DMA interface */ > + > +struct cyber_dma_registers { > + volatile unsigned char dma_addr0; /* DMA address (MSB) [0x000] */ > + unsigned char dmapad1[1]; > + volatile unsigned char dma_addr1; /* DMA address [0x002] */ > + unsigned char dmapad2[1]; > + volatile unsigned char dma_addr2; /* DMA address [0x004] */ > + unsigned char dmapad3[1]; > + volatile unsigned char dma_addr3; /* DMA address (LSB) [0x006] */ > + unsigned char dmapad4[0x3fb]; > + volatile unsigned char cond_reg; /* DMA cond (ro) [0x402] */ > +#define ctrl_reg cond_reg /* DMA control (wo) [0x402] */ > +}; > + > +/* DMA control bits */ > +#define CYBER_DMA_WRITE 0x40 /* DMA direction. 1 = write */ > +#define CYBER_DMA_Z3 0x20 /* 16 (Z2) or 32 (CHIP/Z3) bit DMA transfer */ > + > +/* DMA status bits */ > +#define CYBER_DMA_HNDL_INTR 0x80 /* DMA IRQ pending? */ > + > +/* The CyberStorm II DMA interface */ > +struct cyberII_dma_registers { > + volatile unsigned char cond_reg; /* DMA cond (ro) [0x000] */ > +#define ctrl_reg cond_reg /* DMA control (wo) [0x000] */ > + unsigned char dmapad4[0x3f]; > + volatile unsigned char dma_addr0; /* DMA address (MSB) [0x040] */ > + unsigned char dmapad1[3]; > + volatile unsigned char dma_addr1; /* DMA address [0x044] */ > + unsigned char dmapad2[3]; > + volatile unsigned char dma_addr2; /* DMA address [0x048] */ > + unsigned char dmapad3[3]; > + volatile unsigned char dma_addr3; /* DMA address (LSB) [0x04c] */ > +}; > + > +/* Fastlane DMA interface */ > + > +struct fastlane_dma_registers { > + volatile unsigned char cond_reg; /* DMA status (ro) [0x0000] */ > +#define ctrl_reg cond_reg /* DMA control (wo) [0x0000] */ > + unsigned char dmapad1[0x3f]; > + volatile unsigned char clear_strobe; /* DMA clear (wo) [0x0040] */ > +}; > + > +/* The controller registers can be found in the Z2 config area at these > + * offsets: > + */ > +#define FASTLANE_ESP_ADDR 0x1000001 > + > +/* DMA status bits */ > +#define FASTLANE_DMA_MINT 0x80 > +#define FASTLANE_DMA_IACT 0x40 > +#define FASTLANE_DMA_CREQ 0x20 > + > +/* DMA control bits */ > +#define FASTLANE_DMA_FCODE 0xa0 > +#define FASTLANE_DMA_MASK 0xf3 > +#define FASTLANE_DMA_WRITE 0x08 /* 1 = write */ > +#define FASTLANE_DMA_ENABLE 0x04 /* Enable DMA */ > +#define FASTLANE_DMA_EDI 0x02 /* Enable DMA IRQ ? */ > +#define FASTLANE_DMA_ESI 0x01 /* Enable SCSI IRQ */ > + > +/* > + * private data used for driver > + */ > +struct zorro_esp_priv { > + struct esp *esp; /* our ESP instance - for Scsi_host* */ > + unsigned long *board_base; /* virtual address (Zorro III board) */ > + int error; /* PIO error flag */ > + int zorro3; /* board is Zorro III */ > + unsigned char ctrl_data; /* shadow copy of ctrl_reg */ > +}; > + > +#define ZORRO_ESP_GET_PRIV(esp) ((struct zorro_esp_priv *) \ > + dev_get_drvdata(esp->dev)) > + > +/* > + * On all implementations except for the Oktagon, padding between ESP > + * registers is three bytes. > + * On Oktagon, it is one byte - use a different accessor there. > + * > + * Oktagon needs PDMA - currently unsupported! > + */ > + > +static void zorro_esp_write8(struct esp *esp, u8 val, unsigned long reg) > +{ > + writeb(val, esp->regs + (reg * 4UL)); > +} > + > +static u8 zorro_esp_read8(struct esp *esp, unsigned long reg) > +{ > + return readb(esp->regs + (reg * 4UL)); > +} > + > +static dma_addr_t zorro_esp_map_single(struct esp *esp, void *buf, > + size_t sz, int dir) > +{ > + return dma_map_single(esp->dev, buf, sz, dir); > +} > + > +static int zorro_esp_map_sg(struct esp *esp, struct scatterlist *sg, > + int num_sg, int dir) > +{ > + return dma_map_sg(esp->dev, sg, num_sg, dir); > +} > + > +static void zorro_esp_unmap_single(struct esp *esp, dma_addr_t addr, > + size_t sz, int dir) > +{ > + dma_unmap_single(esp->dev, addr, sz, dir); > +} > + > +static void zorro_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, > + int num_sg, int dir) > +{ > + dma_unmap_sg(esp->dev, sg, num_sg, dir); > +} > + > +static int zorro_esp_irq_pending(struct esp *esp) > +{ > + /* check ESP status register; DMA has no status reg. */ > + > + if (zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR) > + return 1; > + > + return 0; > +} > + > +static int cyber_esp_irq_pending(struct esp *esp) > +{ > + /* It's important to check the DMA IRQ bit in the correct way! */ > + return ((zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR) && > + ((((struct cyber_dma_registers *)(esp->dma_regs))->cond_reg) & > + CYBER_DMA_HNDL_INTR)); > + return 0; > +} > + > +static int fastlane_esp_irq_pending(struct esp *esp) > +{ > + struct fastlane_dma_registers *dregs = > + (struct fastlane_dma_registers *) (esp->dma_regs); > + unsigned char dma_status; > + > + dma_status = dregs->cond_reg; > + > + if (dma_status & FASTLANE_DMA_IACT) > + return 0; /* not our IRQ */ > + > + /* Return non-zero if ESP requested IRQ */ > + return ( > + (dma_status & FASTLANE_DMA_CREQ) && > + (!(dma_status & FASTLANE_DMA_MINT)) && > + (zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)); > +} > + > +static u32 zorro_esp_dma_length_limit(struct esp *esp, u32 dma_addr, > + u32 dma_len) > +{ > + return dma_len > 0xFFFFFF ? 0xFFFFFF : dma_len; > +} > + > +static void zorro_esp_reset_dma(struct esp *esp) > +{ > + /* nothing to do here */ > +} > + > +static void zorro_esp_dma_drain(struct esp *esp) > +{ > + /* nothing to do here */ > +} > + > +static void zorro_esp_dma_invalidate(struct esp *esp) > +{ > + /* nothing to do here */ > +} > + > +static void fastlane_esp_dma_invalidate(struct esp *esp) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + struct fastlane_dma_registers *dregs = > + (struct fastlane_dma_registers *) (esp->dma_regs); > + unsigned char *ctrl_data = &zep->ctrl_data; > + unsigned long *t; > + > + *ctrl_data = (*ctrl_data & FASTLANE_DMA_MASK); > + dregs->ctrl_reg = *ctrl_data; > + > + t = (unsigned long *)(zep->board_base); > + > + dregs->clear_strobe = 0; > + *t = 0; > +} > + > +/* > + * Programmed IO routines follow. > + */ > + > +static inline unsigned int zorro_esp_wait_for_fifo(struct esp *esp) > +{ > + int i = 500000; > + > + do { > + unsigned int fbytes = zorro_esp_read8(esp, ESP_FFLAGS) > + & ESP_FF_FBYTES; > + > + if (fbytes) > + return fbytes; > + > + udelay(2); > + } while (--i); > + > + pr_err("FIFO is empty (sreg %02x)\n", > + zorro_esp_read8(esp, ESP_STATUS)); > + return 0; > +} > + > +static inline int zorro_esp_wait_for_intr(struct esp *esp) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + int i = 500000; > + > + do { > + esp->sreg = zorro_esp_read8(esp, ESP_STATUS); > + if (esp->sreg & ESP_STAT_INTR) > + return 0; > + > + udelay(2); > + } while (--i); > + > + pr_err("IRQ timeout (sreg %02x)\n", esp->sreg); > + zep->error = 1; > + return 1; > +} > + > +#define ZORRO_ESP_PIO_LOOP(operands, reg1) \ > + { \ > + asm volatile ( \ > + "1: moveb " operands "\n" \ > + " subqw #1,%1 \n" \ > + " jbne 1b \n" \ > + : "+a" (addr), "+r" (reg1) \ > + : "a" (fifo)); \ > + } > + > +#define ZORRO_ESP_PIO_FILL(operands, reg1) \ > + { \ > + asm volatile ( \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " moveb " operands "\n" \ > + " subqw #8,%1 \n" \ > + " subqw #8,%1 \n" \ > + : "+a" (addr), "+r" (reg1) \ > + : "a" (fifo)); \ > + } > + > +#define ZORRO_ESP_FIFO_SIZE 16 > + > +static void zorro_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, > + u32 dma_count, int write, u8 cmd) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + u8 __iomem *fifo = esp->regs + ESP_FDATA * 16; > + u8 phase = esp->sreg & ESP_STAT_PMASK; > + > + cmd &= ~ESP_CMD_DMA; > + > + /* We are passed DMA addresses i.e. physical addresses, but must use > + * kernel virtual addresses here, so convert to virtual. This is easy > + * enough for the case of residual bytes of an extended message in > + * transfer - we know the address must be esp->command_block_dma. > + * In other cases, more work is needed to find a mapping. > + * Sidestep the issue by making sure we only end up here when using > + * esp->command_block as transfer buffer. > + */ > + if (addr == esp->command_block_dma) > + addr = (u32) esp->command_block; > + > + if (write) { > + u8 *dst = (u8 *)addr; > + u8 mask = ~(phase == ESP_MIP ? ESP_INTR_FDONE : ESP_INTR_BSERV); > + > + scsi_esp_cmd(esp, cmd); > + > + while (1) { > + if (!zorro_esp_wait_for_fifo(esp)) > + break; > + > + *dst++ = zorro_esp_read8(esp, ESP_FDATA); > + --esp_count; > + > + if (!esp_count) > + break; > + > + if (zorro_esp_wait_for_intr(esp)) > + break; > + > + if ((esp->sreg & ESP_STAT_PMASK) != phase) > + break; > + > + esp->ireg = zorro_esp_read8(esp, ESP_INTRPT); > + if (esp->ireg & mask) { > + zep->error = 1; > + break; > + } > + > + if (phase == ESP_MIP) > + scsi_esp_cmd(esp, ESP_CMD_MOK); > + > + scsi_esp_cmd(esp, ESP_CMD_TI); > + } > + } else { /* unused, as long as we only handle MIP here */ > + scsi_esp_cmd(esp, ESP_CMD_FLUSH); > + > + if (esp_count >= ZORRO_ESP_FIFO_SIZE) { > + ZORRO_ESP_PIO_FILL("%0@+,%2@", esp_count); > + } else > + ZORRO_ESP_PIO_LOOP("%0@+,%2@", esp_count); > + > + scsi_esp_cmd(esp, cmd); > + > + while (esp_count) { > + unsigned int n; > + > + if (zorro_esp_wait_for_intr(esp)) > + break; > + > + if ((esp->sreg & ESP_STAT_PMASK) != phase) > + break; > + > + esp->ireg = zorro_esp_read8(esp, ESP_INTRPT); > + if (esp->ireg & ~ESP_INTR_BSERV) { > + zep->error = 1; > + break; > + } > + > + n = ZORRO_ESP_FIFO_SIZE - > + (zorro_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES); > + if (n > esp_count) > + n = esp_count; > + > + if (n == ZORRO_ESP_FIFO_SIZE) { > + ZORRO_ESP_PIO_FILL("%0@+,%2@", esp_count); > + } else { > + esp_count -= n; > + ZORRO_ESP_PIO_LOOP("%0@+,%2@", n); > + } > + > + scsi_esp_cmd(esp, ESP_CMD_TI); > + } > + } > +} > + > +// Blizzard 1230/60 SCSI-IV DMA > + > +static void zorro_esp_send_blz1230_dma_cmd(struct esp *esp, u32 addr, > + u32 esp_count, u32 dma_count, int write, u8 cmd) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + struct blz1230_dma_registers *dregs = > + (struct blz1230_dma_registers *) (esp->dma_regs); > + u8 phase = esp->sreg & ESP_STAT_PMASK; > + > + zep->error = 0; > + /* Use PIO if transferring message bytes to esp->command_block_dma */ > + if (phase == ESP_MIP && addr == esp->command_block_dma) { > + zorro_esp_send_pio_cmd(esp, addr, esp_count, > + dma_count, write, cmd); > + return; > + } > + > + if (write) > + /* DMA receive */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_FROM_DEVICE); > + else > + /* DMA send */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_TO_DEVICE); > + > + addr >>= 1; > + if (write) > + addr &= ~(DMA_WRITE); > + else > + addr |= DMA_WRITE; > + > + dregs->dma_latch = (addr >> 24) & 0xff; > + dregs->dma_addr = (addr >> 24) & 0xff; > + dregs->dma_addr = (addr >> 16) & 0xff; > + dregs->dma_addr = (addr >> 8) & 0xff; > + dregs->dma_addr = addr & 0xff; > + > + scsi_esp_cmd(esp, ESP_CMD_DMA); > + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); > + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); > + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI); > + > + scsi_esp_cmd(esp, cmd); > +} > + > +// Blizzard 1230-II DMA > + > +static void zorro_esp_send_blz1230II_dma_cmd(struct esp *esp, u32 addr, > + u32 esp_count, u32 dma_count, int write, u8 cmd) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + struct blz1230II_dma_registers *dregs = > + (struct blz1230II_dma_registers *) (esp->dma_regs); > + u8 phase = esp->sreg & ESP_STAT_PMASK; > + > + zep->error = 0; > + /* Use PIO if transferring message bytes to esp->command_block_dma */ > + if (phase == ESP_MIP && addr == esp->command_block_dma) { > + zorro_esp_send_pio_cmd(esp, addr, esp_count, > + dma_count, write, cmd); > + return; > + } > + > + if (write) > + /* DMA receive */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_FROM_DEVICE); > + else > + /* DMA send */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_TO_DEVICE); > + > + addr >>= 1; > + if (write) > + addr &= ~(DMA_WRITE); > + else > + addr |= DMA_WRITE; > + > + dregs->dma_latch = (addr >> 24) & 0xff; > + dregs->dma_addr = (addr >> 16) & 0xff; > + dregs->dma_addr = (addr >> 8) & 0xff; > + dregs->dma_addr = addr & 0xff; > + > + scsi_esp_cmd(esp, ESP_CMD_DMA); > + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); > + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); > + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI); > + > + scsi_esp_cmd(esp, cmd); > +} > + > +// Blizzard 2060 DMA > + > +static void zorro_esp_send_blz2060_dma_cmd(struct esp *esp, u32 addr, > + u32 esp_count, u32 dma_count, int write, u8 cmd) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + struct blz2060_dma_registers *dregs = > + (struct blz2060_dma_registers *) (esp->dma_regs); > + u8 phase = esp->sreg & ESP_STAT_PMASK; > + > + zep->error = 0; > + /* Use PIO if transferring message bytes to esp->command_block_dma */ > + if (phase == ESP_MIP && addr == esp->command_block_dma) { > + zorro_esp_send_pio_cmd(esp, addr, esp_count, > + dma_count, write, cmd); > + return; > + } > + > + if (write) > + /* DMA receive */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_FROM_DEVICE); > + else > + /* DMA send */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_TO_DEVICE); > + > + addr >>= 1; > + if (write) > + addr &= ~(DMA_WRITE); > + else > + addr |= DMA_WRITE; > + > + dregs->dma_addr3 = addr & 0xff; > + dregs->dma_addr2 = (addr >> 8) & 0xff; > + dregs->dma_addr1 = (addr >> 16) & 0xff; > + dregs->dma_addr0 = (addr >> 24) & 0xff; > + > + scsi_esp_cmd(esp, ESP_CMD_DMA); > + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); > + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); > + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI); > + > + scsi_esp_cmd(esp, cmd); > +} > + > +// Cyberstorm I DMA > + > +static void zorro_esp_send_cyber_dma_cmd(struct esp *esp, u32 addr, > + u32 esp_count, u32 dma_count, int write, u8 cmd) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + struct cyber_dma_registers *dregs = > + (struct cyber_dma_registers *) (esp->dma_regs); > + u8 phase = esp->sreg & ESP_STAT_PMASK; > + unsigned char *ctrl_data = &zep->ctrl_data; > + > + zep->error = 0; > + /* Use PIO if transferring message bytes to esp->command_block_dma */ > + if (phase == ESP_MIP && addr == esp->command_block_dma) { > + zorro_esp_send_pio_cmd(esp, addr, esp_count, > + dma_count, write, cmd); > + return; > + } > + > + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); > + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); > + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI); > + > + if (write) { > + /* DMA receive */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_FROM_DEVICE); > + addr &= ~(1); > + } else { > + /* DMA send */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_TO_DEVICE); > + addr |= 1; > + } > + > + dregs->dma_addr0 = (addr >> 24) & 0xff; > + dregs->dma_addr1 = (addr >> 16) & 0xff; > + dregs->dma_addr2 = (addr >> 8) & 0xff; > + dregs->dma_addr3 = addr & 0xff; > + > + if (write) > + *ctrl_data &= ~(CYBER_DMA_WRITE); > + else > + *ctrl_data |= CYBER_DMA_WRITE; > + > + *ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */ > + > + dregs->ctrl_reg = *ctrl_data; > + > + scsi_esp_cmd(esp, cmd); > +} > + > +// Cyberstorm II DMA > + > +static void zorro_esp_send_cyberII_dma_cmd(struct esp *esp, u32 addr, > + u32 esp_count, u32 dma_count, int write, u8 cmd) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + struct cyberII_dma_registers *dregs = > + (struct cyberII_dma_registers *) (esp->dma_regs); > + u8 phase = esp->sreg & ESP_STAT_PMASK; > + > + zep->error = 0; > + /* Use PIO if transferring message bytes to esp->command_block_dma */ > + if (phase == ESP_MIP && addr == esp->command_block_dma) { > + zorro_esp_send_pio_cmd(esp, addr, esp_count, > + dma_count, write, cmd); > + return; > + } > + > + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); > + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); > + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI); > + > + if (write) { > + /* DMA receive */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_FROM_DEVICE); > + addr &= ~(1); > + } else { > + /* DMA send */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_TO_DEVICE); > + addr |= 1; > + } > + > + dregs->dma_addr0 = (addr >> 24) & 0xff; > + dregs->dma_addr1 = (addr >> 16) & 0xff; > + dregs->dma_addr2 = (addr >> 8) & 0xff; > + dregs->dma_addr3 = addr & 0xff; > + > + scsi_esp_cmd(esp, cmd); > +} > + > +// Fastlane DMA > + > +static void zorro_esp_send_fastlane_dma_cmd(struct esp *esp, u32 addr, > + u32 esp_count, u32 dma_count, int write, u8 cmd) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + struct fastlane_dma_registers *dregs = > + (struct fastlane_dma_registers *) (esp->dma_regs); > + u8 phase = esp->sreg & ESP_STAT_PMASK; > + unsigned char *ctrl_data = &zep->ctrl_data; > + unsigned long *t; > + > + zep->error = 0; > + /* Use PIO if transferring message bytes to esp->command_block_dma */ > + if (phase == ESP_MIP && addr == esp->command_block_dma) { > + zorro_esp_send_pio_cmd(esp, addr, esp_count, > + dma_count, write, cmd); > + return; > + } > + > + zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW); > + zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED); > + zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI); > + > + if (write) { > + /* DMA receive */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_FROM_DEVICE); > + addr &= ~(1); > + } else { > + /* DMA send */ > + dma_sync_single_for_device(esp->dev, addr, esp_count, > + DMA_TO_DEVICE); > + addr |= 1; > + } > + > + t = (unsigned long *)((addr & 0x00ffffff) + zep->board_base); > + > + dregs->clear_strobe = 0; > + *t = addr; > + > + if (write) { > + *ctrl_data = (*ctrl_data & FASTLANE_DMA_MASK) | > + FASTLANE_DMA_ENABLE; > + } else { > + *ctrl_data = ((*ctrl_data & FASTLANE_DMA_MASK) | > + FASTLANE_DMA_ENABLE | > + FASTLANE_DMA_WRITE); > + } > + > + dregs->ctrl_reg = *ctrl_data; > + > + scsi_esp_cmd(esp, cmd); > +} > + > +static int zorro_esp_dma_error(struct esp *esp) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + > + /* check for error in case we've been doing PIO */ > + if (zep->error == 1) > + return 1; > + > + /* do nothing - there seems to be no way to check for DMA errors */ > + return 0; > +} > + > +static struct esp_driver_ops zorro_esp_ops = { > + .esp_write8 = zorro_esp_write8, > + .esp_read8 = zorro_esp_read8, > + .map_single = zorro_esp_map_single, > + .map_sg = zorro_esp_map_sg, > + .unmap_single = zorro_esp_unmap_single, > + .unmap_sg = zorro_esp_unmap_sg, > + .irq_pending = zorro_esp_irq_pending, > + .dma_length_limit = zorro_esp_dma_length_limit, > + .reset_dma = zorro_esp_reset_dma, > + .dma_drain = zorro_esp_dma_drain, > + .dma_invalidate = zorro_esp_dma_invalidate, > + .send_dma_cmd = zorro_esp_send_blz2060_dma_cmd, > + .dma_error = zorro_esp_dma_error, > +}; > + > +static int zorro_esp_probe(struct zorro_dev *z, > + const struct zorro_device_id *ent) > +{ > + struct scsi_host_template *tpnt = &scsi_esp_template; > + struct Scsi_Host *host; > + struct esp *esp; > + struct zorro_driver_data *zdd; > + struct zorro_esp_priv *zep; > + unsigned long board, ioaddr, dmaaddr; > + int err; > + > + board = zorro_resource_start(z); > + zdd = (struct zorro_driver_data *)ent->driver_data; > + > + pr_info("%s found at address 0x%lx.\n", zdd->name, board); > + > + zep = kmalloc(sizeof(*zep), GFP_KERNEL); > + if (!zep) { > + pr_err("Can't allocate device private data!\n"); > + return -ENOMEM; > + } > + > + /* let's figure out whether we have a Zorro II or Zorro III board */ > + if ((z->rom.er_Type & ERT_TYPEMASK) == ERT_ZORROIII) { > + /* note this is a Zorro III board */ > + if (board > 0xffffff) > + zep->zorro3 = 1; > + } else > + /* Even though most of these boards identify as Zorro II, > + * they are in fact CPU expansion slot boards and have full > + * access to all of memory. Fix up DMA bitmask here. > + */ > + z->dev.coherent_dma_mask = DMA_BIT_MASK(32); > + > + /* If Zorro III and ID matches Fastlane, our device table entry > + * contains data for the Blizzard 1230 II board which does share the > + * same ID. Fix up device table entry here. > + * TODO: Some Cyberstom060 boards also share this ID but would need > + * to use the Cyberstorm I driver data ... we catch this by checking > + * for presence of ESP chip later, but don't try to fix up yet. > + */ > + if (zep->zorro3 && ent->id == > + ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060) { > + pr_info("%s at address 0x%lx is Fastlane Z3, fixing data!\n", > + zdd->name, board); > + zdd = &fastlanez3_data; > + } > + > + if (zdd->absolute) { > + ioaddr = zdd->offset; > + dmaaddr = zdd->dma_offset; > + } else { > + ioaddr = board + zdd->offset; > + dmaaddr = board + zdd->dma_offset; > + } > + > + if (!zorro_request_device(z, zdd->name)) { > + pr_err("cannot reserve region 0x%lx, abort\n", > + board); > + err = -EBUSY; > + goto fail_free_zep; > + } > + > + /* Fill in the required pieces of hostdata */ > + > + host = scsi_host_alloc(tpnt, sizeof(struct esp)); > + > + if (!host) { > + pr_err("No host detected; board configuration problem?\n"); > + err = -ENOMEM; > + goto fail_release_device; > + } > + > + host->base = ioaddr; > + host->this_id = 7; > + > + esp = shost_priv(host); > + esp->host = host; > + esp->dev = &z->dev; > + > + esp->scsi_id = host->this_id; > + esp->scsi_id_mask = (1 << esp->scsi_id); > + > + esp->cfreq = 40000000; > + > + zep->error = 0; > + zep->esp = esp; > + > + dev_set_drvdata(esp->dev, zep); > + > + /* Switch to the correct the DMA routine and clock frequency. */ > + switch (ent->id) { > + case ZORRO_PROD_PHASE5_BLIZZARD_2060: > + zorro_esp_ops.send_dma_cmd = zorro_esp_send_blz2060_dma_cmd; > + break; > + case ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260: > + zorro_esp_ops.send_dma_cmd = zorro_esp_send_blz1230_dma_cmd; > + break; > + case ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM: > + zorro_esp_ops.send_dma_cmd = zorro_esp_send_cyber_dma_cmd; > + zorro_esp_ops.irq_pending = cyber_esp_irq_pending; > + break; > + case ZORRO_PROD_PHASE5_CYBERSTORM_MK_II: > + zorro_esp_ops.send_dma_cmd = zorro_esp_send_cyberII_dma_cmd; > + break; > + case ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060: > + if (zep->zorro3) { > + /* Fastlane Zorro III board */ > + /* map address space up to ESP address for DMA */ > + zep->board_base = ioremap_nocache(board, > + FASTLANE_ESP_ADDR-1); > + if (!zep->board_base) { > + pr_err("Cannot allocate board address space\n"); > + err = -ENOMEM; > + goto fail_free_host; > + } > + /* initialize DMA control shadow register */ > + zep->ctrl_data = (FASTLANE_DMA_FCODE | > + FASTLANE_DMA_EDI | FASTLANE_DMA_ESI); > + zorro_esp_ops.send_dma_cmd = > + zorro_esp_send_fastlane_dma_cmd; > + zorro_esp_ops.irq_pending = fastlane_esp_irq_pending; > + zorro_esp_ops.dma_invalidate = > + fastlane_esp_dma_invalidate; > + } else { > + /* Blizzard 1230 II Zorro II board */ > + zorro_esp_ops.send_dma_cmd = > + zorro_esp_send_blz1230II_dma_cmd; > + } > + break; > + default: > + /* Oh noes */ > + pr_err("Unsupported board!\n"); > + err = -ENODEV; > + goto fail_free_host; > + } > + > + esp->ops = &zorro_esp_ops; > + > + if (ioaddr > 0xffffff) > + esp->regs = ioremap_nocache(ioaddr, 0x20); > + else > + esp->regs = (void __iomem *)ZTWO_VADDR(ioaddr); > + > + if (!esp->regs) { > + err = -ENOMEM; > + goto fail_unmap_fastlane; > + } > + > + /* Check whether a Blizzard 12x0 or CyberstormII really has SCSI */ > + if (zdd->scsi_option) { > + zorro_esp_write8(esp, (ESP_CONFIG1_PENABLE | 7), ESP_CFG1); > + if (zorro_esp_read8(esp, ESP_CFG1) != (ESP_CONFIG1_PENABLE|7)) { > + err = -ENODEV; > + goto fail_unmap_regs; > + } > + } > + > + if (zep->zorro3) { > + /* Only Fastlane Z3 for now - add switch for correct struct > + * dma_registers size if adding any more > + */ > + esp->dma_regs = ioremap_nocache(dmaaddr, > + sizeof(struct fastlane_dma_registers)); > + } else > + esp->dma_regs = (void __iomem *)ZTWO_VADDR(dmaaddr); > + > + if (!esp->dma_regs) { > + err = -ENOMEM; > + goto fail_unmap_regs; > + } > + > + esp->command_block = dma_alloc_coherent(esp->dev, 16, > + &esp->command_block_dma, > + GFP_KERNEL); > + > + if (!esp->command_block) { > + err = -ENOMEM; > + goto fail_unmap_dma_regs; > + } > + > + host->irq = IRQ_AMIGA_PORTS; > + err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, > + "Amiga Zorro ESP", esp); > + if (err < 0) { > + err = -ENODEV; > + goto fail_free_command_block; > + } > + > + /* register the chip */ > + err = scsi_esp_register(esp, &z->dev); > + > + if (err) { > + err = -ENOMEM; > + goto fail_free_irq; > + } > + > + //zorro_set_drvdata(z, host); > + > + return 0; > + > +fail_free_irq: > + free_irq(host->irq, esp); > + > +fail_free_command_block: > + dma_free_coherent(esp->dev, 16, > + esp->command_block, > + esp->command_block_dma); > + > +fail_unmap_dma_regs: > + if (zep->zorro3) > + iounmap(esp->dma_regs); > + > +fail_unmap_regs: > + if (ioaddr > 0xffffff) > + iounmap(esp->regs); > + > +fail_unmap_fastlane: > + if (zep->zorro3) > + iounmap(zep->board_base); > + > +fail_free_host: > + scsi_host_put(host); > + > +fail_release_device: > + zorro_release_device(z); > + > +fail_free_zep: > + kfree(zep); > + > + return err; > +} > + > +static void zorro_esp_remove(struct zorro_dev *z) > +{ > + /* equivalent to dev_get_drvdata(z->dev) */ > + struct zorro_esp_priv *zep = zorro_get_drvdata(z); > + struct esp *esp = zep->esp; > + struct Scsi_Host *host = esp->host; > + > + scsi_esp_unregister(esp); > + > + /* Disable interrupts. Perhaps use disable_irq instead ... */ > + > + 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); > -- > 1.7.0.4 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-m68k" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html >