summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/dec_esp.c183
-rw-r--r--drivers/scsi/dec_esp.h7
-rw-r--r--include/asm-mips/dec/ioasic_ints.h6
3 files changed, 179 insertions, 17 deletions
diff --git a/drivers/scsi/dec_esp.c b/drivers/scsi/dec_esp.c
index f1c56cd16..47fc0037e 100644
--- a/drivers/scsi/dec_esp.c
+++ b/drivers/scsi/dec_esp.c
@@ -1,7 +1,9 @@
/*
* dec_esp.c: Driver for SCSI chips on IOASIC based TURBOchannel DECstations
+ * and TURBOchannel PMAZ-A cards
*
* TURBOchannel changes by Harald Koerfgen
+ * PMAZ-A support by David Airlie
*
* based on jazz_esp.c:
* Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
@@ -38,21 +40,43 @@
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
static void dma_drain(struct NCR_ESP *esp);
+static void pmaz_dma_drain(struct NCR_ESP *esp);
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 vaddress, int length);
static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
static void dma_ints_off(struct NCR_ESP *esp);
static void dma_ints_on(struct NCR_ESP *esp);
+static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length);
+static void pmaz_dma_ints_off(struct NCR_ESP *esp);
+static void pmaz_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 void dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp);
static void dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+static void pmaz_dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write);
+static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp);
+// static void pmaz_dma_mmu_get_scsi_sgl(struct NCR_ESP *esp, Scsi_Cmnd * sp);
static void dma_advance_sg(Scsi_Cmnd * sp);
+#define TC_ESP_RAM_SIZE 0x20000
+#define ESP_TGT_DMA_SIZE ((TC_ESP_RAM_SIZE/7) & ~(sizeof(int)-1))
+#define ESP_NCMD 7
+
+#define TC_ESP_DMAR_MASK 0x1ffff
+#define TC_ESP_DMAR_WRITE 0x80000000
+#define TC_ESP_DMA_ADDR(x) ((unsigned)(x) & TC_ESP_DMAR_MASK)
+
+volatile unsigned char *scsi_pmaz_dma_ptrs_tc[ESP_NCMD];
+unsigned char scsi_pmaz_dma_buff_used[ESP_NCMD];
+unsigned char scsi_cur_buff = 1; /* Leave space for command buffer */
+__u32 esp_virt_buffer;
+int scsi_current_length = 0;
volatile unsigned char cmd_buffer[16];
+volatile unsigned char pmaz_cmd_buffer[16];
/* This is where all commands are put
* before they are trasfered to the ESP chip
* via PIO.
@@ -65,6 +89,8 @@ volatile unsigned long *ioasic_ssr;
volatile unsigned long *scsi_sdr0;
volatile unsigned long *scsi_sdr1;
+volatile int *scsi_pmaz_dma_ptr_tc;
+
static void scsi_dma_int(int, void *, struct pt_regs *);
/***************************************************************** Detection */
@@ -72,6 +98,9 @@ int dec_esp_detect(Scsi_Host_Template * tpnt)
{
struct NCR_ESP *esp;
struct ConfigDev *esp_dev;
+ int slot, i;
+ unsigned long mem_start;
+ volatile unsigned char *buffer;
if (IOASIC) {
esp_dev = 0;
@@ -143,21 +172,88 @@ int dec_esp_detect(Scsi_Host_Template * tpnt)
request_irq(SCSI_DMA_INT, scsi_dma_int, SA_INTERRUPT, "JUNKIO SCSI DMA",
NULL);
- /*
- * FIXME, look if the scsi id is availabe from NVRAM
- */
esp->scsi_id = 7;
/* Check for differential SCSI-bus */
- /* What is this stuff? */
esp->diff = 0;
esp_initialize(esp);
+ }
+
+ if (TURBOCHANNEL) {
+ while ((slot = search_tc_card("PMAZ-AA")) >= 0) {
+ claim_tc_card(slot);
+ mem_start = get_tc_base_addr(slot);
+
+ esp_dev = 0;
+ esp = esp_allocate(tpnt, (void *) esp_dev);
+
+ esp->dregs = 0;
+ esp->eregs = (struct ESP_regs *) (mem_start + DEC_SCSI_SREG);
+ esp->do_pio_cmds = 1;
+
+ /* Set the command buffer */
+ esp->esp_command = (volatile unsigned char *) pmaz_cmd_buffer;
+
+ /* get virtual dma address for command buffer */
+ esp->esp_command_dvma = (__u32) KSEG0ADDR((volatile unsigned char *) pmaz_cmd_buffer);
+
+ buffer = (volatile unsigned char *) (mem_start + DEC_SCSI_SRAM);
+
+ scsi_pmaz_dma_ptr_tc = (volatile int *) (mem_start + DEC_SCSI_DMAREG);
+
+ for (i = 0; i < ESP_NCMD; i++) {
+ scsi_pmaz_dma_ptrs_tc[i] = (volatile unsigned char *) (buffer + ESP_TGT_DMA_SIZE * i);
+ }
+
+ scsi_pmaz_dma_buff_used[0] = 1;
+
+ esp->cfreq = get_tc_speed();
+
+ esp->irq = get_tc_irq_nr(slot);
+
+ /* 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 = &pmaz_dma_init_read;
+ esp->dma_init_write = &pmaz_dma_init_write;
+ esp->dma_ints_off = &pmaz_dma_ints_off;
+ esp->dma_ints_on = &pmaz_dma_ints_on;
+ esp->dma_irq_p = &dma_irq_p;
+ esp->dma_ports_p = &dma_ports_p;
+ esp->dma_setup = &pmaz_dma_setup;
+
+ /* Optional functions */
+ esp->dma_barrier = 0;
+ esp->dma_drain = &pmaz_dma_drain;
+ esp->dma_invalidate = 0;
+ esp->dma_irq_entry = 0;
+ esp->dma_irq_exit = 0;
+ esp->dma_poll = 0;
+ esp->dma_reset = 0;
+ esp->dma_led_off = 0;
+ esp->dma_led_on = 0;
+
+ esp->dma_mmu_get_scsi_one = pmaz_dma_mmu_get_scsi_one;
+ esp->dma_mmu_get_scsi_sgl = 0;
+ esp->dma_mmu_release_scsi_one = 0;
+ esp->dma_mmu_release_scsi_sgl = 0;
+ esp->dma_advance_sg = 0;
+
+ request_irq(esp->irq, esp_intr, SA_INTERRUPT, "PMAZ-AA", NULL);
+ esp->scsi_id = 7;
+ esp->diff = 0;
+ esp_initialize(esp);
+ }
+ }
+
+ if(nesps) {
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;
- }
+ } else
return 0;
}
@@ -172,18 +268,18 @@ static void scsi_dma_int(int irq, void *dev_id, struct pt_regs *regs)
*scsi_next_ptr = ((*scsi_dma_ptr + PAGE_SIZE) & PAGE_MASK) << 3;
*isr &= ~SCSI_PTR_LOADED;
} else {
- printk("Got unexpected SCSI DMA Interrupt! < ");
if (*isr & SCSI_PAGOVRRUN)
- printk("SCSI_PAGOVRRUN ");
- if (*isr & SCSI_DMA_MEMRDERR)
+ *isr &= ~SCSI_PAGOVRRUN;
+ if (*isr & SCSI_DMA_MEMRDERR) {
+ printk("Got unexpected SCSI DMA Interrupt! < ");
printk("SCSI_DMA_MEMRDERR ");
printk(">\n");
-// panic("stop");
- *isr &= ~(SCSI_PAGOVRRUN || SCSI_DMA_MEMRDERR);
+ *isr &= ~SCSI_DMA_MEMRDERR;
+ }
}
/*
- * This driver will only work on IOASIC machines
+ * This routine will only work on IOASIC machines
* so we can avoid an indirect function call here
* and flush the writeback buffer the fast way
*/
@@ -198,13 +294,13 @@ static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
static void dma_drain(struct NCR_ESP *esp)
{
- unsigned long nw;
+ unsigned long nw = *scsi_scr;
unsigned short *p = KSEG1ADDR((unsigned short *) ((*scsi_dma_ptr) >> 3));
/*
* Is there something in the dma buffers left?
*/
- if (nw = *scsi_scr) {
+ if (nw) {
switch (nw) {
case 1:
*p = (unsigned short) *scsi_sdr0;
@@ -225,6 +321,12 @@ static void dma_drain(struct NCR_ESP *esp)
}
}
+static void pmaz_dma_drain(struct NCR_ESP *esp)
+{
+ memcpy((volatile void *) (KSEG0ADDR(esp_virt_buffer)),
+ (void *) scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], scsi_current_length);
+}
+
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp)
{
return sp->SCp.this_residual;;
@@ -298,6 +400,33 @@ static void dma_ints_on(struct NCR_ESP *esp)
enable_irq(SCSI_DMA_INT);
}
+static void pmaz_dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+
+ if (length > ESP_TGT_DMA_SIZE)
+ length = ESP_TGT_DMA_SIZE;
+
+ *scsi_pmaz_dma_ptr_tc = TC_ESP_DMA_ADDR(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff]);
+ esp_virt_buffer = vaddress;
+ scsi_current_length = length;
+}
+
+static void pmaz_dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+ memcpy(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff], KSEG0ADDR((void *) vaddress), length);
+
+ *scsi_pmaz_dma_ptr_tc = TC_ESP_DMAR_WRITE | TC_ESP_DMA_ADDR(scsi_pmaz_dma_ptrs_tc[scsi_cur_buff]);
+
+}
+
+static void pmaz_dma_ints_off(struct NCR_ESP *esp)
+{
+}
+
+static void pmaz_dma_ints_on(struct NCR_ESP *esp)
+{
+}
+
static int dma_irq_p(struct NCR_ESP *esp)
{
return (esp->eregs->esp_status & ESP_STAT_INTR);
@@ -324,6 +453,34 @@ static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
}
}
+static void pmaz_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) {
+ pmaz_dma_init_read(esp, addr, count);
+ } else {
+ pmaz_dma_init_write(esp, addr, count);
+ }
+}
+
+static void pmaz_dma_mmu_release_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+ int x;
+ for (x = 1; x < 6; x++)
+ if (sp->SCp.have_data_in == PHYSADDR(scsi_pmaz_dma_ptrs_tc[x]))
+ scsi_pmaz_dma_buff_used[x] = 0;
+}
+
+
+static void pmaz_dma_mmu_get_scsi_one(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+ sp->SCp.have_data_in = (int) sp->SCp.ptr =
+ (char *) KSEG0ADDR((sp->request_buffer));
+}
+
/*
* These aren't used yet
*/
diff --git a/drivers/scsi/dec_esp.h b/drivers/scsi/dec_esp.h
index 15a7bc14b..aae3a4a44 100644
--- a/drivers/scsi/dec_esp.h
+++ b/drivers/scsi/dec_esp.h
@@ -1,6 +1,7 @@
/* dec_esp.h: Defines and structures for the JAZZ SCSI driver.
*
* DECstation changes Copyright (C) 1998 Harald Koerfgen
+ * and David Airlie
*
* based on jazz_esp.h:
* Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
@@ -13,6 +14,10 @@
#include "NCR53C9x.h"
+#define DEC_SCSI_SREG 0
+#define DEC_SCSI_DMAREG 0x40000
+#define DEC_SCSI_SRAM 0x80000
+#define DEC_SCSI_DIAG 0xC0000
extern int dec_esp_detect(struct SHT *);
extern const char *esp_info(struct Scsi_Host *);
@@ -26,7 +31,7 @@ extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
#define SCSI_DEC_ESP { \
proc_dir: &proc_scsi_esp, \
proc_info: &esp_proc_info, \
- name: "PMAZ-AA", \
+ name: "NCR53C94", \
detect: dec_esp_detect, \
info: esp_info, \
command: esp_command, \
diff --git a/include/asm-mips/dec/ioasic_ints.h b/include/asm-mips/dec/ioasic_ints.h
index e28e334b2..bd184d1c4 100644
--- a/include/asm-mips/dec/ioasic_ints.h
+++ b/include/asm-mips/dec/ioasic_ints.h
@@ -68,9 +68,9 @@
#define MAXINE_DTOP_RECV 0x00000001 /* DTI Recv-Available */
/* kn03 aka 3max+ aka DS5000_2x0 */
-#define KN03_TC2 0x00004000
-#define KN03_TC1 0x00002000
-#define KN03_TC0 0x00001000
+#define KN03_TC2 0x00002000
+#define KN03_TC1 0x00001000
+#define KN03_TC0 0x00000800
#define KN03_SCSI_FIFO 0x00000004 /* ??? Info from Mach */
/*