root/drivers/scsi/a2091.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. a2091_intr
  2. dma_setup
  3. dma_stop
  4. a2091_detect

   1 #include <linux/types.h>
   2 #include <linux/mm.h>
   3 #include <linux/blk.h>
   4 #include <linux/version.h>
   5 
   6 #include <asm/page.h>
   7 #include <asm/pgtable.h>
   8 #include <asm/bootinfo.h>
   9 #include <asm/amigaints.h>
  10 #include <asm/amigahw.h>
  11 #include <asm/zorro.h>
  12 #include <asm/irq.h>
  13 
  14 #include "scsi.h"
  15 #include "hosts.h"
  16 #include "wd33c93.h"
  17 #include "a2091.h"
  18 
  19 #include<linux/stat.h>
  20 
  21 struct proc_dir_entry proc_scsi_a2091 = {
  22     PROC_SCSI_A2091, 5, "A2091",
  23     S_IFDIR | S_IRUGO | S_IXUGO, 2
  24 };
  25 
  26 #define DMA(ptr) ((a2091_scsiregs *)((ptr)->base))
  27 #define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
  28 
  29 static struct Scsi_Host *first_instance = NULL;
  30 static Scsi_Host_Template *a2091_template;
  31 
  32 static void a2091_intr (int irq, struct pt_regs *fp, void *dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34     unsigned int status;
  35     struct Scsi_Host *instance;
  36 
  37     for (instance = first_instance; instance &&
  38          instance->hostt == a2091_template; instance = instance->next)
  39     {
  40         status = DMA(instance)->ISTR;
  41         if (!(status & (ISTR_INT_F|ISTR_INT_P)))
  42             continue;
  43 
  44         if (status & ISTR_INTS)
  45         {
  46             /* disable PORTS interrupt */
  47             custom.intena = IF_PORTS;
  48             wd33c93_intr (instance);
  49             /* enable PORTS interrupt */
  50             custom.intena = IF_SETCLR | IF_PORTS;
  51         }
  52     }
  53 }
  54 
  55 static int dma_setup (Scsi_Cmnd *cmd, int dir_in)
     /* [previous][next][first][last][top][bottom][index][help] */
  56 {
  57     unsigned short cntr = CNTR_PDMD | CNTR_INTEN;
  58     unsigned long addr = VTOP(cmd->SCp.ptr);
  59     struct Scsi_Host *instance = cmd->host;
  60 
  61     /* don't allow DMA if the physical address is bad */
  62     if (addr & A2091_XFER_MASK ||
  63         (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual)))
  64     {
  65         HDATA(instance)->dma_bounce_len = (cmd->SCp.this_residual + 511)
  66             & ~0x1ff;
  67         HDATA(instance)->dma_bounce_buffer =
  68             scsi_malloc (HDATA(instance)->dma_bounce_len);
  69         
  70         /* can't allocate memory; use PIO */
  71         if (!HDATA(instance)->dma_bounce_buffer) {
  72             HDATA(instance)->dma_bounce_len = 0;
  73             return 1;
  74         }
  75 
  76         /* get the physical address of the bounce buffer */
  77         addr = VTOP(HDATA(instance)->dma_bounce_buffer);
  78 
  79         /* the bounce buffer may not be in the first 16M of physmem */
  80         if (addr & A2091_XFER_MASK) {
  81             /* we could use chipmem... maybe later */
  82             scsi_free (HDATA(instance)->dma_bounce_buffer,
  83                        HDATA(instance)->dma_bounce_len);
  84             HDATA(instance)->dma_bounce_buffer = NULL;
  85             HDATA(instance)->dma_bounce_len = 0;
  86             return 1;
  87         }
  88 
  89         if (!dir_in) {
  90             /* copy to bounce buffer for a write */
  91             if (cmd->use_sg)
  92 #if 0
  93                 panic ("scsi%ddma: incomplete s/g support",
  94                        instance->host_no);
  95 #else
  96                 memcpy (HDATA(instance)->dma_bounce_buffer,
  97                         cmd->SCp.ptr, cmd->SCp.this_residual);
  98 #endif
  99             else
 100                 memcpy (HDATA(instance)->dma_bounce_buffer,
 101                         cmd->request_buffer, cmd->request_bufflen);
 102         }
 103     }
 104 
 105     /* setup dma direction */
 106     if (!dir_in)
 107         cntr |= CNTR_DDIR;
 108 
 109     /* remember direction */
 110     HDATA(cmd->host)->dma_dir = dir_in;
 111 
 112     DMA(cmd->host)->CNTR = cntr;
 113 
 114     /* setup DMA *physical* address */
 115     DMA(cmd->host)->ACR = addr;
 116 
 117     if (dir_in){
 118         /* invalidate any cache */
 119         cache_clear (addr, cmd->SCp.this_residual);
 120     }else{
 121         /* push any dirty cache */
 122         cache_push (addr, cmd->SCp.this_residual);
 123       }
 124     /* start DMA */
 125     DMA(cmd->host)->ST_DMA = 1;
 126 
 127     /* return success */
 128     return 0;
 129 }
 130 
 131 static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, 
     /* [previous][next][first][last][top][bottom][index][help] */
 132                       int status)
 133 {
 134     /* disable SCSI interrupts */
 135     unsigned short cntr = CNTR_PDMD;
 136 
 137     if (!HDATA(instance)->dma_dir)
 138             cntr |= CNTR_DDIR;
 139 
 140     /* disable SCSI interrupts */
 141     DMA(instance)->CNTR = cntr;
 142 
 143     /* flush if we were reading */
 144     if (HDATA(instance)->dma_dir) {
 145         DMA(instance)->FLUSH = 1;
 146         while (!(DMA(instance)->ISTR & ISTR_FE_FLG))
 147             ;
 148     }
 149 
 150     /* clear a possible interrupt */
 151     DMA(instance)->CINT = 1;
 152 
 153     /* stop DMA */
 154     DMA(instance)->SP_DMA = 1;
 155 
 156     /* restore the CONTROL bits (minus the direction flag) */
 157     DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
 158 
 159     /* copy from a bounce buffer, if necessary */
 160     if (status && HDATA(instance)->dma_bounce_buffer) {
 161         if (SCpnt && SCpnt->use_sg) {
 162 #if 0
 163             panic ("scsi%d: incomplete s/g support",
 164                    instance->host_no);
 165 #else
 166             if( HDATA(instance)->dma_dir )
 167                 memcpy (SCpnt->SCp.ptr, 
 168                         HDATA(instance)->dma_bounce_buffer,
 169                         SCpnt->SCp.this_residual);
 170             scsi_free (HDATA(instance)->dma_bounce_buffer,
 171                        HDATA(instance)->dma_bounce_len);
 172             HDATA(instance)->dma_bounce_buffer = NULL;
 173             HDATA(instance)->dma_bounce_len = 0;
 174             
 175 #endif
 176         } else {
 177             if (HDATA(instance)->dma_dir && SCpnt)
 178                 memcpy (SCpnt->request_buffer,
 179                         HDATA(instance)->dma_bounce_buffer,
 180                         SCpnt->request_bufflen);
 181 
 182             scsi_free (HDATA(instance)->dma_bounce_buffer,
 183                        HDATA(instance)->dma_bounce_len);
 184             HDATA(instance)->dma_bounce_buffer = NULL;
 185             HDATA(instance)->dma_bounce_len = 0;
 186         }
 187     }
 188 }
 189 
 190 int a2091_detect(Scsi_Host_Template *tpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192     static unsigned char called = 0;
 193     struct Scsi_Host *instance;
 194     int i, manuf, product, num_a2091 = 0;
 195     caddr_t address;
 196 
 197     if (!MACH_IS_AMIGA || called)
 198         return 0;
 199     called = 1;
 200 
 201     tpnt->proc_dir = &proc_scsi_a2091;
 202 
 203     for (i = 0; i < boot_info.bi_amiga.num_autocon; i++)
 204     {
 205         manuf = boot_info.bi_amiga.autocon[i].cd_Rom.er_Manufacturer;
 206         product = boot_info.bi_amiga.autocon[i].cd_Rom.er_Product;
 207         if (manuf == MANUF_COMMODORE && (product == PROD_A2091 ||
 208                                          product == PROD_A590)) {
 209             address = boot_info.bi_amiga.autocon[i].cd_BoardAddr;
 210             instance = scsi_register (tpnt,
 211                                       sizeof (struct WD33C93_hostdata));
 212             instance->base = (unsigned char *)ZTWO_VADDR(address);
 213             DMA(instance)->DAWR = DAWR_A2091;
 214             wd33c93_init(instance, (wd33c93_regs *)&(DMA(instance)->SASR),
 215                          dma_setup, dma_stop, WD33C93_FS_8_10);
 216             if (num_a2091++ == 0) {
 217                 first_instance = instance;
 218                 a2091_template = instance->hostt;
 219                 add_isr(IRQ_AMIGA_PORTS, a2091_intr, 0, NULL, "A2091 SCSI");
 220             }
 221             DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN;
 222 
 223 #if 0 /* The Zorro stuff is not totally integrated yet ! */
 224             boot_info.bi_amiga.autocon_configured |= 1<<i;
 225 #endif
 226           }
 227     }
 228 
 229     return num_a2091;
 230 }

/* [previous][next][first][last][top][bottom][index][help] */