linux-mips-fnet
[Top] [All Lists]

patch for pmaz_esp support

To: linux-mips@fnet.fr
Subject: patch for pmaz_esp support
From: Dave Airlie <airlied@csn.ul.ie>
Date: Wed, 19 May 1999 17:06:18 +0100 (IST)
Hi,
        Please find attached the diff for the PMAZ-AA non-IOASIC
Turbochannel SCSI adapter :-) ... it doesn't fully work, and I'm still
dodgy about parts of it particularly anywhere I use the KSEG macros, 

The diff is against my cvs tree of today, so you may need to read over the
diff before applying it as I think I see a few spurious wbflush things ..

Dave.

------------ David Airlie, David.Airlie@ul.ie,airlied@skynet --------
Telecommunications Research Centre, ECE Dept, University of Limerick \
http://www.csn.ul.ie/~airlied   -- Telecommunications Researcher      \
--- TEL: +353-61-202695 -----------------------------------------------
diff -urwP -x *CVS* linux/arch/mips/config.in 
/home/airlied/cvs/linux/arch/mips/config.in
--- linux/arch/mips/config.in   Wed May 19 15:20:30 1999
+++ /home/airlied/cvs/linux/arch/mips/config.in Tue May 18 11:27:35 1999
@@ -156,7 +156,8 @@
                dep_tristate 'SGI wd93 Scsi Driver' CONFIG_SCSI_SGIWD93 
$CONFIG_SCSI
        else
                        if [ "$CONFIG_TC" = "y" ]; then
-                               dep_tristate 'DEC NCR53C94 Scsi Driver' 
CONFIG_SCSI_DECNCR $CONFIG_SCSI
+                               dep_tristate 'DEC IOASIC NCR53C94 Scsi Driver' 
CONFIG_SCSI_DECNCR $CONFIG_SCSI
+                               dep_tristate 'DEC PMAZ-AA NCR Scsi Driver' 
CONFIG_SCSI_DECPMAZ $CONFIG_SCSI
                        fi
                        dep_tristate 'DEC SII Scsi Driver' CONFIG_SCSI_DECSII 
$CONFIG_SCSI
                fi
diff -urwP -x *CVS* linux/drivers/scsi/Makefile 
/home/airlied/cvs/linux/drivers/scsi/Makefile
--- linux/drivers/scsi/Makefile Wed May 19 15:30:28 1999
+++ /home/airlied/cvs/linux/drivers/scsi/Makefile       Tue May 18 11:30:01 1999
@@ -592,6 +592,10 @@
 L_OBJS += NCR53C9x.o dec_esp.o
 endif
 
+ifeq ($(CONFIG_SCSI_DECPMAZ),y)
+L_OBJS += NCR53C9x.o pmaz_esp.o
+endif
+
 include $(TOPDIR)/Rules.make
 
 53c8xx_d.h: 53c7,8xx.scr script_asm.pl
diff -urwP -x *CVS* linux/drivers/scsi/NCR53C9x.c 
/home/airlied/cvs/linux/drivers/scsi/NCR53C9x.c
--- linux/drivers/scsi/NCR53C9x.c       Wed May 19 15:30:30 1999
+++ /home/airlied/cvs/linux/drivers/scsi/NCR53C9x.c     Wed May 19 15:44:23 1999
@@ -9,6 +9,10 @@
  *
  * Set up to use GETREG/SETREG (preprocessor macros in NCR53c9x.h) by
  * Tymm Twillman (tymm@coe.missouri.edu)
+ *
+ * Support for IOASIC DECstations by
+ * Harald Koerfgen (harald@unix-ag.org) 
+ * also changes by David Airlie (airlied@linux.ie)
  */
 
 /* TODO:
@@ -33,6 +37,14 @@
 
 #include <linux/init.h>
 
+#ifdef CONFIG_DECSTATION
+#include <asm/wbflush.h>
+#else
+#define wbflush()
+#endif
+
+
+
 #include "scsi.h"
 #include "hosts.h"
 #include "NCR53C9x.h"
@@ -302,6 +314,7 @@
        esp->espcmdent = (esp->espcmdent + 1) & 31;
 #endif
        SETREG(eregs->esp_cmnd, cmd);
+       wbflush();
 }
 
 /* How we use the various Linux SCSI data structures for operation.
@@ -437,11 +450,13 @@
 
        /* Reload the configuration registers */
        SETREG(eregs->esp_cfact, esp->cfact);
