Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/scsi/arm/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  cumana_1.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Generic Generic NCR5380 driver
 *
 * Copyright 1995-2002, Russell King
 */

#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
#include <linux/init.h>

#include <asm/ecard.h>
#include <asm/io.h>

#include <scsi/scsi_host.h>

#define priv(host)   ((struct NCR5380_hostdata *)(host)->hostdata)
#define NCR5380_read(reg)  cumanascsi_read(hostdata, reg)
#define NCR5380_write(reg, value) cumanascsi_write(hostdata, reg, value)

#define NCR5380_dma_xfer_len  cumanascsi_dma_xfer_len
#define NCR5380_dma_recv_setup  cumanascsi_pread
#define NCR5380_dma_send_setup  cumanascsi_pwrite
#define NCR5380_dma_residual  NCR5380_dma_residual_none

#define NCR5380_intr   cumanascsi_intr
#define NCR5380_queue_command  cumanascsi_queue_command
#define NCR5380_info   cumanascsi_info

#define NCR5380_implementation_fields \
 unsigned ctrl

struct NCR5380_hostdata;
static u8 cumanascsi_read(struct NCR5380_hostdata *, unsigned int);
static void cumanascsi_write(struct NCR5380_hostdata *, unsigned int, u8);

#include "../NCR5380.h"

#define CTRL 0x16fc
#define STAT 0x2004
#define L(v) (((v)<<16)|((v) & 0x0000ffff))
#define H(v) (((v)>>16)|((v) & 0xffff0000))

static inline int cumanascsi_pwrite(struct NCR5380_hostdata *hostdata,
                                    unsigned char *addr, int len)
{
  unsigned long *laddr;
  u8 __iomem *base = hostdata->io;
  u8 __iomem *dma = hostdata->pdma_io + 0x2000;

  if(!len) return 0;

  writeb(0x02, base + CTRL);
  laddr = (unsigned long *)addr;
  while(len >= 32)
  {
    unsigned int status;
    unsigned long v;
    status = readb(base + STAT);
    if(status & 0x80)
      goto end;
    if(!(status & 0x40))
      continue;
    v=*laddr++; writew(L(v), dma); writew(H(v), dma);
    v=*laddr++; writew(L(v), dma); writew(H(v), dma);
    v=*laddr++; writew(L(v), dma); writew(H(v), dma);
    v=*laddr++; writew(L(v), dma); writew(H(v), dma);
    v=*laddr++; writew(L(v), dma); writew(H(v), dma);
    v=*laddr++; writew(L(v), dma); writew(H(v), dma);
    v=*laddr++; writew(L(v), dma); writew(H(v), dma);
    v=*laddr++; writew(L(v), dma); writew(H(v), dma);
    len -= 32;
    if(len == 0)
      break;
  }

  addr = (unsigned char *)laddr;
  writeb(0x12, base + CTRL);

  while(len > 0)
  {
    unsigned int status;
    status = readb(base + STAT);
    if(status & 0x80)
      goto end;
    if(status & 0x40)
    {
      writeb(*addr++, dma);
      if(--len == 0)
        break;
    }

    status = readb(base + STAT);
    if(status & 0x80)
      goto end;
    if(status & 0x40)
    {
      writeb(*addr++, dma);
      if(--len == 0)
        break;
    }
  }
end:
  writeb(hostdata->ctrl | 0x40, base + CTRL);

 if (len)
  return -1;
 return 0;
}

static inline int cumanascsi_pread(struct NCR5380_hostdata *hostdata,
                                   unsigned char *addr, int len)
{
  unsigned long *laddr;
  u8 __iomem *base = hostdata->io;
  u8 __iomem *dma = hostdata->pdma_io + 0x2000;

  if(!len) return 0;

  writeb(0x00, base + CTRL);
  laddr = (unsigned long *)addr;
  while(len >= 32)
  {
    unsigned int status;
    status = readb(base + STAT);
    if(status & 0x80)
      goto end;
    if(!(status & 0x40))
      continue;
    *laddr++ = readw(dma) | (readw(dma) << 16);
    *laddr++ = readw(dma) | (readw(dma) << 16);
    *laddr++ = readw(dma) | (readw(dma) << 16);
    *laddr++ = readw(dma) | (readw(dma) << 16);
    *laddr++ = readw(dma) | (readw(dma) << 16);
    *laddr++ = readw(dma) | (readw(dma) << 16);
    *laddr++ = readw(dma) | (readw(dma) << 16);
    *laddr++ = readw(dma) | (readw(dma) << 16);
    len -= 32;
    if(len == 0)
      break;
  }

  addr = (unsigned char *)laddr;
  writeb(0x10, base + CTRL);

  while(len > 0)
  {
    unsigned int status;
    status = readb(base + STAT);
    if(status & 0x80)
      goto end;
    if(status & 0x40)
    {
      *addr++ = readb(dma);
      if(--len == 0)
        break;
    }

    status = readb(base + STAT);
    if(status & 0x80)
      goto end;
    if(status & 0x40)
    {
      *addr++ = readb(dma);
      if(--len == 0)
        break;
    }
  }
end:
  writeb(hostdata->ctrl | 0x40, base + CTRL);

 if (len)
  return -1;
 return 0;
}

