root/drivers/scsi/arm/cumana_1.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cumanascsi_pwrite
  2. cumanascsi_pread
  3. cumanascsi_dma_xfer_len
  4. cumanascsi_read
  5. cumanascsi_write
  6. cumanascsi1_probe
  7. cumanascsi1_remove
  8. cumanascsi_init
  9. cumanascsi_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Generic Generic NCR5380 driver
   4  *
   5  * Copyright 1995-2002, Russell King
   6  */
   7 #include <linux/module.h>
   8 #include <linux/ioport.h>
   9 #include <linux/blkdev.h>
  10 #include <linux/init.h>
  11 
  12 #include <asm/ecard.h>
  13 #include <asm/io.h>
  14 
  15 #include <scsi/scsi_host.h>
  16 
  17 #define priv(host)                      ((struct NCR5380_hostdata *)(host)->hostdata)
  18 #define NCR5380_read(reg)               cumanascsi_read(hostdata, reg)
  19 #define NCR5380_write(reg, value)       cumanascsi_write(hostdata, reg, value)
  20 
  21 #define NCR5380_dma_xfer_len            cumanascsi_dma_xfer_len
  22 #define NCR5380_dma_recv_setup          cumanascsi_pread
  23 #define NCR5380_dma_send_setup          cumanascsi_pwrite
  24 #define NCR5380_dma_residual            NCR5380_dma_residual_none
  25 
  26 #define NCR5380_intr                    cumanascsi_intr
  27 #define NCR5380_queue_command           cumanascsi_queue_command
  28 #define NCR5380_info                    cumanascsi_info
  29 
  30 #define NCR5380_implementation_fields   \
  31         unsigned ctrl
  32 
  33 struct NCR5380_hostdata;
  34 static u8 cumanascsi_read(struct NCR5380_hostdata *, unsigned int);
  35 static void cumanascsi_write(struct NCR5380_hostdata *, unsigned int, u8);
  36 
  37 #include "../NCR5380.h"
  38 
  39 #define CTRL    0x16fc
  40 #define STAT    0x2004
  41 #define L(v)    (((v)<<16)|((v) & 0x0000ffff))
  42 #define H(v)    (((v)>>16)|((v) & 0xffff0000))
  43 
  44 static inline int cumanascsi_pwrite(struct NCR5380_hostdata *hostdata,
  45                                     unsigned char *addr, int len)
  46 {
  47   unsigned long *laddr;
  48   u8 __iomem *base = hostdata->io;
  49   u8 __iomem *dma = hostdata->pdma_io + 0x2000;
  50 
  51   if(!len) return 0;
  52 
  53   writeb(0x02, base + CTRL);
  54   laddr = (unsigned long *)addr;
  55   while(len >= 32)
  56   {
  57     unsigned int status;
  58     unsigned long v;
  59     status = readb(base + STAT);
  60     if(status & 0x80)
  61       goto end;
  62     if(!(status & 0x40))
  63       continue;
  64     v=*laddr++; writew(L(v), dma); writew(H(v), dma);
  65     v=*laddr++; writew(L(v), dma); writew(H(v), dma);
  66     v=*laddr++; writew(L(v), dma); writew(H(v), dma);
  67     v=*laddr++; writew(L(v), dma); writew(H(v), dma);
  68     v=*laddr++; writew(L(v), dma); writew(H(v), dma);
  69     v=*laddr++; writew(L(v), dma); writew(H(v), dma);
  70     v=*laddr++; writew(L(v), dma); writew(H(v), dma);
  71     v=*laddr++; writew(L(v), dma); writew(H(v), dma);
  72     len -= 32;
  73     if(len == 0)
  74       break;
  75   }
  76 
  77   addr = (unsigned char *)laddr;
  78   writeb(0x12, base + CTRL);
  79 
  80   while(len > 0)
  81   {
  82     unsigned int status;
  83     status = readb(base + STAT);
  84     if(status & 0x80)
  85       goto end;
  86     if(status & 0x40)
  87     {
  88       writeb(*addr++, dma);
  89       if(--len == 0)
  90         break;
  91     }
  92 
  93     status = readb(base + STAT);
  94     if(status & 0x80)
  95       goto end;
  96     if(status & 0x40)
  97     {
  98       writeb(*addr++, dma);
  99       if(--len == 0)
 100         break;
 101     }
 102   }
 103 end:
 104   writeb(hostdata->ctrl | 0x40, base + CTRL);
 105 
 106         if (len)
 107                 return -1;
 108         return 0;
 109 }
 110 
 111 static inline int cumanascsi_pread(struct NCR5380_hostdata *hostdata,
 112                                    unsigned char *addr, int len)
 113 {
 114   unsigned long *laddr;
 115   u8 __iomem *base = hostdata->io;
 116   u8 __iomem *dma = hostdata->pdma_io + 0x2000;
 117 
 118   if(!len) return 0;
 119 
 120   writeb(0x00, base + CTRL);
 121   laddr = (unsigned long *)addr;
 122   while(len >= 32)
 123   {
 124     unsigned int status;
 125     status = readb(base + STAT);
 126     if(status & 0x80)
 127       goto end;
 128     if(!(status & 0x40))
 129       continue;
 130     *laddr++ = readw(dma) | (readw(dma) << 16);
 131     *laddr++ = readw(dma) | (readw(dma) << 16);
 132     *laddr++ = readw(dma) | (readw(dma) << 16);
 133     *laddr++ = readw(dma) | (readw(dma) << 16);
 134     *laddr++ = readw(dma) | (readw(dma) << 16);
 135     *laddr++ = readw(dma) | (readw(dma) << 16);
 136     *laddr++ = readw(dma) | (readw(dma) << 16);
 137     *laddr++ = readw(dma) | (readw(dma) << 16);
 138     len -= 32;
 139     if(len == 0)
 140       break;
 141   }
 142 
 143   addr = (unsigned char *)laddr;
 144   writeb(0x10, base + CTRL);
 145 
 146   while(len > 0)
 147   {
 148     unsigned int status;
 149     status = readb(base + STAT);
 150     if(status & 0x80)
 151       goto end;
 152     if(status & 0x40)
 153     {
 154       *addr++ = readb(dma);
 155       if(--len == 0)
 156         break;
 157     }
 158 
 159     status = readb(base + STAT);
 160     if(status & 0x80)
 161       goto end;
 162     if(status & 0x40)
 163     {
 164       *addr++ = readb(dma);
 165       if(--len == 0)
 166         break;
 167     }
 168   }
 169 end:
 170   writeb(hostdata->ctrl | 0x40, base + CTRL);
 171 
 172         if (len)
 173                 return -1;
 174         return 0;
 175 }
 176 
 177 static int cumanascsi_dma_xfer_len(struct NCR5380_hostdata *hostdata,
 178                                    struct scsi_cmnd *cmd)
 179 {
 180         return cmd->transfersize;
 181 }
 182 
 183 static u8 cumanascsi_read(struct NCR5380_hostdata *hostdata,
 184                           unsigned int reg)
 185 {
 186         u8 __iomem *base = hostdata->io;
 187         u8 val;
 188 
 189         writeb(0, base + CTRL);
 190 
 191         val = readb(base + 0x2100 + (reg << 2));
 192 
 193         hostdata->ctrl = 0x40;
 194         writeb(0x40, base + CTRL);
 195 
 196         return val;
 197 }
 198 
 199 static void cumanascsi_write(struct NCR5380_hostdata *hostdata,
 200                              unsigned int reg, u8 value)
 201 {
 202         u8 __iomem *base = hostdata->io;
 203 
 204         writeb(0, base + CTRL);
 205 
 206         writeb(value, base + 0x2100 + (reg << 2));
 207 
 208         hostdata->ctrl = 0x40;
 209         writeb(0x40, base + CTRL);
 210 }
 211 
 212 #include "../NCR5380.c"
 213 
 214 static struct scsi_host_template cumanascsi_template = {
 215         .module                 = THIS_MODULE,
 216         .name                   = "Cumana 16-bit SCSI",
 217         .info                   = cumanascsi_info,
 218         .queuecommand           = cumanascsi_queue_command,
 219         .eh_abort_handler       = NCR5380_abort,
 220         .eh_host_reset_handler  = NCR5380_host_reset,
 221         .can_queue              = 16,
 222         .this_id                = 7,
 223         .sg_tablesize           = SG_ALL,
 224         .cmd_per_lun            = 2,
 225         .proc_name              = "CumanaSCSI-1",
 226         .cmd_size               = NCR5380_CMD_SIZE,
 227         .max_sectors            = 128,
 228         .dma_boundary           = PAGE_SIZE - 1,
 229 };
 230 
 231 static int cumanascsi1_probe(struct expansion_card *ec,
 232                              const struct ecard_id *id)
 233 {
 234         struct Scsi_Host *host;
 235         int ret;
 236 
 237         ret = ecard_request_resources(ec);
 238         if (ret)
 239                 goto out;
 240 
 241         host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata));
 242         if (!host) {
 243                 ret = -ENOMEM;
 244                 goto out_release;
 245         }
 246 
 247         priv(host)->io = ioremap(ecard_resource_start(ec, ECARD_RES_IOCSLOW),
 248                                  ecard_resource_len(ec, ECARD_RES_IOCSLOW));
 249         priv(host)->pdma_io = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
 250                                       ecard_resource_len(ec, ECARD_RES_MEMC));
 251         if (!priv(host)->io || !priv(host)->pdma_io) {
 252                 ret = -ENOMEM;
 253                 goto out_unmap;
 254         }
 255 
 256         host->irq = ec->irq;
 257 
 258         ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP);
 259         if (ret)
 260                 goto out_unmap;
 261 
 262         NCR5380_maybe_reset_bus(host);
 263 
 264         priv(host)->ctrl = 0;
 265         writeb(0, priv(host)->io + CTRL);
 266 
 267         ret = request_irq(host->irq, cumanascsi_intr, 0,
 268                           "CumanaSCSI-1", host);
 269         if (ret) {
 270                 printk("scsi%d: IRQ%d not free: %d\n",
 271                     host->host_no, host->irq, ret);
 272                 goto out_exit;
 273         }
 274 
 275         ret = scsi_add_host(host, &ec->dev);
 276         if (ret)
 277                 goto out_free_irq;
 278 
 279         scsi_scan_host(host);
 280         goto out;
 281 
 282  out_free_irq:
 283         free_irq(host->irq, host);
 284  out_exit:
 285         NCR5380_exit(host);
 286  out_unmap:
 287         iounmap(priv(host)->io);
 288         iounmap(priv(host)->pdma_io);
 289         scsi_host_put(host);
 290  out_release:
 291         ecard_release_resources(ec);
 292  out:
 293         return ret;
 294 }
 295 
 296 static void cumanascsi1_remove(struct expansion_card *ec)
 297 {
 298         struct Scsi_Host *host = ecard_get_drvdata(ec);
 299         void __iomem *base = priv(host)->io;
 300         void __iomem *dma = priv(host)->pdma_io;
 301 
 302         ecard_set_drvdata(ec, NULL);
 303 
 304         scsi_remove_host(host);
 305         free_irq(host->irq, host);
 306         NCR5380_exit(host);
 307         scsi_host_put(host);
 308         iounmap(base);
 309         iounmap(dma);
 310         ecard_release_resources(ec);
 311 }
 312 
 313 static const struct ecard_id cumanascsi1_cids[] = {
 314         { MANU_CUMANA, PROD_CUMANA_SCSI_1 },
 315         { 0xffff, 0xffff }
 316 };
 317 
 318 static struct ecard_driver cumanascsi1_driver = {
 319         .probe          = cumanascsi1_probe,
 320         .remove         = cumanascsi1_remove,
 321         .id_table       = cumanascsi1_cids,
 322         .drv = {
 323                 .name           = "cumanascsi1",
 324         },
 325 };
 326 
 327 static int __init cumanascsi_init(void)
 328 {
 329         return ecard_register_driver(&cumanascsi1_driver);
 330 }
 331 
 332 static void __exit cumanascsi_exit(void)
 333 {
 334         ecard_remove_driver(&cumanascsi1_driver);
 335 }
 336 
 337 module_init(cumanascsi_init);
 338 module_exit(cumanascsi_exit);
 339 
 340 MODULE_DESCRIPTION("Cumana SCSI-1 driver for Acorn machines");
 341 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */