0001
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;
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
0043 if (!dir_in)
0044 flags |= 0x04;
0045
0046
0047 hdata->dma_dir = dir_in;
0048
0049 if (dir_in) {
0050
0051 cache_clear(addr, scsi_pointer->this_residual);
0052 } else {
0053
0054 cache_push(addr, scsi_pointer->this_residual);
0055 }
0056
0057
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
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
0125 m147_pcc->scsi_interrupt = 0x10;
0126 udelay(100);
0127 m147_pcc->scsi_interrupt = 0x00;
0128 udelay(2000);
0129 m147_pcc->scsi_interrupt = 0x40;
0130 #endif
0131 m147_pcc->scsi_interrupt = 0x09;
0132
0133 m147_pcc->dma_cntrl = 0x00;
0134 m147_pcc->dma_intr = 0x89;
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
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);