+       wbflush();
        SETREG(eregs->esp_stp, 0);
        SETREG(eregs->esp_soff, 0);
        SETREG(eregs->esp_timeo, esp->neg_defp);
        esp->max_period = (esp->max_period + 3)>>2;
        esp->min_period = (esp->min_period + 3)>>2;
+       wbflush();
 
        SETREG(eregs->esp_cfg1, esp->config1);
        switch(esp->erev) {
@@ -492,6 +507,7 @@
                panic("esp: what could it be... I wonder...");
                break;
        };
+       wbflush();
 
        /* Eat any bitrot in the chip */
        trash = GETREG(eregs->esp_intrpt);
@@ -515,6 +531,7 @@
        esp_cmd(esp, eregs, ESP_CMD_RS);
        udelay(400);
        SETREG(eregs->esp_cfg1, esp->config1);
+       wbflush();
 
        /* Eat any bitrot in the chip and we are done... */
        trash = GETREG(eregs->esp_intrpt);
@@ -638,6 +655,7 @@
        esp->ctick = ESP_TICK(ccf, esp->ccycle);
        esp->neg_defp = ESP_NEG_DEFP(fmhz, ccf);
        esp->sync_defp = SYNC_DEFP_SLOW;
+       esp->ccf = ccf;
 
        printk("SCSI ID %d  Clock %d MHz CCF=%d Time-Out %d ",
               esp->scsi_id, (esp->cfreq / 1000000),
@@ -655,6 +673,7 @@
        esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
        esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
        SETREG(eregs->esp_cfg2, esp->config2);
+       wbflush();
 #ifndef SYMBIOS_HACK
        if((GETREG(eregs->esp_cfg2) & ~(ESP_CONFIG2_MAGIC)) !=
           (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
@@ -667,6 +686,7 @@
                SETREG(eregs->esp_cfg3, 0);
                esp->config3[0] = 5;
                SETREG(eregs->esp_cfg3, esp->config3[0]);
+               wbflush();
 #ifndef SYMBIOS_HACK
                if(GETREG(eregs->esp_cfg3) != 5) {
                        printk("NCR53C90A(esp100a) detected\n");
@@ -695,6 +715,7 @@
                                esp->config2 = 0;
                                SETREG(eregs->esp_cfg2, esp->config2);
                        }
+                       wbflush();
                }
 #endif
        }                               
@@ -1201,10 +1222,14 @@
 
        /* HME sucks... */
        if(esp->erev == fashme)
+         {
                SETREG(eregs->esp_busid, (target & 0xf) |
                        (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT));
+         }
        else
+         {
                SETREG(eregs->esp_busid, (target & 7));
+         }
        SETREG(eregs->esp_soff, SDptr->sync_max_offset);
        SETREG(eregs->esp_stp, SDptr->sync_min_period);
        if(esp->erev > esp100a)
@@ -1274,6 +1299,7 @@
                else
                        SCpnt->SCp.have_data_in = (int) SCpnt->SCp.ptr =
                                (char *) virt_to_phys(SCpnt->request_buffer);
+               /*      printk("scsi_queue: %d = %p = %p", 
SCpnt->SCp.have_data_in, SCpnt->SCp.ptr, SCpnt->request_buffer); */
        } else {
                ESPQUEUE(("use_sg "));
 #ifdef DEBUG_ESP_SG
@@ -1672,10 +1698,13 @@
 {
        SETREG(eregs->esp_tclow, (cnt & 0xff));
        SETREG(eregs->esp_tcmed, ((cnt >> 8) & 0xff));
+       /* NetBSD had this... - Dave */
+       SETREG(eregs->esp_cmnd, ESP_CMD_NULL | ESP_CMD_DMA);
        if(hme) {
                SETREG(eregs->fas_rlo, 0);
                SETREG(eregs->fas_rhi, 0);
        }
+       wbflush();
 }
 
 static inline int esp_getcount(struct ESP_regs *eregs)
@@ -1831,6 +1860,7 @@
                SETREG(eregs->esp_busid, (sp->target & 0xf) |
                        (ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT));
        esp->current_SC = sp;
+       wbflush();
 }
 
 /* This will place the current working command back into the issue queue
@@ -2951,6 +2986,7 @@
                        }
                        SETREG(eregs->esp_soff, SDptr->sync_min_period);
                        SETREG(eregs->esp_stp, SDptr->sync_max_offset);
+                       wbflush();
 
                        ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n",
                                SDptr->sync_max_offset,
@@ -2975,6 +3011,7 @@
                                esp->config3[SCptr->target] &= ~bit;
                                SETREG(eregs->esp_cfg3,
                                 esp->config3[SCptr->target]);
+                               wbflush();
                        }
                }
 
@@ -3025,6 +3062,7 @@
                                esp->config3[SCptr->target] &= 
~(ESP_CONFIG3_EWIDE);
                        }
                        SETREG(eregs->esp_cfg3, esp->config3[SCptr->target]);
+                       wbflush();
 
                        /* Regardless, next try for sync transfers. */
                        build_sync_nego_msg(esp, esp->sync_defp, 15);
