mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
[SCSI] remove m68k NCR53C9x based drivers
These drivers depend on the deprecated NCR53C9X core and need to be converted to the esp_scsi core. Acked-by: Boaz Harrosh <bharrosh@panasas.com> Cc: Linux/m68k <linux-m68k@vger.kernel.org> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
@@ -1578,45 +1578,6 @@ config GVP11_SCSI
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called gvp11.
|
||||
|
||||
config CYBERSTORM_SCSI
|
||||
tristate "CyberStorm SCSI support"
|
||||
depends on ZORRO && SCSI
|
||||
help
|
||||
If you have an Amiga with an original (MkI) Phase5 Cyberstorm
|
||||
accelerator board and the optional Cyberstorm SCSI controller,
|
||||
answer Y. Otherwise, say N.
|
||||
|
||||
config CYBERSTORMII_SCSI
|
||||
tristate "CyberStorm Mk II SCSI support"
|
||||
depends on ZORRO && SCSI
|
||||
help
|
||||
If you have an Amiga with a Phase5 Cyberstorm MkII accelerator board
|
||||
and the optional Cyberstorm SCSI controller, say Y. Otherwise,
|
||||
answer N.
|
||||
|
||||
config BLZ2060_SCSI
|
||||
tristate "Blizzard 2060 SCSI support"
|
||||
depends on ZORRO && SCSI
|
||||
help
|
||||
If you have an Amiga with a Phase5 Blizzard 2060 accelerator board
|
||||
and want to use the onboard SCSI controller, say Y. Otherwise,
|
||||
answer N.
|
||||
|
||||
config BLZ1230_SCSI
|
||||
tristate "Blizzard 1230IV/1260 SCSI support"
|
||||
depends on ZORRO && SCSI
|
||||
help
|
||||
If you have an Amiga 1200 with a Phase5 Blizzard 1230IV or Blizzard
|
||||
1260 accelerator, and the optional SCSI module, say Y. Otherwise,
|
||||
say N.
|
||||
|
||||
config FASTLANE_SCSI
|
||||
tristate "Fastlane SCSI support"
|
||||
depends on ZORRO && SCSI
|
||||
help
|
||||
If you have the Phase5 Fastlane Z3 SCSI controller, or plan to use
|
||||
one in the near future, say Y to this question. Otherwise, say N.
|
||||
|
||||
config SCSI_A4000T
|
||||
tristate "A4000T NCR53c710 SCSI support (EXPERIMENTAL)"
|
||||
depends on AMIGA && SCSI && EXPERIMENTAL
|
||||
@@ -1644,15 +1605,6 @@ config SCSI_ZORRO7XX
|
||||
accelerator card for the Amiga 1200,
|
||||
- the SCSI controller on the GVP Turbo 040/060 accelerator.
|
||||
|
||||
config OKTAGON_SCSI
|
||||
tristate "BSC Oktagon SCSI support (EXPERIMENTAL)"
|
||||
depends on ZORRO && SCSI && EXPERIMENTAL
|
||||
help
|
||||
If you have the BSC Oktagon SCSI disk controller for the Amiga, say
|
||||
Y to this question. If you're in doubt about whether you have one,
|
||||
see the picture at
|
||||
<http://amiga.resource.cx/exp/search.pl?product=oktagon>.
|
||||
|
||||
config ATARI_SCSI
|
||||
tristate "Atari native SCSI support"
|
||||
depends on ATARI && SCSI
|
||||
@@ -1705,18 +1657,6 @@ config MAC_SCSI
|
||||
SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
config SCSI_MAC_ESP
|
||||
tristate "Macintosh NCR53c9[46] SCSI"
|
||||
depends on MAC && SCSI
|
||||
help
|
||||
This is the NCR 53c9x SCSI controller found on most of the 68040
|
||||
based Macintoshes. If you have one of these say Y and read the
|
||||
SCSI-HOWTO, available from
|
||||
<http://www.tldp.org/docs.html#howto>.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called mac_esp.
|
||||
|
||||
config MVME147_SCSI
|
||||
bool "WD33C93 SCSI driver for MVME147"
|
||||
depends on MVME147 && SCSI=y
|
||||
|
||||
@@ -44,15 +44,8 @@ obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o
|
||||
obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o
|
||||
obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o
|
||||
obj-$(CONFIG_SGIWD93_SCSI) += sgiwd93.o wd33c93.o
|
||||
obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o
|
||||
obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o
|
||||
obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o
|
||||
obj-$(CONFIG_BLZ1230_SCSI) += NCR53C9x.o blz1230.o
|
||||
obj-$(CONFIG_FASTLANE_SCSI) += NCR53C9x.o fastlane.o
|
||||
obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp_mod.o
|
||||
obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o
|
||||
obj-$(CONFIG_MAC_SCSI) += mac_scsi.o
|
||||
obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o
|
||||
obj-$(CONFIG_SUN3_SCSI) += sun3_scsi.o sun3_scsi_vme.o
|
||||
obj-$(CONFIG_MVME16x_SCSI) += 53c700.o mvme16x_scsi.o
|
||||
obj-$(CONFIG_BVME6000_SCSI) += 53c700.o bvme6000_scsi.o
|
||||
|
||||
@@ -1,353 +0,0 @@
|
||||
/* blz1230.c: Driver for Blizzard 1230 SCSI IV Controller.
|
||||
*
|
||||
* Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
|
||||
*
|
||||
* This driver is based on the CyberStorm driver, hence the occasional
|
||||
* reference to CyberStorm.
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* 1) Figure out how to make a cleaner merge with the sparc driver with regard
|
||||
* to the caches and the Sparc MMU mapping.
|
||||
* 2) Make as few routines required outside the generic driver. A lot of the
|
||||
* routines in this file used to be inline!
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "NCR53C9x.h"
|
||||
|
||||
#include <linux/zorro.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/amigaints.h>
|
||||
#include <asm/amigahw.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
#define MKIV 1
|
||||
|
||||
/* The controller registers can be found in the Z2 config area at these
|
||||
* offsets:
|
||||
*/
|
||||
#define BLZ1230_ESP_ADDR 0x8000
|
||||
#define BLZ1230_DMA_ADDR 0x10000
|
||||
#define BLZ1230II_ESP_ADDR 0x10000
|
||||
#define BLZ1230II_DMA_ADDR 0x10021
|
||||
|
||||
|
||||
/* The Blizzard 1230 DMA interface
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Only two things can be programmed in the Blizzard DMA:
|
||||
* 1) The data direction is controlled by the status of bit 31 (1 = write)
|
||||
* 2) The source/dest address (word aligned, shifted one right) in bits 30-0
|
||||
*
|
||||
* Program DMA by first latching the highest byte of the address/direction
|
||||
* (i.e. bits 31-24 of the long word constructed as described in steps 1+2
|
||||
* above). Then write each byte of the address/direction (starting with the
|
||||
* top byte, working down) to the DMA address register.
|
||||
*
|
||||
* Figure out interrupt status by reading the ESP status byte.
|
||||
*/
|
||||
struct blz1230_dma_registers {
|
||||
volatile unsigned char dma_addr; /* DMA address [0x0000] */
|
||||
unsigned char dmapad2[0x7fff];
|
||||
volatile unsigned char dma_latch; /* DMA latch [0x8000] */
|
||||
};
|
||||
|
||||
struct blz1230II_dma_registers {
|
||||
volatile unsigned char dma_addr; /* DMA address [0x0000] */
|
||||
unsigned char dmapad2[0xf];
|
||||
volatile unsigned char dma_latch; /* DMA latch [0x0010] */
|
||||
};
|
||||
|
||||
#define BLZ1230_DMA_WRITE 0x80000000
|
||||
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
|
||||
static void dma_dump_state(struct NCR_ESP *esp);
|
||||
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
|
||||
static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length);
|
||||
static void dma_ints_off(struct NCR_ESP *esp);
|
||||
static void dma_ints_on(struct NCR_ESP *esp);
|
||||
static int dma_irq_p(struct NCR_ESP *esp);
|
||||
static int dma_ports_p(struct NCR_ESP *esp);
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
|
||||
|
||||
static volatile unsigned char cmd_buffer[16];
|
||||
/* This is where all commands are put
|
||||
* before they are transferred to the ESP chip
|
||||
* via PIO.
|
||||
*/
|
||||
|
||||
/***************************************************************** Detection */
|
||||
int __init blz1230_esp_detect(struct scsi_host_template *tpnt)
|
||||
{
|
||||
struct NCR_ESP *esp;
|
||||
struct zorro_dev *z = NULL;
|
||||
unsigned long address;
|
||||
struct ESP_regs *eregs;
|
||||
unsigned long board;
|
||||
|
||||
#if MKIV
|
||||
#define REAL_BLZ1230_ID ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260
|
||||
#define REAL_BLZ1230_ESP_ADDR BLZ1230_ESP_ADDR
|
||||
#define REAL_BLZ1230_DMA_ADDR BLZ1230_DMA_ADDR
|
||||
#else
|
||||
#define REAL_BLZ1230_ID ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060
|
||||
#define REAL_BLZ1230_ESP_ADDR BLZ1230II_ESP_ADDR
|
||||
#define REAL_BLZ1230_DMA_ADDR BLZ1230II_DMA_ADDR
|
||||
#endif
|
||||
|
||||
if ((z = zorro_find_device(REAL_BLZ1230_ID, z))) {
|
||||
board = z->resource.start;
|
||||
if (request_mem_region(board+REAL_BLZ1230_ESP_ADDR,
|
||||
sizeof(struct ESP_regs), "NCR53C9x")) {
|
||||
/* Do some magic to figure out if the blizzard is
|
||||
* equipped with a SCSI controller
|
||||
*/
|
||||
address = ZTWO_VADDR(board);
|
||||
eregs = (struct ESP_regs *)(address + REAL_BLZ1230_ESP_ADDR);
|
||||
esp = esp_allocate(tpnt, (void *)board + REAL_BLZ1230_ESP_ADDR,
|
||||
0);
|
||||
|
||||
esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
|
||||
udelay(5);
|
||||
if(esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7))
|
||||
goto err_out;
|
||||
|
||||
/* Do command transfer with programmed I/O */
|
||||
esp->do_pio_cmds = 1;
|
||||
|
||||
/* Required functions */
|
||||
esp->dma_bytes_sent = &dma_bytes_sent;
|
||||
esp->dma_can_transfer = &dma_can_transfer;
|
||||
esp->dma_dump_state = &dma_dump_state;
|
||||
esp->dma_init_read = &dma_init_read;
|
||||
esp->dma_init_write = &dma_init_write;
|
||||
esp->dma_ints_off = &dma_ints_off;
|
||||
esp->dma_ints_on = &dma_ints_on;
|
||||
esp->dma_irq_p = &dma_irq_p;
|
||||
esp->dma_ports_p = &dma_ports_p;
|
||||
esp->dma_setup = &dma_setup;
|
||||
|
||||
/* Optional functions */
|
||||
esp->dma_barrier = 0;
|
||||
esp->dma_drain = 0;
|
||||
esp->dma_invalidate = 0;
|
||||
esp->dma_irq_entry = 0;
|
||||
esp->dma_irq_exit = 0;
|
||||
esp->dma_led_on = 0;
|
||||
esp->dma_led_off = 0;
|
||||
esp->dma_poll = 0;
|
||||
esp->dma_reset = 0;
|
||||
|
||||
/* SCSI chip speed */
|
||||
esp->cfreq = 40000000;
|
||||
|
||||
/* The DMA registers on the Blizzard are mapped
|
||||
* relative to the device (i.e. in the same Zorro
|
||||
* I/O block).
|
||||
*/
|
||||
esp->dregs = (void *)(address + REAL_BLZ1230_DMA_ADDR);
|
||||
|
||||
/* ESP register base */
|
||||
esp->eregs = eregs;
|
||||
|
||||
/* Set the command buffer */
|
||||
esp->esp_command = cmd_buffer;
|
||||
esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
|
||||
|
||||
esp->irq = IRQ_AMIGA_PORTS;
|
||||
esp->slot = board+REAL_BLZ1230_ESP_ADDR;
|
||||
if (request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
|
||||
"Blizzard 1230 SCSI IV", esp->ehost))
|
||||
goto err_out;
|
||||
|
||||
/* Figure out our scsi ID on the bus */
|
||||
esp->scsi_id = 7;
|
||||
|
||||
/* We don't have a differential SCSI-bus. */
|
||||
esp->diff = 0;
|
||||
|
||||
esp_initialize(esp);
|
||||
|
||||
printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
|
||||
esps_running = esps_in_use;
|
||||
return esps_in_use;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
scsi_unregister(esp->ehost);
|
||||
esp_deallocate(esp);
|
||||
release_mem_region(board+REAL_BLZ1230_ESP_ADDR,
|
||||
sizeof(struct ESP_regs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************* DMA Functions */
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
|
||||
{
|
||||
/* Since the Blizzard DMA is fully dedicated to the ESP chip,
|
||||
* the number of bytes sent (to the ESP chip) equals the number
|
||||
* of bytes in the FIFO - there is no buffering in the DMA controller.
|
||||
* XXXX Do I read this right? It is from host to ESP, right?
|
||||
*/
|
||||
return fifo_count;
|
||||
}
|
||||
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
|
||||
{
|
||||
/* I don't think there's any limit on the Blizzard DMA. So we use what
|
||||
* the ESP chip can handle (24 bit).
|
||||
*/
|
||||
unsigned long sz = sp->SCp.this_residual;
|
||||
if(sz > 0x1000000)
|
||||
sz = 0x1000000;
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void dma_dump_state(struct NCR_ESP *esp)
|
||||
{
|
||||
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
|
||||
amiga_custom.intreqr, amiga_custom.intenar));
|
||||
}
|
||||
|
||||
void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
#if MKIV
|
||||
struct blz1230_dma_registers *dregs =
|
||||
(struct blz1230_dma_registers *) (esp->dregs);
|
||||
#else
|
||||
struct blz1230II_dma_registers *dregs =
|
||||
(struct blz1230II_dma_registers *) (esp->dregs);
|
||||
#endif
|
||||
|
||||
cache_clear(addr, length);
|
||||
|
||||
addr >>= 1;
|
||||
addr &= ~(BLZ1230_DMA_WRITE);
|
||||
|
||||
/* First set latch */
|
||||
dregs->dma_latch = (addr >> 24) & 0xff;
|
||||
|
||||
/* Then pump the address to the DMA address register */
|
||||
#if MKIV
|
||||
dregs->dma_addr = (addr >> 24) & 0xff;
|
||||
#endif
|
||||
dregs->dma_addr = (addr >> 16) & 0xff;
|
||||
dregs->dma_addr = (addr >> 8) & 0xff;
|
||||
dregs->dma_addr = (addr ) & 0xff;
|
||||
}
|
||||
|
||||
void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
#if MKIV
|
||||
struct blz1230_dma_registers *dregs =
|
||||
(struct blz1230_dma_registers *) (esp->dregs);
|
||||
#else
|
||||
struct blz1230II_dma_registers *dregs =
|
||||
(struct blz1230II_dma_registers *) (esp->dregs);
|
||||
#endif
|
||||
|
||||
cache_push(addr, length);
|
||||
|
||||
addr >>= 1;
|
||||
addr |= BLZ1230_DMA_WRITE;
|
||||
|
||||
/* First set latch */
|
||||
dregs->dma_latch = (addr >> 24) & 0xff;
|
||||
|
||||
/* Then pump the address to the DMA address register */
|
||||
#if MKIV
|
||||
dregs->dma_addr = (addr >> 24) & 0xff;
|
||||
#endif
|
||||
dregs->dma_addr = (addr >> 16) & 0xff;
|
||||
dregs->dma_addr = (addr >> 8) & 0xff;
|
||||
dregs->dma_addr = (addr ) & 0xff;
|
||||
}
|
||||
|
||||
static void dma_ints_off(struct NCR_ESP *esp)
|
||||
{
|
||||
disable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static void dma_ints_on(struct NCR_ESP *esp)
|
||||
{
|
||||
enable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static int dma_irq_p(struct NCR_ESP *esp)
|
||||
{
|
||||
return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
|
||||
}
|
||||
|
||||
static int dma_ports_p(struct NCR_ESP *esp)
|
||||
{
|
||||
return ((amiga_custom.intenar) & IF_PORTS);
|
||||
}
|
||||
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
|
||||
{
|
||||
/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
|
||||
* so when (write) is true, it actually means READ!
|
||||
*/
|
||||
if(write){
|
||||
dma_init_read(esp, addr, count);
|
||||
} else {
|
||||
dma_init_write(esp, addr, count);
|
||||
}
|
||||
}
|
||||
|
||||
#define HOSTS_C
|
||||
|
||||
int blz1230_esp_release(struct Scsi_Host *instance)
|
||||
{
|
||||
#ifdef MODULE
|
||||
unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
|
||||
esp_deallocate((struct NCR_ESP *)instance->hostdata);
|
||||
esp_release();
|
||||
release_mem_region(address, sizeof(struct ESP_regs));
|
||||
free_irq(IRQ_AMIGA_PORTS, esp_intr);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.proc_name = "esp-blz1230",
|
||||
.proc_info = esp_proc_info,
|
||||
.name = "Blizzard1230 SCSI IV",
|
||||
.detect = blz1230_esp_detect,
|
||||
.slave_alloc = esp_slave_alloc,
|
||||
.slave_destroy = esp_slave_destroy,
|
||||
.release = blz1230_esp_release,
|
||||
.queuecommand = esp_queue,
|
||||
.eh_abort_handler = esp_abort,
|
||||
.eh_bus_reset_handler = esp_reset,
|
||||
.can_queue = 7,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = 1,
|
||||
.use_clustering = ENABLE_CLUSTERING
|
||||
};
|
||||
|
||||
|
||||
#include "scsi_module.c"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -1,306 +0,0 @@
|
||||
/* blz2060.c: Driver for Blizzard 2060 SCSI Controller.
|
||||
*
|
||||
* Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
|
||||
*
|
||||
* This driver is based on the CyberStorm driver, hence the occasional
|
||||
* reference to CyberStorm.
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* 1) Figure out how to make a cleaner merge with the sparc driver with regard
|
||||
* to the caches and the Sparc MMU mapping.
|
||||
* 2) Make as few routines required outside the generic driver. A lot of the
|
||||
* routines in this file used to be inline!
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "NCR53C9x.h"
|
||||
|
||||
#include <linux/zorro.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/amigaints.h>
|
||||
#include <asm/amigahw.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/* The controller registers can be found in the Z2 config area at these
|
||||
* offsets:
|
||||
*/
|
||||
#define BLZ2060_ESP_ADDR 0x1ff00
|
||||
#define BLZ2060_DMA_ADDR 0x1ffe0
|
||||
|
||||
|
||||
/* The Blizzard 2060 DMA interface
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Only two things can be programmed in the Blizzard DMA:
|
||||
* 1) The data direction is controlled by the status of bit 31 (1 = write)
|
||||
* 2) The source/dest address (word aligned, shifted one right) in bits 30-0
|
||||
*
|
||||
* Figure out interrupt status by reading the ESP status byte.
|
||||
*/
|
||||
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] */
|
||||
};
|
||||
|
||||
#define BLZ2060_DMA_WRITE 0x80000000
|
||||
|
||||
/* DMA control bits */
|
||||
#define BLZ2060_DMA_LED 0x02 /* HD led control 1 = off */
|
||||
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
|
||||
static void dma_dump_state(struct NCR_ESP *esp);
|
||||
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
|
||||
static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length);
|
||||
static void dma_ints_off(struct NCR_ESP *esp);
|
||||
static void dma_ints_on(struct NCR_ESP *esp);
|
||||
static int dma_irq_p(struct NCR_ESP *esp);
|
||||
static void dma_led_off(struct NCR_ESP *esp);
|
||||
static void dma_led_on(struct NCR_ESP *esp);
|
||||
static int dma_ports_p(struct NCR_ESP *esp);
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
|
||||
|
||||
static volatile unsigned char cmd_buffer[16];
|
||||
/* This is where all commands are put
|
||||
* before they are transferred to the ESP chip
|
||||
* via PIO.
|
||||
*/
|
||||
|
||||
/***************************************************************** Detection */
|
||||
int __init blz2060_esp_detect(struct scsi_host_template *tpnt)
|
||||
{
|
||||
struct NCR_ESP *esp;
|
||||
struct zorro_dev *z = NULL;
|
||||
unsigned long address;
|
||||
|
||||
if ((z = zorro_find_device(ZORRO_PROD_PHASE5_BLIZZARD_2060, z))) {
|
||||
unsigned long board = z->resource.start;
|
||||
if (request_mem_region(board+BLZ2060_ESP_ADDR,
|
||||
sizeof(struct ESP_regs), "NCR53C9x")) {
|
||||
esp = esp_allocate(tpnt, (void *)board + BLZ2060_ESP_ADDR, 0);
|
||||
|
||||
/* Do command transfer with programmed I/O */
|
||||
esp->do_pio_cmds = 1;
|
||||
|
||||
/* Required functions */
|
||||
esp->dma_bytes_sent = &dma_bytes_sent;
|
||||
esp->dma_can_transfer = &dma_can_transfer;
|
||||
esp->dma_dump_state = &dma_dump_state;
|
||||
esp->dma_init_read = &dma_init_read;
|
||||
esp->dma_init_write = &dma_init_write;
|
||||
esp->dma_ints_off = &dma_ints_off;
|
||||
esp->dma_ints_on = &dma_ints_on;
|
||||
esp->dma_irq_p = &dma_irq_p;
|
||||
esp->dma_ports_p = &dma_ports_p;
|
||||
esp->dma_setup = &dma_setup;
|
||||
|
||||
/* Optional functions */
|
||||
esp->dma_barrier = 0;
|
||||
esp->dma_drain = 0;
|
||||
esp->dma_invalidate = 0;
|
||||
esp->dma_irq_entry = 0;
|
||||
esp->dma_irq_exit = 0;
|
||||
esp->dma_led_on = &dma_led_on;
|
||||
esp->dma_led_off = &dma_led_off;
|
||||
esp->dma_poll = 0;
|
||||
esp->dma_reset = 0;
|
||||
|
||||
/* SCSI chip speed */
|
||||
esp->cfreq = 40000000;
|
||||
|
||||
/* The DMA registers on the Blizzard are mapped
|
||||
* relative to the device (i.e. in the same Zorro
|
||||
* I/O block).
|
||||
*/
|
||||
address = (unsigned long)ZTWO_VADDR(board);
|
||||
esp->dregs = (void *)(address + BLZ2060_DMA_ADDR);
|
||||
|
||||
/* ESP register base */
|
||||
esp->eregs = (struct ESP_regs *)(address + BLZ2060_ESP_ADDR);
|
||||
|
||||
/* Set the command buffer */
|
||||
esp->esp_command = cmd_buffer;
|
||||
esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
|
||||
|
||||
esp->irq = IRQ_AMIGA_PORTS;
|
||||
request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
|
||||
"Blizzard 2060 SCSI", esp->ehost);
|
||||
|
||||
/* Figure out our scsi ID on the bus */
|
||||
esp->scsi_id = 7;
|
||||
|
||||
/* We don't have a differential SCSI-bus. */
|
||||
esp->diff = 0;
|
||||
|
||||
esp_initialize(esp);
|
||||
|
||||
printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
|
||||
esps_running = esps_in_use;
|
||||
return esps_in_use;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************* DMA Functions */
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
|
||||
{
|
||||
/* Since the Blizzard DMA is fully dedicated to the ESP chip,
|
||||
* the number of bytes sent (to the ESP chip) equals the number
|
||||
* of bytes in the FIFO - there is no buffering in the DMA controller.
|
||||
* XXXX Do I read this right? It is from host to ESP, right?
|
||||
*/
|
||||
return fifo_count;
|
||||
}
|
||||
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
|
||||
{
|
||||
/* I don't think there's any limit on the Blizzard DMA. So we use what
|
||||
* the ESP chip can handle (24 bit).
|
||||
*/
|
||||
unsigned long sz = sp->SCp.this_residual;
|
||||
if(sz > 0x1000000)
|
||||
sz = 0x1000000;
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void dma_dump_state(struct NCR_ESP *esp)
|
||||
{
|
||||
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
|
||||
amiga_custom.intreqr, amiga_custom.intenar));
|
||||
}
|
||||
|
||||
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
struct blz2060_dma_registers *dregs =
|
||||
(struct blz2060_dma_registers *) (esp->dregs);
|
||||
|
||||
cache_clear(addr, length);
|
||||
|
||||
addr >>= 1;
|
||||
addr &= ~(BLZ2060_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;
|
||||
}
|
||||
|
||||
static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
struct blz2060_dma_registers *dregs =
|
||||
(struct blz2060_dma_registers *) (esp->dregs);
|
||||
|
||||
cache_push(addr, length);
|
||||
|
||||
addr >>= 1;
|
||||
addr |= BLZ2060_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;
|
||||
}
|
||||
|
||||
static void dma_ints_off(struct NCR_ESP *esp)
|
||||
{
|
||||
disable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static void dma_ints_on(struct NCR_ESP *esp)
|
||||
{
|
||||
enable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static int dma_irq_p(struct NCR_ESP *esp)
|
||||
{
|
||||
return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
|
||||
}
|
||||
|
||||
static void dma_led_off(struct NCR_ESP *esp)
|
||||
{
|
||||
((struct blz2060_dma_registers *) (esp->dregs))->dma_led_ctrl =
|
||||
BLZ2060_DMA_LED;
|
||||
}
|
||||
|
||||
static void dma_led_on(struct NCR_ESP *esp)
|
||||
{
|
||||
((struct blz2060_dma_registers *) (esp->dregs))->dma_led_ctrl = 0;
|
||||
}
|
||||
|
||||
static int dma_ports_p(struct NCR_ESP *esp)
|
||||
{
|
||||
return ((amiga_custom.intenar) & IF_PORTS);
|
||||
}
|
||||
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
|
||||
{
|
||||
/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
|
||||
* so when (write) is true, it actually means READ!
|
||||
*/
|
||||
if(write){
|
||||
dma_init_read(esp, addr, count);
|
||||
} else {
|
||||
dma_init_write(esp, addr, count);
|
||||
}
|
||||
}
|
||||
|
||||
#define HOSTS_C
|
||||
|
||||
int blz2060_esp_release(struct Scsi_Host *instance)
|
||||
{
|
||||
#ifdef MODULE
|
||||
unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
|
||||
|
||||
esp_deallocate((struct NCR_ESP *)instance->hostdata);
|
||||
esp_release();
|
||||
release_mem_region(address, sizeof(struct ESP_regs));
|
||||
free_irq(IRQ_AMIGA_PORTS, esp_intr);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.proc_name = "esp-blz2060",
|
||||
.proc_info = esp_proc_info,
|
||||
.name = "Blizzard2060 SCSI",
|
||||
.detect = blz2060_esp_detect,
|
||||
.slave_alloc = esp_slave_alloc,
|
||||
.slave_destroy = esp_slave_destroy,
|
||||
.release = blz2060_esp_release,
|
||||
.queuecommand = esp_queue,
|
||||
.eh_abort_handler = esp_abort,
|
||||
.eh_bus_reset_handler = esp_reset,
|
||||
.can_queue = 7,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = 1,
|
||||
.use_clustering = ENABLE_CLUSTERING
|
||||
};
|
||||
|
||||
|
||||
#include "scsi_module.c"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -1,377 +0,0 @@
|
||||
/* cyberstorm.c: Driver for CyberStorm SCSI Controller.
|
||||
*
|
||||
* Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
|
||||
*
|
||||
* The CyberStorm SCSI driver is based on David S. Miller's ESP driver
|
||||
* for the Sparc computers.
|
||||
*
|
||||
* This work was made possible by Phase5 who willingly (and most generously)
|
||||
* supported me with hardware and all the information I needed.
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* 1) Figure out how to make a cleaner merge with the sparc driver with regard
|
||||
* to the caches and the Sparc MMU mapping.
|
||||
* 2) Make as few routines required outside the generic driver. A lot of the
|
||||
* routines in this file used to be inline!
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "NCR53C9x.h"
|
||||
|
||||
#include <linux/zorro.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/amigaints.h>
|
||||
#include <asm/amigahw.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/* The controller registers can be found in the Z2 config area at these
|
||||
* offsets:
|
||||
*/
|
||||
#define CYBER_ESP_ADDR 0xf400
|
||||
#define CYBER_DMA_ADDR 0xf800
|
||||
|
||||
|
||||
/* The 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_LED 0x80 /* HD led control 1 = on */
|
||||
#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 bits below appears to be Phase5 Debug bits only; they were not
|
||||
* described by Phase5 so using them may seem a bit stupid...
|
||||
*/
|
||||
#define CYBER_HOST_ID 0x02 /* If set, host ID should be 7, otherwise
|
||||
* it should be 6.
|
||||
*/
|
||||
#define CYBER_SLOW_CABLE 0x08 /* If *not* set, assume SLOW_CABLE */
|
||||
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
|
||||
static void dma_dump_state(struct NCR_ESP *esp);
|
||||
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
|
||||
static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length);
|
||||
static void dma_ints_off(struct NCR_ESP *esp);
|
||||
static void dma_ints_on(struct NCR_ESP *esp);
|
||||
static int dma_irq_p(struct NCR_ESP *esp);
|
||||
static void dma_led_off(struct NCR_ESP *esp);
|
||||
static void dma_led_on(struct NCR_ESP *esp);
|
||||
static int dma_ports_p(struct NCR_ESP *esp);
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
|
||||
|
||||
static unsigned char ctrl_data = 0; /* Keep backup of the stuff written
|
||||
* to ctrl_reg. Always write a copy
|
||||
* to this register when writing to
|
||||
* the hardware register!
|
||||
*/
|
||||
|
||||
static volatile unsigned char cmd_buffer[16];
|
||||
/* This is where all commands are put
|
||||
* before they are transferred to the ESP chip
|
||||
* via PIO.
|
||||
*/
|
||||
|
||||
/***************************************************************** Detection */
|
||||
int __init cyber_esp_detect(struct scsi_host_template *tpnt)
|
||||
{
|
||||
struct NCR_ESP *esp;
|
||||
struct zorro_dev *z = NULL;
|
||||
unsigned long address;
|
||||
|
||||
while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
|
||||
unsigned long board = z->resource.start;
|
||||
if ((z->id == ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM ||
|
||||
z->id == ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060) &&
|
||||
request_mem_region(board+CYBER_ESP_ADDR,
|
||||
sizeof(struct ESP_regs), "NCR53C9x")) {
|
||||
/* Figure out if this is a CyberStorm or really a
|
||||
* Fastlane/Blizzard Mk II by looking at the board size.
|
||||
* CyberStorm maps 64kB
|
||||
* (ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM does anyway)
|
||||
*/
|
||||
if(z->resource.end-board != 0xffff) {
|
||||
release_mem_region(board+CYBER_ESP_ADDR,
|
||||
sizeof(struct ESP_regs));
|
||||
return 0;
|
||||
}
|
||||
esp = esp_allocate(tpnt, (void *)board + CYBER_ESP_ADDR, 0);
|
||||
|
||||
/* Do command transfer with programmed I/O */
|
||||
esp->do_pio_cmds = 1;
|
||||
|
||||
/* Required functions */
|
||||
esp->dma_bytes_sent = &dma_bytes_sent;
|
||||
esp->dma_can_transfer = &dma_can_transfer;
|
||||
esp->dma_dump_state = &dma_dump_state;
|
||||
esp->dma_init_read = &dma_init_read;
|
||||
esp->dma_init_write = &dma_init_write;
|
||||
esp->dma_ints_off = &dma_ints_off;
|
||||
esp->dma_ints_on = &dma_ints_on;
|
||||
esp->dma_irq_p = &dma_irq_p;
|
||||
esp->dma_ports_p = &dma_ports_p;
|
||||
esp->dma_setup = &dma_setup;
|
||||
|
||||
/* Optional functions */
|
||||
esp->dma_barrier = 0;
|
||||
esp->dma_drain = 0;
|
||||
esp->dma_invalidate = 0;
|
||||
esp->dma_irq_entry = 0;
|
||||
esp->dma_irq_exit = 0;
|
||||
esp->dma_led_on = &dma_led_on;
|
||||
esp->dma_led_off = &dma_led_off;
|
||||
esp->dma_poll = 0;
|
||||
esp->dma_reset = 0;
|
||||
|
||||
/* SCSI chip speed */
|
||||
esp->cfreq = 40000000;
|
||||
|
||||
/* The DMA registers on the CyberStorm are mapped
|
||||
* relative to the device (i.e. in the same Zorro
|
||||
* I/O block).
|
||||
*/
|
||||
address = (unsigned long)ZTWO_VADDR(board);
|
||||
esp->dregs = (void *)(address + CYBER_DMA_ADDR);
|
||||
|
||||
/* ESP register base */
|
||||
esp->eregs = (struct ESP_regs *)(address + CYBER_ESP_ADDR);
|
||||
|
||||
/* Set the command buffer */
|
||||
esp->esp_command = cmd_buffer;
|
||||
esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
|
||||
|
||||
esp->irq = IRQ_AMIGA_PORTS;
|
||||
request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
|
||||
"CyberStorm SCSI", esp->ehost);
|
||||
/* Figure out our scsi ID on the bus */
|
||||
/* The DMA cond flag contains a hardcoded jumper bit
|
||||
* which can be used to select host number 6 or 7.
|
||||
* However, even though it may change, we use a hardcoded
|
||||
* value of 7.
|
||||
*/
|
||||
esp->scsi_id = 7;
|
||||
|
||||
/* We don't have a differential SCSI-bus. */
|
||||
esp->diff = 0;
|
||||
|
||||
esp_initialize(esp);
|
||||
|
||||
printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
|
||||
esps_running = esps_in_use;
|
||||
return esps_in_use;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************* DMA Functions */
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
|
||||
{
|
||||
/* Since the CyberStorm DMA is fully dedicated to the ESP chip,
|
||||
* the number of bytes sent (to the ESP chip) equals the number
|
||||
* of bytes in the FIFO - there is no buffering in the DMA controller.
|
||||
* XXXX Do I read this right? It is from host to ESP, right?
|
||||
*/
|
||||
return fifo_count;
|
||||
}
|
||||
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
|
||||
{
|
||||
/* I don't think there's any limit on the CyberDMA. So we use what
|
||||
* the ESP chip can handle (24 bit).
|
||||
*/
|
||||
unsigned long sz = sp->SCp.this_residual;
|
||||
if(sz > 0x1000000)
|
||||
sz = 0x1000000;
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void dma_dump_state(struct NCR_ESP *esp)
|
||||
{
|
||||
ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
|
||||
esp->esp_id, ((struct cyber_dma_registers *)
|
||||
(esp->dregs))->cond_reg));
|
||||
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
|
||||
amiga_custom.intreqr, amiga_custom.intenar));
|
||||
}
|
||||
|
||||
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
struct cyber_dma_registers *dregs =
|
||||
(struct cyber_dma_registers *) esp->dregs;
|
||||
|
||||
cache_clear(addr, length);
|
||||
|
||||
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;
|
||||
ctrl_data &= ~(CYBER_DMA_WRITE);
|
||||
|
||||
/* Check if physical address is outside Z2 space and of
|
||||
* block length/block aligned in memory. If this is the
|
||||
* case, enable 32 bit transfer. In all other cases, fall back
|
||||
* to 16 bit transfer.
|
||||
* Obviously 32 bit transfer should be enabled if the DMA address
|
||||
* and length are 32 bit aligned. However, this leads to some
|
||||
* strange behavior. Even 64 bit aligned addr/length fails.
|
||||
* Until I've found a reason for this, 32 bit transfer is only
|
||||
* used for full-block transfers (1kB).
|
||||
* -jskov
|
||||
*/
|
||||
#if 0
|
||||
if((addr & 0x3fc) || length & 0x3ff || ((addr > 0x200000) &&
|
||||
(addr < 0xff0000)))
|
||||
ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */
|
||||
else
|
||||
ctrl_data |= CYBER_DMA_Z3; /* CHIP/Z3, do 32 bit DMA */
|
||||
#else
|
||||
ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */
|
||||
#endif
|
||||
dregs->ctrl_reg = ctrl_data;
|
||||
}
|
||||
|
||||
static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
struct cyber_dma_registers *dregs =
|
||||
(struct cyber_dma_registers *) esp->dregs;
|
||||
|
||||
cache_push(addr, length);
|
||||
|
||||
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;
|
||||
ctrl_data |= CYBER_DMA_WRITE;
|
||||
|
||||
/* See comment above */
|
||||
#if 0
|
||||
if((addr & 0x3fc) || length & 0x3ff || ((addr > 0x200000) &&
|
||||
(addr < 0xff0000)))
|
||||
ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */
|
||||
else
|
||||
ctrl_data |= CYBER_DMA_Z3; /* CHIP/Z3, do 32 bit DMA */
|
||||
#else
|
||||
ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */
|
||||
#endif
|
||||
dregs->ctrl_reg = ctrl_data;
|
||||
}
|
||||
|
||||
static void dma_ints_off(struct NCR_ESP *esp)
|
||||
{
|
||||
disable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static void dma_ints_on(struct NCR_ESP *esp)
|
||||
{
|
||||
enable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static int dma_irq_p(struct NCR_ESP *esp)
|
||||
{
|
||||
/* It's important to check the DMA IRQ bit in the correct way! */
|
||||
return ((esp_read(esp->eregs->esp_status) & ESP_STAT_INTR) &&
|
||||
((((struct cyber_dma_registers *)(esp->dregs))->cond_reg) &
|
||||
CYBER_DMA_HNDL_INTR));
|
||||
}
|
||||
|
||||
static void dma_led_off(struct NCR_ESP *esp)
|
||||
{
|
||||
ctrl_data &= ~CYBER_DMA_LED;
|
||||
((struct cyber_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
|
||||
}
|
||||
|
||||
static void dma_led_on(struct NCR_ESP *esp)
|
||||
{
|
||||
ctrl_data |= CYBER_DMA_LED;
|
||||
((struct cyber_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
|
||||
}
|
||||
|
||||
static int dma_ports_p(struct NCR_ESP *esp)
|
||||
{
|
||||
return ((amiga_custom.intenar) & IF_PORTS);
|
||||
}
|
||||
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
|
||||
{
|
||||
/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
|
||||
* so when (write) is true, it actually means READ!
|
||||
*/
|
||||
if(write){
|
||||
dma_init_read(esp, addr, count);
|
||||
} else {
|
||||
dma_init_write(esp, addr, count);
|
||||
}
|
||||
}
|
||||
|
||||
#define HOSTS_C
|
||||
|
||||
int cyber_esp_release(struct Scsi_Host *instance)
|
||||
{
|
||||
#ifdef MODULE
|
||||
unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
|
||||
|
||||
esp_deallocate((struct NCR_ESP *)instance->hostdata);
|
||||
esp_release();
|
||||
release_mem_region(address, sizeof(struct ESP_regs));
|
||||
free_irq(IRQ_AMIGA_PORTS, esp_intr);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.proc_name = "esp-cyberstorm",
|
||||
.proc_info = esp_proc_info,
|
||||
.name = "CyberStorm SCSI",
|
||||
.detect = cyber_esp_detect,
|
||||
.slave_alloc = esp_slave_alloc,
|
||||
.slave_destroy = esp_slave_destroy,
|
||||
.release = cyber_esp_release,
|
||||
.queuecommand = esp_queue,
|
||||
.eh_abort_handler = esp_abort,
|
||||
.eh_bus_reset_handler = esp_reset,
|
||||
.can_queue = 7,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = 1,
|
||||
.use_clustering = ENABLE_CLUSTERING
|
||||
};
|
||||
|
||||
|
||||
#include "scsi_module.c"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -1,314 +0,0 @@
|
||||
/* cyberstormII.c: Driver for CyberStorm SCSI Mk II
|
||||
*
|
||||
* Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
|
||||
*
|
||||
* This driver is based on cyberstorm.c
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* 1) Figure out how to make a cleaner merge with the sparc driver with regard
|
||||
* to the caches and the Sparc MMU mapping.
|
||||
* 2) Make as few routines required outside the generic driver. A lot of the
|
||||
* routines in this file used to be inline!
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "NCR53C9x.h"
|
||||
|
||||
#include <linux/zorro.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/amigaints.h>
|
||||
#include <asm/amigahw.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/* The controller registers can be found in the Z2 config area at these
|
||||
* offsets:
|
||||
*/
|
||||
#define CYBERII_ESP_ADDR 0x1ff03
|
||||
#define CYBERII_DMA_ADDR 0x1ff43
|
||||
|
||||
|
||||
/* 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] */
|
||||
};
|
||||
|
||||
/* DMA control bits */
|
||||
#define CYBERII_DMA_LED 0x02 /* HD led control 1 = on */
|
||||
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
|
||||
static void dma_dump_state(struct NCR_ESP *esp);
|
||||
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
|
||||
static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length);
|
||||
static void dma_ints_off(struct NCR_ESP *esp);
|
||||
static void dma_ints_on(struct NCR_ESP *esp);
|
||||
static int dma_irq_p(struct NCR_ESP *esp);
|
||||
static void dma_led_off(struct NCR_ESP *esp);
|
||||
static void dma_led_on(struct NCR_ESP *esp);
|
||||
static int dma_ports_p(struct NCR_ESP *esp);
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
|
||||
|
||||
static volatile unsigned char cmd_buffer[16];
|
||||
/* This is where all commands are put
|
||||
* before they are transferred to the ESP chip
|
||||
* via PIO.
|
||||
*/
|
||||
|
||||
/***************************************************************** Detection */
|
||||
int __init cyberII_esp_detect(struct scsi_host_template *tpnt)
|
||||
{
|
||||
struct NCR_ESP *esp;
|
||||
struct zorro_dev *z = NULL;
|
||||
unsigned long address;
|
||||
struct ESP_regs *eregs;
|
||||
|
||||
if ((z = zorro_find_device(ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, z))) {
|
||||
unsigned long board = z->resource.start;
|
||||
if (request_mem_region(board+CYBERII_ESP_ADDR,
|
||||
sizeof(struct ESP_regs), "NCR53C9x")) {
|
||||
/* Do some magic to figure out if the CyberStorm Mk II
|
||||
* is equipped with a SCSI controller
|
||||
*/
|
||||
address = (unsigned long)ZTWO_VADDR(board);
|
||||
eregs = (struct ESP_regs *)(address + CYBERII_ESP_ADDR);
|
||||
|
||||
esp = esp_allocate(tpnt, (void *)board + CYBERII_ESP_ADDR, 0);
|
||||
|
||||
esp_write(eregs->esp_cfg1, (ESP_CONFIG1_PENABLE | 7));
|
||||
udelay(5);
|
||||
if(esp_read(eregs->esp_cfg1) != (ESP_CONFIG1_PENABLE | 7)) {
|
||||
esp_deallocate(esp);
|
||||
scsi_unregister(esp->ehost);
|
||||
release_mem_region(board+CYBERII_ESP_ADDR,
|
||||
sizeof(struct ESP_regs));
|
||||
return 0; /* Bail out if address did not hold data */
|
||||
}
|
||||
|
||||
/* Do command transfer with programmed I/O */
|
||||
esp->do_pio_cmds = 1;
|
||||
|
||||
/* Required functions */
|
||||
esp->dma_bytes_sent = &dma_bytes_sent;
|
||||
esp->dma_can_transfer = &dma_can_transfer;
|
||||
esp->dma_dump_state = &dma_dump_state;
|
||||
esp->dma_init_read = &dma_init_read;
|
||||
esp->dma_init_write = &dma_init_write;
|
||||
esp->dma_ints_off = &dma_ints_off;
|
||||
esp->dma_ints_on = &dma_ints_on;
|
||||
esp->dma_irq_p = &dma_irq_p;
|
||||
esp->dma_ports_p = &dma_ports_p;
|
||||
esp->dma_setup = &dma_setup;
|
||||
|
||||
/* Optional functions */
|
||||
esp->dma_barrier = 0;
|
||||
esp->dma_drain = 0;
|
||||
esp->dma_invalidate = 0;
|
||||
esp->dma_irq_entry = 0;
|
||||
esp->dma_irq_exit = 0;
|
||||
esp->dma_led_on = &dma_led_on;
|
||||
esp->dma_led_off = &dma_led_off;
|
||||
esp->dma_poll = 0;
|
||||
esp->dma_reset = 0;
|
||||
|
||||
/* SCSI chip speed */
|
||||
esp->cfreq = 40000000;
|
||||
|
||||
/* The DMA registers on the CyberStorm are mapped
|
||||
* relative to the device (i.e. in the same Zorro
|
||||
* I/O block).
|
||||
*/
|
||||
esp->dregs = (void *)(address + CYBERII_DMA_ADDR);
|
||||
|
||||
/* ESP register base */
|
||||
esp->eregs = eregs;
|
||||
|
||||
/* Set the command buffer */
|
||||
esp->esp_command = cmd_buffer;
|
||||
esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
|
||||
|
||||
esp->irq = IRQ_AMIGA_PORTS;
|
||||
request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
|
||||
"CyberStorm SCSI Mk II", esp->ehost);
|
||||
|
||||
/* Figure out our scsi ID on the bus */
|
||||
esp->scsi_id = 7;
|
||||
|
||||
/* We don't have a differential SCSI-bus. */
|
||||
esp->diff = 0;
|
||||
|
||||
esp_initialize(esp);
|
||||
|
||||
printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
|
||||
esps_running = esps_in_use;
|
||||
return esps_in_use;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************* DMA Functions */
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
|
||||
{
|
||||
/* Since the CyberStorm DMA is fully dedicated to the ESP chip,
|
||||
* the number of bytes sent (to the ESP chip) equals the number
|
||||
* of bytes in the FIFO - there is no buffering in the DMA controller.
|
||||
* XXXX Do I read this right? It is from host to ESP, right?
|
||||
*/
|
||||
return fifo_count;
|
||||
}
|
||||
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
|
||||
{
|
||||
/* I don't think there's any limit on the CyberDMA. So we use what
|
||||
* the ESP chip can handle (24 bit).
|
||||
*/
|
||||
unsigned long sz = sp->SCp.this_residual;
|
||||
if(sz > 0x1000000)
|
||||
sz = 0x1000000;
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void dma_dump_state(struct NCR_ESP *esp)
|
||||
{
|
||||
ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
|
||||
esp->esp_id, ((struct cyberII_dma_registers *)
|
||||
(esp->dregs))->cond_reg));
|
||||
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
|
||||
amiga_custom.intreqr, amiga_custom.intenar));
|
||||
}
|
||||
|
||||
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
struct cyberII_dma_registers *dregs =
|
||||
(struct cyberII_dma_registers *) esp->dregs;
|
||||
|
||||
cache_clear(addr, length);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
struct cyberII_dma_registers *dregs =
|
||||
(struct cyberII_dma_registers *) esp->dregs;
|
||||
|
||||
cache_push(addr, length);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void dma_ints_off(struct NCR_ESP *esp)
|
||||
{
|
||||
disable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static void dma_ints_on(struct NCR_ESP *esp)
|
||||
{
|
||||
enable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static int dma_irq_p(struct NCR_ESP *esp)
|
||||
{
|
||||
/* It's important to check the DMA IRQ bit in the correct way! */
|
||||
return (esp_read(esp->eregs->esp_status) & ESP_STAT_INTR);
|
||||
}
|
||||
|
||||
static void dma_led_off(struct NCR_ESP *esp)
|
||||
{
|
||||
((struct cyberII_dma_registers *)(esp->dregs))->ctrl_reg &= ~CYBERII_DMA_LED;
|
||||
}
|
||||
|
||||
static void dma_led_on(struct NCR_ESP *esp)
|
||||
{
|
||||
((struct cyberII_dma_registers *)(esp->dregs))->ctrl_reg |= CYBERII_DMA_LED;
|
||||
}
|
||||
|
||||
static int dma_ports_p(struct NCR_ESP *esp)
|
||||
{
|
||||
return ((amiga_custom.intenar) & IF_PORTS);
|
||||
}
|
||||
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
|
||||
{
|
||||
/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
|
||||
* so when (write) is true, it actually means READ!
|
||||
*/
|
||||
if(write){
|
||||
dma_init_read(esp, addr, count);
|
||||
} else {
|
||||
dma_init_write(esp, addr, count);
|
||||
}
|
||||
}
|
||||
|
||||
#define HOSTS_C
|
||||
|
||||
int cyberII_esp_release(struct Scsi_Host *instance)
|
||||
{
|
||||
#ifdef MODULE
|
||||
unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
|
||||
|
||||
esp_deallocate((struct NCR_ESP *)instance->hostdata);
|
||||
esp_release();
|
||||
release_mem_region(address, sizeof(struct ESP_regs));
|
||||
free_irq(IRQ_AMIGA_PORTS, esp_intr);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.proc_name = "esp-cyberstormII",
|
||||
.proc_info = esp_proc_info,
|
||||
.name = "CyberStorm Mk II SCSI",
|
||||
.detect = cyberII_esp_detect,
|
||||
.slave_alloc = esp_slave_alloc,
|
||||
.slave_destroy = esp_slave_destroy,
|
||||
.release = cyberII_esp_release,
|
||||
.queuecommand = esp_queue,
|
||||
.eh_abort_handler = esp_abort,
|
||||
.eh_bus_reset_handler = esp_reset,
|
||||
.can_queue = 7,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = 1,
|
||||
.use_clustering = ENABLE_CLUSTERING
|
||||
};
|
||||
|
||||
|
||||
#include "scsi_module.c"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -1,421 +0,0 @@
|
||||
/* fastlane.c: Driver for Phase5's Fastlane SCSI Controller.
|
||||
*
|
||||
* Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
|
||||
*
|
||||
* This driver is based on the CyberStorm driver, hence the occasional
|
||||
* reference to CyberStorm.
|
||||
*
|
||||
* Betatesting & crucial adjustments by
|
||||
* Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
|
||||
*
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
*
|
||||
* o According to the doc from laire, it is required to reset the DMA when
|
||||
* the transfer is done. ATM we reset DMA just before every new
|
||||
* dma_init_(read|write).
|
||||
*
|
||||
* 1) Figure out how to make a cleaner merge with the sparc driver with regard
|
||||
* to the caches and the Sparc MMU mapping.
|
||||
* 2) Make as few routines required outside the generic driver. A lot of the
|
||||
* routines in this file used to be inline!
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include "scsi.h"
|
||||
#include <scsi/scsi_host.h>
|
||||
#include "NCR53C9x.h"
|
||||
|
||||
#include <linux/zorro.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
#include <asm/amigaints.h>
|
||||
#include <asm/amigahw.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
|
||||
/* Such day has just come... */
|
||||
#if 0
|
||||
/* Let this defined unless you really need to enable DMA IRQ one day */
|
||||
#define NODMAIRQ
|
||||
#endif
|
||||
|
||||
/* The controller registers can be found in the Z2 config area at these
|
||||
* offsets:
|
||||
*/
|
||||
#define FASTLANE_ESP_ADDR 0x1000001
|
||||
#define FASTLANE_DMA_ADDR 0x1000041
|
||||
|
||||
|
||||
/* The 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] */
|
||||
};
|
||||
|
||||
|
||||
/* 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_LED 0x10 /* HD led control 1 = on */
|
||||
#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 */
|
||||
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
|
||||
static void dma_dump_state(struct NCR_ESP *esp);
|
||||
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length);
|
||||
static void dma_init_write(struct NCR_ESP *esp, __u32 vaddr, int length);
|
||||
static void dma_ints_off(struct NCR_ESP *esp);
|
||||
static void dma_ints_on(struct NCR_ESP *esp);
|
||||
static int dma_irq_p(struct NCR_ESP *esp);
|
||||
static void dma_irq_exit(struct NCR_ESP *esp);
|
||||
static void dma_led_off(struct NCR_ESP *esp);
|
||||
static void dma_led_on(struct NCR_ESP *esp);
|
||||
static int dma_ports_p(struct NCR_ESP *esp);
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
|
||||
|
||||
static unsigned char ctrl_data = 0; /* Keep backup of the stuff written
|
||||
* to ctrl_reg. Always write a copy
|
||||
* to this register when writing to
|
||||
* the hardware register!
|
||||
*/
|
||||
|
||||
static volatile unsigned char cmd_buffer[16];
|
||||
/* This is where all commands are put
|
||||
* before they are transferred to the ESP chip
|
||||
* via PIO.
|
||||
*/
|
||||
|
||||
static inline void dma_clear(struct NCR_ESP *esp)
|
||||
{
|
||||
struct fastlane_dma_registers *dregs =
|
||||
(struct fastlane_dma_registers *) (esp->dregs);
|
||||
unsigned long *t;
|
||||
|
||||
ctrl_data = (ctrl_data & FASTLANE_DMA_MASK);
|
||||
dregs->ctrl_reg = ctrl_data;
|
||||
|
||||
t = (unsigned long *)(esp->edev);
|
||||
|
||||
dregs->clear_strobe = 0;
|
||||
*t = 0 ;
|
||||
}
|
||||
|
||||
/***************************************************************** Detection */
|
||||
int __init fastlane_esp_detect(struct scsi_host_template *tpnt)
|
||||
{
|
||||
struct NCR_ESP *esp;
|
||||
struct zorro_dev *z = NULL;
|
||||
unsigned long address;
|
||||
|
||||
if ((z = zorro_find_device(ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, z))) {
|
||||
unsigned long board = z->resource.start;
|
||||
if (request_mem_region(board+FASTLANE_ESP_ADDR,
|
||||
sizeof(struct ESP_regs), "NCR53C9x")) {
|
||||
/* Check if this is really a fastlane controller. The problem
|
||||
* is that also the cyberstorm and blizzard controllers use
|
||||
* this ID value. Fortunately only Fastlane maps in Z3 space
|
||||
*/
|
||||
if (board < 0x1000000) {
|
||||
goto err_release;
|
||||
}
|
||||
esp = esp_allocate(tpnt, (void *)board + FASTLANE_ESP_ADDR, 0);
|
||||
|
||||
/* Do command transfer with programmed I/O */
|
||||
esp->do_pio_cmds = 1;
|
||||
|
||||
/* Required functions */
|
||||
esp->dma_bytes_sent = &dma_bytes_sent;
|
||||
esp->dma_can_transfer = &dma_can_transfer;
|
||||
esp->dma_dump_state = &dma_dump_state;
|
||||
esp->dma_init_read = &dma_init_read;
|
||||
esp->dma_init_write = &dma_init_write;
|
||||
esp->dma_ints_off = &dma_ints_off;
|
||||
esp->dma_ints_on = &dma_ints_on;
|
||||
esp->dma_irq_p = &dma_irq_p;
|
||||
esp->dma_ports_p = &dma_ports_p;
|
||||
esp->dma_setup = &dma_setup;
|
||||
|
||||
/* Optional functions */
|
||||
esp->dma_barrier = 0;
|
||||
esp->dma_drain = 0;
|
||||
esp->dma_invalidate = 0;
|
||||
esp->dma_irq_entry = 0;
|
||||
esp->dma_irq_exit = &dma_irq_exit;
|
||||
esp->dma_led_on = &dma_led_on;
|
||||
esp->dma_led_off = &dma_led_off;
|
||||
esp->dma_poll = 0;
|
||||
esp->dma_reset = 0;
|
||||
|
||||
/* Initialize the portBits (enable IRQs) */
|
||||
ctrl_data = (FASTLANE_DMA_FCODE |
|
||||
#ifndef NODMAIRQ
|
||||
FASTLANE_DMA_EDI |
|
||||
#endif
|
||||
FASTLANE_DMA_ESI);
|
||||
|
||||
|
||||
/* SCSI chip clock */
|
||||
esp->cfreq = 40000000;
|
||||
|
||||
|
||||
/* Map the physical address space into virtual kernel space */
|
||||
address = (unsigned long)
|
||||
z_ioremap(board, z->resource.end-board+1);
|
||||
|
||||
if(!address){
|
||||
printk("Could not remap Fastlane controller memory!");
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
|
||||
/* The DMA registers on the Fastlane are mapped
|
||||
* relative to the device (i.e. in the same Zorro
|
||||
* I/O block).
|
||||
*/
|
||||
esp->dregs = (void *)(address + FASTLANE_DMA_ADDR);
|
||||
|
||||
/* ESP register base */
|
||||
esp->eregs = (struct ESP_regs *)(address + FASTLANE_ESP_ADDR);
|
||||
|
||||
/* Board base */
|
||||
esp->edev = (void *) address;
|
||||
|
||||
/* Set the command buffer */
|
||||
esp->esp_command = cmd_buffer;
|
||||
esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer);
|
||||
|
||||
esp->irq = IRQ_AMIGA_PORTS;
|
||||
esp->slot = board+FASTLANE_ESP_ADDR;
|
||||
if (request_irq(IRQ_AMIGA_PORTS, esp_intr, IRQF_SHARED,
|
||||
"Fastlane SCSI", esp->ehost)) {
|
||||
printk(KERN_WARNING "Fastlane: Could not get IRQ%d, aborting.\n", IRQ_AMIGA_PORTS);
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
/* Controller ID */
|
||||
esp->scsi_id = 7;
|
||||
|
||||
/* We don't have a differential SCSI-bus. */
|
||||
esp->diff = 0;
|
||||
|
||||
dma_clear(esp);
|
||||
esp_initialize(esp);
|
||||
|
||||
printk("ESP: Total of %d ESP hosts found, %d actually in use.\n", nesps, esps_in_use);
|
||||
esps_running = esps_in_use;
|
||||
return esps_in_use;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_unmap:
|
||||
z_iounmap((void *)address);
|
||||
err_unregister:
|
||||
scsi_unregister (esp->ehost);
|
||||
err_release:
|
||||
release_mem_region(z->resource.start+FASTLANE_ESP_ADDR,
|
||||
sizeof(struct ESP_regs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************* DMA Functions */
|
||||
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
|
||||
{
|
||||
/* Since the Fastlane DMA is fully dedicated to the ESP chip,
|
||||
* the number of bytes sent (to the ESP chip) equals the number
|
||||
* of bytes in the FIFO - there is no buffering in the DMA controller.
|
||||
* XXXX Do I read this right? It is from host to ESP, right?
|
||||
*/
|
||||
return fifo_count;
|
||||
}
|
||||
|
||||
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
|
||||
{
|
||||
unsigned long sz = sp->SCp.this_residual;
|
||||
if(sz > 0xfffc)
|
||||
sz = 0xfffc;
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void dma_dump_state(struct NCR_ESP *esp)
|
||||
{
|
||||
ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
|
||||
esp->esp_id, ((struct fastlane_dma_registers *)
|
||||
(esp->dregs))->cond_reg));
|
||||
ESPLOG(("intreq:<%04x>, intena:<%04x>\n",
|
||||
amiga_custom.intreqr, amiga_custom.intenar));
|
||||
}
|
||||
|
||||
static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
struct fastlane_dma_registers *dregs =
|
||||
(struct fastlane_dma_registers *) (esp->dregs);
|
||||
unsigned long *t;
|
||||
|
||||
cache_clear(addr, length);
|
||||
|
||||
dma_clear(esp);
|
||||
|
||||
t = (unsigned long *)((addr & 0x00ffffff) + esp->edev);
|
||||
|
||||
dregs->clear_strobe = 0;
|
||||
*t = addr;
|
||||
|
||||
ctrl_data = (ctrl_data & FASTLANE_DMA_MASK) | FASTLANE_DMA_ENABLE;
|
||||
dregs->ctrl_reg = ctrl_data;
|
||||
}
|
||||
|
||||
static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
|
||||
{
|
||||
struct fastlane_dma_registers *dregs =
|
||||
(struct fastlane_dma_registers *) (esp->dregs);
|
||||
unsigned long *t;
|
||||
|
||||
cache_push(addr, length);
|
||||
|
||||
dma_clear(esp);
|
||||
|
||||
t = (unsigned long *)((addr & 0x00ffffff) + (esp->edev));
|
||||
|
||||
dregs->clear_strobe = 0;
|
||||
*t = addr;
|
||||
|
||||
ctrl_data = ((ctrl_data & FASTLANE_DMA_MASK) |
|
||||
FASTLANE_DMA_ENABLE |
|
||||
FASTLANE_DMA_WRITE);
|
||||
dregs->ctrl_reg = ctrl_data;
|
||||
}
|
||||
|
||||
|
||||
static void dma_ints_off(struct NCR_ESP *esp)
|
||||
{
|
||||
disable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static void dma_ints_on(struct NCR_ESP *esp)
|
||||
{
|
||||
enable_irq(esp->irq);
|
||||
}
|
||||
|
||||
static void dma_irq_exit(struct NCR_ESP *esp)
|
||||
{
|
||||
struct fastlane_dma_registers *dregs =
|
||||
(struct fastlane_dma_registers *) (esp->dregs);
|
||||
|
||||
dregs->ctrl_reg = ctrl_data & ~(FASTLANE_DMA_EDI|FASTLANE_DMA_ESI);
|
||||
#ifdef __mc68000__
|
||||
nop();
|
||||
#endif
|
||||
dregs->ctrl_reg = ctrl_data;
|
||||
}
|
||||
|
||||
static int dma_irq_p(struct NCR_ESP *esp)
|
||||
{
|
||||
struct fastlane_dma_registers *dregs =
|
||||
(struct fastlane_dma_registers *) (esp->dregs);
|
||||
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 (
|
||||
#ifndef NODMAIRQ
|
||||
(dma_status & FASTLANE_DMA_CREQ) &&
|
||||
#endif
|
||||
(!(dma_status & FASTLANE_DMA_MINT)) &&
|
||||
(esp_read(((struct ESP_regs *) (esp->eregs))->esp_status) & ESP_STAT_INTR));
|
||||
}
|
||||
|
||||
static void dma_led_off(struct NCR_ESP *esp)
|
||||
{
|
||||
ctrl_data &= ~FASTLANE_DMA_LED;
|
||||
((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
|
||||
}
|
||||
|
||||
static void dma_led_on(struct NCR_ESP *esp)
|
||||
{
|
||||
ctrl_data |= FASTLANE_DMA_LED;
|
||||
((struct fastlane_dma_registers *)(esp->dregs))->ctrl_reg = ctrl_data;
|
||||
}
|
||||
|
||||
static int dma_ports_p(struct NCR_ESP *esp)
|
||||
{
|
||||
return ((amiga_custom.intenar) & IF_PORTS);
|
||||
}
|
||||
|
||||
static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
|
||||
{
|
||||
/* On the Sparc, DMA_ST_WRITE means "move data from device to memory"
|
||||
* so when (write) is true, it actually means READ!
|
||||
*/
|
||||
if(write){
|
||||
dma_init_read(esp, addr, count);
|
||||
} else {
|
||||
dma_init_write(esp, addr, count);
|
||||
}
|
||||
}
|
||||
|
||||
#define HOSTS_C
|
||||
|
||||
int fastlane_esp_release(struct Scsi_Host *instance)
|
||||
{
|
||||
#ifdef MODULE
|
||||
unsigned long address = (unsigned long)((struct NCR_ESP *)instance->hostdata)->edev;
|
||||
esp_deallocate((struct NCR_ESP *)instance->hostdata);
|
||||
esp_release();
|
||||
release_mem_region(address, sizeof(struct ESP_regs));
|
||||
free_irq(IRQ_AMIGA_PORTS, esp_intr);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static struct scsi_host_template driver_template = {
|
||||
.proc_name = "esp-fastlane",
|
||||
.proc_info = esp_proc_info,
|
||||
.name = "Fastlane SCSI",
|
||||
.detect = fastlane_esp_detect,
|
||||
.slave_alloc = esp_slave_alloc,
|
||||
.slave_destroy = esp_slave_destroy,
|
||||
.release = fastlane_esp_release,
|
||||
.queuecommand = esp_queue,
|
||||
.eh_abort_handler = esp_abort,
|
||||
.eh_bus_reset_handler = esp_reset,
|
||||
.can_queue = 7,
|
||||
.this_id = 7,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.cmd_per_lun = 1,
|
||||
.use_clustering = ENABLE_CLUSTERING
|
||||
};
|
||||
|
||||
#include "scsi_module.c"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,194 +0,0 @@
|
||||
/* -*- mode: asm -*-
|
||||
* Due to problems while transferring data I've put these routines as assembly
|
||||
* code.
|
||||
* Since I'm no PPC assembler guru, the code is just the assembler version of
|
||||
|
||||
int oktag_to_io(long *paddr,long *addr,long len)
|
||||
{
|
||||
long *addr2 = addr;
|
||||
for(len=(len+sizeof(long)-1)/sizeof(long);len--;)
|
||||
*paddr = *addr2++;
|
||||
return addr2 - addr;
|
||||
}
|
||||
|
||||
int oktag_from_io(long *addr,long *paddr,long len)
|
||||
{
|
||||
long *addr2 = addr;
|
||||
for(len=(len+sizeof(long)-1)/sizeof(long);len--;)
|
||||
*addr2++ = *paddr;
|
||||
return addr2 - addr;
|
||||
}
|
||||
|
||||
* assembled using gcc -O2 -S, with two exception catch points where data
|
||||
* is moved to/from the IO register.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef CONFIG_APUS
|
||||
|
||||
.file "oktagon_io.c"
|
||||
|
||||
gcc2_compiled.:
|
||||
/*
|
||||
.section ".text"
|
||||
*/
|
||||
.align 2
|
||||
.globl oktag_to_io
|
||||
.type oktag_to_io,@function
|
||||
oktag_to_io:
|
||||
addi 5,5,3
|
||||
srwi 5,5,2
|
||||
cmpwi 1,5,0
|
||||
mr 9,3
|
||||
mr 3,4
|
||||
addi 5,5,-1
|
||||
bc 12,6,.L3
|
||||
.L5:
|
||||
cmpwi 1,5,0
|
||||
lwz 0,0(3)
|
||||
addi 3,3,4
|
||||
addi 5,5,-1
|
||||
exp1: stw 0,0(9)
|
||||
bc 4,6,.L5
|
||||
.L3:
|
||||
ret1: subf 3,4,3
|
||||
srawi 3,3,2
|
||||
blr
|
||||
.Lfe1:
|
||||
.size oktag_to_io,.Lfe1-oktag_to_io
|
||||
.align 2
|
||||
.globl oktag_from_io
|
||||
.type oktag_from_io,@function
|
||||
oktag_from_io:
|
||||
addi 5,5,3
|
||||
srwi 5,5,2
|
||||
cmpwi 1,5,0
|
||||
mr 9,3
|
||||
addi 5,5,-1
|
||||
bc 12,6,.L9
|
||||
.L11:
|
||||
cmpwi 1,5,0
|
||||
exp2: lwz 0,0(4)
|
||||
addi 5,5,-1
|
||||
stw 0,0(3)
|
||||
addi 3,3,4
|
||||
bc 4,6,.L11
|
||||
.L9:
|
||||
ret2: subf 3,9,3
|
||||
srawi 3,3,2
|
||||
blr
|
||||
.Lfe2:
|
||||
.size oktag_from_io,.Lfe2-oktag_from_io
|
||||
.ident "GCC: (GNU) egcs-2.90.29 980515 (egcs-1.0.3 release)"
|
||||
|
||||
/*
|
||||
* Exception table.
|
||||
* Second longword shows where to jump when an exception at the addr the first
|
||||
* longword is pointing to is caught.
|
||||
*/
|
||||
|
||||
.section __ex_table,"a"
|
||||
.align 2
|
||||
oktagon_except:
|
||||
.long exp1,ret1
|
||||
.long exp2,ret2
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
The code which follows is for 680x0 based assembler and is meant for
|
||||
Linux/m68k. It was created by cross compiling the code using the
|
||||
instructions given above. I then added the four labels used in the
|
||||
exception handler table at the bottom of this file.
|
||||
- Kevin <kcozens@interlog.com>
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_AMIGA
|
||||
|
||||
.file "oktagon_io.c"
|
||||
.version "01.01"
|
||||
gcc2_compiled.:
|
||||
.text
|
||||
.align 2
|
||||
.globl oktag_to_io
|
||||
.type oktag_to_io,@function
|
||||
oktag_to_io:
|
||||
link.w %a6,#0
|
||||
move.l %d2,-(%sp)
|
||||
move.l 8(%a6),%a1
|
||||
move.l 12(%a6),%d1
|
||||
move.l %d1,%a0
|
||||
move.l 16(%a6),%d0
|
||||
addq.l #3,%d0
|
||||
lsr.l #2,%d0
|
||||
subq.l #1,%d0
|
||||
moveq.l #-1,%d2
|
||||
cmp.l %d0,%d2
|
||||
jbeq .L3
|
||||
.L5:
|
||||
exp1:
|
||||
move.l (%a0)+,(%a1)
|
||||
dbra %d0,.L5
|
||||
clr.w %d0
|
||||
subq.l #1,%d0
|
||||
jbcc .L5
|
||||
.L3:
|
||||
ret1:
|
||||
move.l %a0,%d0
|
||||
sub.l %d1,%d0
|
||||
asr.l #2,%d0
|
||||
move.l -4(%a6),%d2
|
||||
unlk %a6
|
||||
rts
|
||||
|
||||
.Lfe1:
|
||||
.size oktag_to_io,.Lfe1-oktag_to_io
|
||||
.align 2
|
||||
.globl oktag_from_io
|
||||
.type oktag_from_io,@function
|
||||
oktag_from_io:
|
||||
link.w %a6,#0
|
||||
move.l %d2,-(%sp)
|
||||
move.l 8(%a6),%d1
|
||||
move.l 12(%a6),%a1
|
||||
move.l %d1,%a0
|
||||
move.l 16(%a6),%d0
|
||||
addq.l #3,%d0
|
||||
lsr.l #2,%d0
|
||||
subq.l #1,%d0
|
||||
moveq.l #-1,%d2
|
||||
cmp.l %d0,%d2
|
||||
jbeq .L9
|
||||
.L11:
|
||||
exp2:
|
||||
move.l (%a1),(%a0)+
|
||||
dbra %d0,.L11
|
||||
clr.w %d0
|
||||
subq.l #1,%d0
|
||||
jbcc .L11
|
||||
.L9:
|
||||
ret2:
|
||||
move.l %a0,%d0
|
||||
sub.l %d1,%d0
|
||||
asr.l #2,%d0
|
||||
move.l -4(%a6),%d2
|
||||
unlk %a6
|
||||
rts
|
||||
.Lfe2:
|
||||
.size oktag_from_io,.Lfe2-oktag_from_io
|
||||
.ident "GCC: (GNU) 2.7.2.1"
|
||||
|
||||
/*
|
||||
* Exception table.
|
||||
* Second longword shows where to jump when an exception at the addr the first
|
||||
* longword is pointing to is caught.
|
||||
*/
|
||||
|
||||
.section __ex_table,"a"
|
||||
.align 2
|
||||
oktagon_except:
|
||||
.long exp1,ret1
|
||||
.long exp2,ret2
|
||||
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user