static int cumanascsi_dma_xfer_len(struct NCR5380_hostdata *hostdata,
                                   struct scsi_cmnd *cmd)
{
 return cmd->transfersize;
}

static u8 cumanascsi_read(struct NCR5380_hostdata *hostdata,
                          unsigned int reg)
{
 u8 __iomem *base = hostdata->io;
 u8 val;

 writeb(0, base + CTRL);

 val = readb(base + 0x2100 + (reg << 2));

 hostdata->ctrl = 0x40;
 writeb(0x40, base + CTRL);

 return val;
}

static void cumanascsi_write(struct NCR5380_hostdata *hostdata,
                             unsigned int reg, u8 value)
{
 u8 __iomem *base = hostdata->io;

 writeb(0, base + CTRL);

 writeb(value, base + 0x2100 + (reg << 2));

 hostdata->ctrl = 0x40;
 writeb(0x40, base + CTRL);
}

#include "../NCR5380.c"

static const struct scsi_host_template cumanascsi_template = {
 .module   = THIS_MODULE,
 .name   = "Cumana 16-bit SCSI",
 .info   = cumanascsi_info,
 .queuecommand  = cumanascsi_queue_command,
 .eh_abort_handler = NCR5380_abort,
 .eh_host_reset_handler = NCR5380_host_reset,
 .can_queue  = 16,
 .this_id  = 7,
 .sg_tablesize  = SG_ALL,
 .cmd_per_lun  = 2,
 .proc_name  = "CumanaSCSI-1",
 .cmd_size  = sizeof(struct NCR5380_cmd),
 .max_sectors  = 128,
 .dma_boundary  = PAGE_SIZE - 1,
};

static int cumanascsi1_probe(struct expansion_card *ec,
        const struct ecard_id *id)
{
 struct Scsi_Host *host;
 int ret;

 ret = ecard_request_resources(ec);
 if (ret)
  goto out;

 host = scsi_host_alloc(&cumanascsi_template, sizeof(struct NCR5380_hostdata));
 if (!host) {
  ret = -ENOMEM;
  goto out_release;
 }

 priv(host)->io = ioremap(ecard_resource_start(ec, ECARD_RES_IOCSLOW),
                          ecard_resource_len(ec, ECARD_RES_IOCSLOW));
 priv(host)->pdma_io = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
                               ecard_resource_len(ec, ECARD_RES_MEMC));
 if (!priv(host)->io || !priv(host)->pdma_io) {
  ret = -ENOMEM;
  goto out_unmap;
 }

 host->irq = ec->irq;

 ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP);
 if (ret)
  goto out_unmap;

 NCR5380_maybe_reset_bus(host);

        priv(host)->ctrl = 0;
        writeb(0, priv(host)->io + CTRL);

 ret = request_irq(host->irq, cumanascsi_intr, 0,
     "CumanaSCSI-1", host);
 if (ret) {
  printk("scsi%d: IRQ%d not free: %d\n",
      host->host_no, host->irq, ret);
  goto out_exit;
 }

 ret = scsi_add_host(host, &ec->dev);
 if (ret)
  goto out_free_irq;

 scsi_scan_host(host);
 goto out;

 out_free_irq:
 free_irq(host->irq, host);
 out_exit:
 NCR5380_exit(host);
 out_unmap:
 iounmap(priv(host)->io);
 iounmap(priv(host)->pdma_io);
 scsi_host_put(host);
 out_release:
 ecard_release_resources(ec);
 out:
 return ret;
}

static void cumanascsi1_remove(struct expansion_card *ec)
{
 struct Scsi_Host *host = ecard_get_drvdata(ec);
 void __iomem *base = priv(host)->io;
 void __iomem *dma = priv(host)->pdma_io;

 ecard_set_drvdata(ec, NULL);

 scsi_remove_host(host);
 free_irq(host->irq, host);
 NCR5380_exit(host);
 scsi_host_put(host);
 iounmap(base);
 iounmap(dma);
 ecard_release_resources(ec);
}

static const struct ecard_id cumanascsi1_cids[] = {
 { MANU_CUMANA, PROD_CUMANA_SCSI_1 },
 { 0xffff, 0xffff }
};

static struct ecard_driver cumanascsi1_driver = {
 .probe  = cumanascsi1_probe,
 .remove  = cumanascsi1_remove,
 .id_table = cumanascsi1_cids,
 .drv = {
  .name  = "cumanascsi1",
 },
};

static int __init cumanascsi_init(void)
{
 return ecard_register_driver(&cumanascsi1_driver);
}

static void __exit cumanascsi_exit(void)
{
 ecard_remove_driver(&cumanascsi1_driver);
}

module_init(cumanascsi_init);
module_exit(cumanascsi_exit);

MODULE_DESCRIPTION("Cumana SCSI-1 driver for Acorn machines");
MODULE_LICENSE("GPL");

Messung V0.5
C=100 H=76 G=88

¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.