cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cumana_1.c (7922B)


      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
     33struct NCR5380_hostdata;
     34static u8 cumanascsi_read(struct NCR5380_hostdata *, unsigned int);
     35static 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
     44static 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  }
    103end:
    104  writeb(hostdata->ctrl | 0x40, base + CTRL);
    105
    106	if (len)
    107		return -1;
    108	return 0;
    109}
    110
    111static 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  }
    169end:
    170  writeb(hostdata->ctrl | 0x40, base + CTRL);
    171
    172	if (len)
    173		return -1;
    174	return 0;
    175}
    176
    177static int cumanascsi_dma_xfer_len(struct NCR5380_hostdata *hostdata,
    178                                   struct scsi_cmnd *cmd)
    179{
    180	return cmd->transfersize;
    181}
    182
    183static 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
    199static 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
    214static 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		= sizeof(struct NCR5380_cmd),
    227	.max_sectors		= 128,
    228	.dma_boundary		= PAGE_SIZE - 1,
    229};
    230
    231static 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
    296static 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
    313static const struct ecard_id cumanascsi1_cids[] = {
    314	{ MANU_CUMANA, PROD_CUMANA_SCSI_1 },
    315	{ 0xffff, 0xffff }
    316};
    317
    318static 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
    327static int __init cumanascsi_init(void)
    328{
    329	return ecard_register_driver(&cumanascsi1_driver);
    330}
    331
    332static void __exit cumanascsi_exit(void)
    333{
    334	ecard_remove_driver(&cumanascsi1_driver);
    335}
    336
    337module_init(cumanascsi_init);
    338module_exit(cumanascsi_exit);
    339
    340MODULE_DESCRIPTION("Cumana SCSI-1 driver for Acorn machines");
    341MODULE_LICENSE("GPL");