Linux Audio

Check our new training course

Loading...
v3.1
 
  1#include <linux/types.h>
  2#include <linux/mm.h>
  3#include <linux/blkdev.h>
  4#include <linux/interrupt.h>
 
 
 
  5
  6#include <asm/page.h>
  7#include <asm/pgtable.h>
  8#include <asm/mvme147hw.h>
  9#include <asm/irq.h>
 10
 11#include "scsi.h"
 12#include <scsi/scsi_host.h>
 13#include "wd33c93.h"
 14#include "mvme147.h"
 15
 16#include <linux/stat.h>
 17
 18
 19static irqreturn_t mvme147_intr(int irq, void *data)
 20{
 21	struct Scsi_Host *instance = data;
 22
 23	if (irq == MVME147_IRQ_SCSI_PORT)
 24		wd33c93_intr(instance);
 25	else
 26		m147_pcc->dma_intr = 0x89;	/* Ack and enable ints */
 27	return IRQ_HANDLED;
 28}
 29
 30static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 31{
 32	struct Scsi_Host *instance = cmd->device->host;
 33	struct WD33C93_hostdata *hdata = shost_priv(instance);
 34	unsigned char flags = 0x01;
 35	unsigned long addr = virt_to_bus(cmd->SCp.ptr);
 36
 37	/* setup dma direction */
 38	if (!dir_in)
 39		flags |= 0x04;
 40
 41	/* remember direction */
 42	hdata->dma_dir = dir_in;
 43
 44	if (dir_in) {
 45		/* invalidate any cache */
 46		cache_clear(addr, cmd->SCp.this_residual);
 47	} else {
 48		/* push any dirty cache */
 49		cache_push(addr, cmd->SCp.this_residual);
 50	}
 51
 52	/* start DMA */
 53	m147_pcc->dma_bcr = cmd->SCp.this_residual | (1 << 24);
 54	m147_pcc->dma_dadr = addr;
 55	m147_pcc->dma_cntrl = flags;
 56
 57	/* return success */
 58	return 0;
 59}
 60
 61static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
 62		     int status)
 63{
 64	m147_pcc->dma_cntrl = 0;
 65}
 66
 67int mvme147_detect(struct scsi_host_template *tpnt)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 68{
 69	static unsigned char called = 0;
 70	struct Scsi_Host *instance;
 71	wd33c93_regs regs;
 72	struct WD33C93_hostdata *hdata;
 
 73
 74	if (!MACH_IS_MVME147 || called)
 75		return 0;
 76	called++;
 77
 78	tpnt->proc_name = "MVME147";
 79	tpnt->proc_info = &wd33c93_proc_info;
 80
 81	instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata));
 82	if (!instance)
 
 83		goto err_out;
 
 
 84
 85	instance->base = 0xfffe4000;
 86	instance->irq = MVME147_IRQ_SCSI_PORT;
 87	regs.SASR = (volatile unsigned char *)0xfffe4000;
 88	regs.SCMD = (volatile unsigned char *)0xfffe4001;
 89	hdata = shost_priv(instance);
 
 90	hdata->no_sync = 0xff;
 91	hdata->fast = 0;
 92	hdata->dma_mode = CTRL_DMA;
 93	wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
 94
 95	if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0,
 96			"MVME147 SCSI PORT", instance))
 
 
 
 97		goto err_unregister;
 98	if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0,
 99			"MVME147 SCSI DMA", instance))
 
100		goto err_free_irq;
101#if 0	/* Disabled; causes problems booting */
102	m147_pcc->scsi_interrupt = 0x10;	/* Assert SCSI bus reset */
103	udelay(100);
104	m147_pcc->scsi_interrupt = 0x00;	/* Negate SCSI bus reset */
105	udelay(2000);
106	m147_pcc->scsi_interrupt = 0x40;	/* Clear bus reset interrupt */
107#endif
108	m147_pcc->scsi_interrupt = 0x09;	/* Enable interrupt */
109
110	m147_pcc->dma_cntrl = 0x00;	/* ensure DMA is stopped */
111	m147_pcc->dma_intr = 0x89;	/* Ack and enable ints */
112
113	return 1;
 
 
 
 
114
115err_free_irq:
116	free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr);
117err_unregister:
118	scsi_unregister(instance);
119err_out:
120	return 0;
121}
122
123static int mvme147_bus_reset(struct scsi_cmnd *cmd)
124{
125	/* FIXME perform bus-specific reset */
126
127	/* FIXME 2: kill this function, and let midlayer fallback to
128	   the same result, calling wd33c93_host_reset() */
129
130	spin_lock_irq(cmd->device->host->host_lock);
131	wd33c93_host_reset(cmd);
132	spin_unlock_irq(cmd->device->host->host_lock);
133
134	return SUCCESS;
135}
136
137
138static struct scsi_host_template driver_template = {
139	.proc_name		= "MVME147",
140	.name			= "MVME147 built-in SCSI",
141	.detect			= mvme147_detect,
142	.release		= mvme147_release,
143	.queuecommand		= wd33c93_queuecommand,
144	.eh_abort_handler	= wd33c93_abort,
145	.eh_bus_reset_handler	= mvme147_bus_reset,
146	.eh_host_reset_handler	= wd33c93_host_reset,
147	.can_queue		= CAN_QUEUE,
148	.this_id		= 7,
149	.sg_tablesize		= SG_ALL,
150	.cmd_per_lun		= CMD_PER_LUN,
151	.use_clustering		= ENABLE_CLUSTERING
152};
153
154
155#include "scsi_module.c"
156
157int mvme147_release(struct Scsi_Host *instance)
158{
159#ifdef MODULE
160	/* XXX Make sure DMA is stopped! */
161	free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr);
162	free_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr);
163#endif
164	return 1;
165}
v4.17
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/types.h>
  3#include <linux/mm.h>
  4#include <linux/blkdev.h>
  5#include <linux/interrupt.h>
  6#include <linux/init.h>
  7#include <linux/kernel.h>
  8#include <linux/module.h>
  9
 10#include <asm/page.h>
 11#include <asm/pgtable.h>
 12#include <asm/mvme147hw.h>
 13#include <asm/irq.h>
 14
 15#include "scsi.h"
 16#include <scsi/scsi_host.h>
 17#include "wd33c93.h"
 18#include "mvme147.h"
 19
 
 
 
 20static irqreturn_t mvme147_intr(int irq, void *data)
 21{
 22	struct Scsi_Host *instance = data;
 23
 24	if (irq == MVME147_IRQ_SCSI_PORT)
 25		wd33c93_intr(instance);
 26	else
 27		m147_pcc->dma_intr = 0x89;	/* Ack and enable ints */
 28	return IRQ_HANDLED;
 29}
 30
 31static int dma_setup(struct scsi_cmnd *cmd, int dir_in)
 32{
 33	struct Scsi_Host *instance = cmd->device->host;
 34	struct WD33C93_hostdata *hdata = shost_priv(instance);
 35	unsigned char flags = 0x01;
 36	unsigned long addr = virt_to_bus(cmd->SCp.ptr);
 37
 38	/* setup dma direction */
 39	if (!dir_in)
 40		flags |= 0x04;
 41
 42	/* remember direction */
 43	hdata->dma_dir = dir_in;
 44
 45	if (dir_in) {
 46		/* invalidate any cache */
 47		cache_clear(addr, cmd->SCp.this_residual);
 48	} else {
 49		/* push any dirty cache */
 50		cache_push(addr, cmd->SCp.this_residual);
 51	}
 52
 53	/* start DMA */
 54	m147_pcc->dma_bcr = cmd->SCp.this_residual | (1 << 24);
 55	m147_pcc->dma_dadr = addr;
 56	m147_pcc->dma_cntrl = flags;
 57
 58	/* return success */
 59	return 0;
 60}
 61
 62static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
 63		     int status)
 64{
 65	m147_pcc->dma_cntrl = 0;
 66}
 67
 68static struct scsi_host_template mvme147_host_template = {
 69	.module			= THIS_MODULE,
 70	.proc_name		= "MVME147",
 71	.name			= "MVME147 built-in SCSI",
 72	.queuecommand		= wd33c93_queuecommand,
 73	.eh_abort_handler	= wd33c93_abort,
 74	.eh_host_reset_handler	= wd33c93_host_reset,
 75	.show_info		= wd33c93_show_info,
 76	.write_info		= wd33c93_write_info,
 77	.can_queue		= CAN_QUEUE,
 78	.this_id		= 7,
 79	.sg_tablesize		= SG_ALL,
 80	.cmd_per_lun		= CMD_PER_LUN,
 81	.use_clustering		= ENABLE_CLUSTERING
 82};
 83
 84static struct Scsi_Host *mvme147_shost;
 85
 86static int __init mvme147_init(void)
 87{
 
 
 88	wd33c93_regs regs;
 89	struct WD33C93_hostdata *hdata;
 90	int error = -ENOMEM;
 91
 92	if (!MACH_IS_MVME147)
 93		return 0;
 
 
 
 
 94
 95	mvme147_shost = scsi_host_alloc(&mvme147_host_template,
 96			sizeof(struct WD33C93_hostdata));
 97	if (!mvme147_shost)
 98		goto err_out;
 99	mvme147_shost->base = 0xfffe4000;
100	mvme147_shost->irq = MVME147_IRQ_SCSI_PORT;
101
 
 
102	regs.SASR = (volatile unsigned char *)0xfffe4000;
103	regs.SCMD = (volatile unsigned char *)0xfffe4001;
104
105	hdata = shost_priv(mvme147_shost);
106	hdata->no_sync = 0xff;
107	hdata->fast = 0;
108	hdata->dma_mode = CTRL_DMA;
 
109
110	wd33c93_init(mvme147_shost, regs, dma_setup, dma_stop, WD33C93_FS_8_10);
111
112	error = request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0,
113			"MVME147 SCSI PORT", mvme147_shost);
114	if (error)
115		goto err_unregister;
116	error = request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0,
117			"MVME147 SCSI DMA", mvme147_shost);
118	if (error)
119		goto err_free_irq;
120#if 0	/* Disabled; causes problems booting */
121	m147_pcc->scsi_interrupt = 0x10;	/* Assert SCSI bus reset */
122	udelay(100);
123	m147_pcc->scsi_interrupt = 0x00;	/* Negate SCSI bus reset */
124	udelay(2000);
125	m147_pcc->scsi_interrupt = 0x40;	/* Clear bus reset interrupt */
126#endif
127	m147_pcc->scsi_interrupt = 0x09;	/* Enable interrupt */
128
129	m147_pcc->dma_cntrl = 0x00;	/* ensure DMA is stopped */
130	m147_pcc->dma_intr = 0x89;	/* Ack and enable ints */
131
132	error = scsi_add_host(mvme147_shost, NULL);
133	if (error)
134		goto err_free_irq;
135	scsi_scan_host(mvme147_shost);
136	return 0;
137
138err_free_irq:
139	free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost);
140err_unregister:
141	scsi_host_put(mvme147_shost);
142err_out:
143	return error;
144}
145
146static void __exit mvme147_exit(void)
147{
148	scsi_remove_host(mvme147_shost);
149
150	/* XXX Make sure DMA is stopped! */
151	free_irq(MVME147_IRQ_SCSI_PORT, mvme147_shost);
152	free_irq(MVME147_IRQ_SCSI_DMA, mvme147_shost);
 
 
 
153
154	scsi_host_put(mvme147_shost);
155}
156
157module_init(mvme147_init);
158module_exit(mvme147_exit);