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

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