diff -urwP -x *CVS* linux/drivers/scsi/hosts.c 
/home/airlied/cvs/linux/drivers/scsi/hosts.c
--- linux/drivers/scsi/hosts.c  Wed May 19 15:30:49 1999
+++ /home/airlied/cvs/linux/drivers/scsi/hosts.c        Tue May 18 11:52:08 1999
@@ -323,6 +323,10 @@
 #include "dec_esp.h"
 #endif
 
+#ifdef CONFIG_SCSI_DECPMAZ
+#include "pmaz_esp.h"
+#endif
+
 /*
  * Moved ppa driver to the end of the probe list
  * since it is a removable host adapter.
@@ -579,6 +583,9 @@
 #ifdef CONFIG_SCSI_DECNCR      
     SCSI_DEC_ESP,
 #endif 
+#ifdef CONFIG_SCSI_DECPMAZ
+    SCSI_PMAZ_ESP,
+#endif
 /* "Removable host adapters" below this line (Parallel Port/USB/other) */
 #ifdef CONFIG_SCSI_PPA
     PPA,
diff -urwP -x *CVS* linux/drivers/scsi/pmaz_esp.c 
/home/airlied/cvs/linux/drivers/scsi/pmaz_esp.c
--- linux/drivers/scsi/pmaz_esp.c       Thu Jan  1 01:00:00 1970
+++ /home/airlied/cvs/linux/drivers/scsi/pmaz_esp.c     Wed May 19 14:29:15 1999
@@ -0,0 +1,272 @@
+/*
+ * pmaz_esp.c:
+ *     Driver for PMAZ-cards on non-IOASIC based TURBOchannel DECstations
+ *
+ * TURBOchannel changes by Harald Koerfgen
+ *
+ * based on jazz_esp.c:
+ * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ *
+ * jazz_esp is based on David S. Miller's ESP driver and cyber_esp
+ * 
+ * Non-IOASIC changes by David Airlie (airlied@linux.ie)
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "pmaz_esp.h"
+
+#include <asm/irq.h>
+#include <asm/jazz.h>
+#include <asm/jazzdma.h>
+#include <asm/dma.h>
+
+#include <asm/pgtable.h>
+
+#include <asm/wbflush.h>
+
+#include <asm/dec/tc.h>
+#include <asm/dec/interrupts.h>
+#include <asm/dec/ioasic_addrs.h>
+#include <asm/dec/ioasic_ints.h>
+#include <asm/dec/machtype.h>
+
+static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
+static void 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 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 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_dma_ptrs_tc[ESP_NCMD];
+unsigned char scsi_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];
+                               /* This is where all commands are put
+                                * before they are trasfered to the ESP chip
+                                * via PIO.
+                                */
+
+volatile int *scsi_dma_ptr_tc;
+
+/***************************************************************** Detection */
+int pmaz_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 (TURBOCHANNEL)
+       {
+               esp_dev=0;
+               esp=esp_allocate(tpnt, (void *) esp_dev);
+       
+               slot = search_tc_card("PMAZ-AA");
+               claim_tc_card(slot);
+               
+               mem_start = get_tc_base_addr(slot);
+               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 *) cmd_buffer;
+               
+               /* get virtual dma address for command buffer */
+               esp->esp_command_dvma = (__u32)KSEG1ADDR((volatile unsigned 
char *) cmd_buffer);
+               
+               buffer = (volatile unsigned char *)(mem_start+DEC_SCSI_SRAM);
+       
+               scsi_dma_ptr_tc = (volatile int *)(mem_start + DEC_SCSI_DMAREG);
+
+               for (i=0; i<ESP_NCMD; i++)
+                 {
+                   scsi_dma_ptrs_tc[i]=(volatile unsigned char *)(buffer + 
ESP_TGT_DMA_SIZE * i);
+                 }
+
+               scsi_dma_buff_used[0]=1;
+
+               esp->cfreq = 25000000;
+
+               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 = &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 = &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 = 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, "NCR 53C94 SCSI", 
NULL);
+               esp->scsi_id=7;
+               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;
+}
+
+static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+    return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd * sp)
+{
+    return sp->SCp.this_residual;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+/*    
+   ESPLOG(("esp%d: dma -- enable <%08x> residue <%08x\n",
+   esp->esp_id, vdma_get_enable((int)esp->dregs), 
vdma_get_resdiue((int)esp->dregs)));
+ */
+}
+
+static void dma_drain(struct NCR_ESP *esp)
+{
+  memcpy((void *)(KSEG0ADDR(esp_virt_buffer)),(void *) 
scsi_dma_ptrs_tc[scsi_cur_buff], scsi_current_length);
+
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+  
+  if (length>ESP_TGT_DMA_SIZE)
+    length=ESP_TGT_DMA_SIZE;
+
+  *scsi_dma_ptr_tc = TC_ESP_DMA_ADDR(scsi_dma_ptrs_tc[scsi_cur_buff]);
+  wbflush();
+  esp_virt_buffer = vaddress;
+  scsi_current_length = length;
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 vaddress, int length)
+{
+  memcpy(scsi_dma_ptrs_tc[scsi_cur_buff], KSEG1ADDR((void *)vaddress), length);
+
+  *scsi_dma_ptr_tc = TC_ESP_DMAR_WRITE | 
TC_ESP_DMA_ADDR(scsi_dma_ptrs_tc[scsi_cur_buff]);
+  wbflush();
+ 
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+    disable_irq(SCSI_DMA_INT);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+    enable_irq(SCSI_DMA_INT);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+    return (esp->eregs->esp_status & ESP_STAT_INTR);
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+/*
+ * FIXME: what's this good for?
+ */
+    return 1;
+}
+
+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);
+    }
+}
+
+static void 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_dma_ptrs_tc[x]))
+       scsi_dma_buff_used[x]=0;
+}
+
+
+static void 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
+ */
+static void dma_advance_sg(Scsi_Cmnd * sp)
+{
+}
+
+
+
+
+
+
diff -urwP -x *CVS* linux/drivers/scsi/pmaz_esp.h 
/home/airlied/cvs/linux/drivers/scsi/pmaz_esp.h
--- linux/drivers/scsi/pmaz_esp.h       Thu Jan  1 01:00:00 1970
+++ /home/airlied/cvs/linux/drivers/scsi/pmaz_esp.h     Wed May 19 15:43:49 1999
@@ -0,0 +1,47 @@
+/* pmaz_esp.h: Defines and structures for the JAZZ SCSI driver.
+ *
+ * DECstation changes Copyright (C) 1998 Harald Koerfgen
+ * non-IOASIC changes Copyright (C) 1999 David Airlie (airlied@linux.ie)
+ *
+ * based on jazz_esp.h:
+ * Copyright (C) 1997 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
+ */
+
+#ifndef PMAZ_ESP_H
+#define PMAZ_ESP_H
+
+#define EREGS_PAD(n)     unchar n[3];
+
+#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 pmaz_esp_detect(struct SHT *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *, unsigned int);
+extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
+                        int hostno, int inout);
+
+#define SCSI_PMAZ_ESP {                                         \
+               proc_dir:       &proc_scsi_esp,                 \
+               proc_info:      &esp_proc_info,                 \
+               name:           "PMAZ-AA",                      \
+               detect:         pmaz_esp_detect,                        \
+               info:           esp_info,                       \
+               command:        esp_command,                    \
+               queuecommand:   esp_queue,                      \
+               abort:          esp_abort,                      \
+               reset:          esp_reset,                      \
+               can_queue:      7,                              \
+               this_id:        7,                              \
+               sg_tablesize:   SG_ALL,                         \
+               cmd_per_lun:    1,                              \
+               use_clustering: DISABLE_CLUSTERING, }
+
+#endif /* PMAZ_ESP_H */
<Prev in Thread] Current Thread [Next in Thread>