Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/types.h>
0003 #include <linux/mm.h>
0004 #include <linux/blkdev.h>
0005 #include <linux/interrupt.h>
0006 #include <linux/init.h>
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 
0010 #include <asm/page.h>
0011 #include <asm/mvme147hw.h>
0012 #include <asm/irq.h>
0013 
0014 #include <scsi/scsi.h>
0015 #include <scsi/scsi_cmnd.h>
0016 #include <scsi/scsi_device.h>
0017 #include <scsi/scsi_eh.h>
0018 #include <scsi/scsi_host.h>
0019 #include <scsi/scsi_tcq.h>
0020 #include "wd33c93.h"
0021 #include "mvme147.h"
0022 
0023 static irqreturn_t mvme147_intr(int irq, void *data)
0024 {
0025     struct Scsi_Host *instance = data;
0026 
0027     if (irq == MVME147_IRQ_SCSI_PORT)
0028         wd33c93_intr(instance);
0029     else
0030         m147_pcc->dma_intr = 0x89;  /* Ack and enable ints */
0031     return IRQ_HANDLED;
0032 }
0033 
0034 static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
0035 {
0036     struct scsi_pointer *scsi_pointer = WD33C93_scsi_pointer(cmd);
0037     struct Scsi_Host *instance = cmd->device->host;
0038     struct WD33C93_hostdata *hdata = shost_priv(instance);
0039     unsigned char flags = 0x01;
0040     unsigned long addr = virt_to_bus(scsi_pointer->ptr);
0041 
0042     /* setup dma direction */
0043     if (!dir_in)
0044         flags |= 0x04;
0045 
0046     /* remember direction */
0047     hdata->dma_dir = dir_in;
0048 
0049     if (dir_in) {
0050         /* invalidate any cache */
0051         cache_clear(addr, scsi_pointer->this_residual);
0052     } else {
0053         /* push any dirty cache */
0054         cache_push(addr, scsi_pointer->this_residual);
0055     }
0056 
0057     /* start DMA */
0058     m147_pcc->dma_bcr = scsi_pointer->this_residual | (1 << 24);
0059     m147_pcc->dma_dadr = addr;
0060     m147_pcc->dma_cntrl = flags;
0061 
0062     /* return success */
0063     return 0;
0064 }
0065 
0066 static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
0067              int status)
0068 {
0069     m147_pcc->dma_cntrl = 0;
0070 }
0071 
0072 static struct scsi_host_template mvme147_host_template = {
0073     .module         = THIS_MODULE,
0074     .proc_name      = "MVME147",
0075     .name           = "MVME147 built-in SCSI",
0076     .queuecommand       = wd33c93_queuecommand,
0077     .eh_abort_handler   = wd33c93_abort,
0078     .eh_host_reset_handler  = wd33c93_host_reset,
0079     .show_info      = wd33c93_show_info,
0080     .write_info     = wd33c93_write_info,
0081     .can_queue      = CAN_QUEUE,
0082     .this_id        = 7,
0083     .sg_tablesize       = SG_ALL,
0084     .cmd_per_lun        = CMD_PER_LUN,
0085     .cmd_size       = sizeof(struct scsi_pointer),
0086 };
0087 
0088 static struct Scsi_Host *mvme147_shost;
0089 
0090 static int __init mvme147_init(void)
0091 {
0092     wd33c93_regs regs;
0093     struct WD33C93_hostdata *hdata;
0094     int error = -ENOMEM;
0095 
0096     if (!MACH_IS_MVME147)
0097         return 0;
0098 
0099     mvme147_shost = scsi_host_alloc(&mvme147_host_template,
0100             sizeof(struct WD33C93_hostdata));
0101     if (!mvme147_shost)
0102         goto err_out;
0103     mvme147_shost->base = 0xfffe4000;
0104     mvme147_shost->irq = MVME147_IRQ_SCSI_PORT;
0105 
0106     regs.SASR = (volatile unsigned char *)0xfffe4000;
0107     regs.SCMD = (volatile unsigned char *)0xfffe4001;
0108 
0109     hdata = shost_priv(mvme147_shost);
0110     hdata->no_sync = 0xff;
0111     hdata->fast = 0;
0112     hdata->dma_mode = CTRL_DMA;
0113 
0114     wd33c93_init(mvme147_shost, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
0115 
0116     error = request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0,
0117             "MVME147 SCSI PORT", mvme147_shost);
0118     if (error)
0119         goto err_unregister;
0120     error = request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0,
0121             "MVME147 SCSI DMA", mvme147_shost);
0122     if (error)
0123         goto err_free_irq;
0124 #if 0   /* Disabled; causes problems booting */
0125     m147_pcc->scsi_interrupt = 0x10;    /* Assert SCSI bus reset */
0126     udelay(100);
0127     m147_pcc->scsi_interrupt = 0x00;    /* Negate SCSI bus reset */
0128     udelay(2000);
0129     m147_pcc->scsi_interrupt = 0x40;    /* Clear bus reset interrupt */
0130 #endif
0131     m147_pcc->scsi_interrupt = 0x09;    /* Enable interrupt */
0132 
0133     m147_pcc->dma_cntrl = 0x00; /* ensure DMA is stopped */
0134     m147_pcc->dma_intr = 0x89;  /* Ack and enable ints */
0135 
0136     error = scsi_add_host(mvme147_shost, NULL);
0137     if (error)
0138         goto err_free_irq;
0139     scsi_scan_host(mvme147_shost);
0140     return 0;
0141 
0142 err_free_irq:
0143     free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost);
0144 err_unregister:
0145     scsi_host_put(mvme147_shost);
0146 err_out:
0147     return error;
0148 }
0149 
0150 static void __exit mvme147_exit(void)
0151 {
0152     scsi_remove_host(mvme147_shost);
0153 
0154     /* XXX Make sure DMA is stopped! */
0155     free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost);
0156     free_irq(MVME147_IRQ_SCSI_DMA, mvme147_shost);
0157 
0158     scsi_host_put(mvme147_shost);
0159 }
0160 
0161 module_init(mvme147_init);
0162 module_exit(mvme147_exit);