1/*
2 * sgiwd93.c: SGI WD93 scsi driver.
3 *
4 * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
5 *		 1999 Andrew R. Baker (andrewb@uab.edu)
6 *		      - Support for 2nd SCSI controller on Indigo2
7 *		 2001 Florian Lohoff (flo@rfc822.org)
8 *		      - Delete HPC scatter gather (Read corruption on
9 *		        multiple disks)
10 *		      - Cleanup wback cache handling
11 *
12 * (In all truth, Jed Schimmel wrote all this code.)
13 *
14 */
15#include <linux/init.h>
16#include <linux/types.h>
17#include <linux/mm.h>
18#include <linux/blk.h>
19#include <linux/version.h>
20#include <linux/delay.h>
21#include <linux/spinlock.h>
22
23#include <asm/page.h>
24#include <asm/pgtable.h>
25#include <asm/sgialib.h>
26#include <asm/sgi/sgi.h>
27#include <asm/sgi/sgimc.h>
28#include <asm/sgi/sgihpc.h>
29#include <asm/sgi/sgint23.h>
30#include <asm/irq.h>
31#include <asm/io.h>
32
33#include "scsi.h"
34#include "hosts.h"
35#include "wd33c93.h"
36#include "sgiwd93.h"
37
38#include <linux/stat.h>
39
40struct hpc_chunk {
41	struct hpc_dma_desc desc;
42	u32 _padding;	/* align to quadword boundary */
43};
44
45struct Scsi_Host *sgiwd93_host = NULL;
46struct Scsi_Host *sgiwd93_host1 = NULL;
47
48/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */
49static inline void write_wd33c93_count(const wd33c93_regs regs,
50                                      unsigned long value)
51{
52	*regs.SASR = WD_TRANSFER_COUNT_MSB;
53	mb();
54	*regs.SCMD = ((value >> 16) & 0xff);
55	*regs.SCMD = ((value >>  8) & 0xff);
56	*regs.SCMD = ((value >>  0) & 0xff);
57	mb();
58}
59
60static inline unsigned long read_wd33c93_count(const wd33c93_regs regs)
61{
62	unsigned long value;
63
64	*regs.SASR = WD_TRANSFER_COUNT_MSB;
65	mb();
66	value =  ((*regs.SCMD & 0xff) << 16);
67	value |= ((*regs.SCMD & 0xff) <<  8);
68	value |= ((*regs.SCMD & 0xff) <<  0);
69	mb();
70	return value;
71}
72
73static void sgiwd93_intr(int irq, void *dev_id, struct pt_regs *regs)
74{
75	unsigned long flags;
76
77	spin_lock_irqsave(&io_request_lock, flags);
78	wd33c93_intr((struct Scsi_Host *) dev_id);
79	spin_unlock_irqrestore(&io_request_lock, flags);
80}
81
82#undef DEBUG_DMA
83
84static inline
85void fill_hpc_entries (struct hpc_chunk **hcp, char *addr, unsigned long len)
86{
87	unsigned long physaddr;
88	unsigned long count;
89
90	physaddr = PHYSADDR(addr);
91	while (len) {
92		/*
93		 * even cntinfo could be up to 16383, without
94		 * magic only 8192 works correctly
95		 */
96		count = len > 8192 ? 8192 : len;
97		(*hcp)->desc.pbuf = physaddr;
98		(*hcp)->desc.cntinfo = count;
99		(*hcp)++;
100		len -= count;
101		physaddr += count;
102	}
103}
104
105static int dma_setup(Scsi_Cmnd *cmd, int datainp)
106{
107	struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
108	struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) cmd->host->base;
109	struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->dma_bounce_buffer;
110
111#ifdef DEBUG_DMA
112	printk("dma_setup: datainp<%d> hcp<%p> ",
113	       datainp, hcp);
114#endif
115
116	hdata->dma_dir = datainp;
117
118	/*
119	 * wd33c93 shouldn't pass us bogus dma_setups, but
120	 * it does:-( The other wd33c93 drivers deal with
121	 * it the same way (which isn't that obvious).
122	 * IMHO a better fix would be, not to do these
123	 * dma setups in the first place
124	 */
125	if (cmd->SCp.ptr == NULL)
126		return 1;
127
128	fill_hpc_entries (&hcp, cmd->SCp.ptr,cmd->SCp.this_residual);
129
130	/* To make sure, if we trip an HPC bug, that we transfer
131	 * every single byte, we tag on an extra zero length dma
132	 * descriptor at the end of the chain.
133	 */
134	hcp->desc.pbuf = 0;
135	hcp->desc.cntinfo = (HPCDMA_EOX);
136
137#ifdef DEBUG_DMA
138	printk(" HPCGO\n");
139#endif
140
141	/* Start up the HPC. */
142	hregs->ndptr = PHYSADDR(hdata->dma_bounce_buffer);
143	if(datainp) {
144		dma_cache_inv((unsigned long) cmd->SCp.ptr, cmd->SCp.this_residual);
145		hregs->ctrl = (HPC3_SCTRL_ACTIVE);
146	} else {
147		dma_cache_wback_inv((unsigned long) cmd->SCp.ptr, cmd->SCp.this_residual);
148		hregs->ctrl = (HPC3_SCTRL_ACTIVE | HPC3_SCTRL_DIR);
149	}
150
151	return 0;
152}
153
154static void dma_stop(struct Scsi_Host *instance, Scsi_Cmnd *SCpnt,
155		     int status)
156{
157	struct WD33C93_hostdata *hdata = (struct WD33C93_hostdata *)instance->hostdata;
158	struct hpc3_scsiregs *hregs;
159
160	if (!SCpnt)
161		return;
162
163	hregs = (struct hpc3_scsiregs *) SCpnt->host->base;
164
165#ifdef DEBUG_DMA
166	printk("dma_stop: status<%d> ", status);
167#endif
168
169	/* First stop the HPC and flush it's FIFO. */
170	if(hdata->dma_dir) {
171		hregs->ctrl |= HPC3_SCTRL_FLUSH;
172		while(hregs->ctrl & HPC3_SCTRL_ACTIVE)
173			barrier();
174	}
175	hregs->ctrl = 0;
176
177#ifdef DEBUG_DMA
178	printk("\n");
179#endif
180}
181
182void sgiwd93_reset(unsigned long base)
183{
184	struct hpc3_scsiregs *hregs = (struct hpc3_scsiregs *) base;
185
186	hregs->ctrl = HPC3_SCTRL_CRESET;
187	udelay (50);
188	hregs->ctrl = 0;
189}
190
191static inline void init_hpc_chain(uchar *buf)
192{
193	struct hpc_chunk *hcp = (struct hpc_chunk *) buf;
194	unsigned long start, end;
195
196	start = (unsigned long) buf;
197	end = start + PAGE_SIZE;
198	while(start < end) {
199		hcp->desc.pnext = PHYSADDR((hcp + 1));
200		hcp->desc.cntinfo = HPCDMA_EOX;
201		hcp++;
202		start += sizeof(struct hpc_chunk);
203	};
204	hcp--;
205	hcp->desc.pnext = PHYSADDR(buf);
206
207	/* Force flush to memory */
208	dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE);
209}
210
211int __init sgiwd93_detect(Scsi_Host_Template *SGIblows)
212{
213	static unsigned char called = 0;
214	struct hpc3_scsiregs *hregs = &hpc3c0->scsi_chan0;
215	struct hpc3_scsiregs *hregs1 = &hpc3c0->scsi_chan1;
216	struct WD33C93_hostdata *hdata;
217	struct WD33C93_hostdata *hdata1;
218	wd33c93_regs regs;
219	uchar *buf;
220
221	if(called)
222		return 0; /* Should bitch on the console about this... */
223
224	SGIblows->proc_name = "SGIWD93";
225
226	sgiwd93_host = scsi_register(SGIblows, sizeof(struct WD33C93_hostdata));
227	if(sgiwd93_host == NULL)
228		return 0;
229	sgiwd93_host->base = (unsigned long) hregs;
230	sgiwd93_host->irq = SGI_WD93_0_IRQ;
231
232	buf = (uchar *) get_free_page(GFP_KERNEL);
233	if (!buf) {
234		printk(KERN_WARNING "sgiwd93: Could not allocate memory for host0 buffer.\n");
235		scsi_unregister(sgiwd93_host);
236		return 0;
237	}
238	init_hpc_chain(buf);
239
240	/* HPC_SCSI_REG0 | 0x03 | KSEG1 */
241	regs.SASR = (unsigned char*) KSEG1ADDR (0x1fbc0003);
242	regs.SCMD = (unsigned char*) KSEG1ADDR (0x1fbc0007);
243	wd33c93_init(sgiwd93_host, regs, dma_setup, dma_stop, WD33C93_FS_16_20);
244
245	hdata = (struct WD33C93_hostdata *)sgiwd93_host->hostdata;
246	hdata->no_sync = 0;
247	hdata->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf));
248
249	if (request_irq(SGI_WD93_0_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host)) {
250		printk(KERN_WARNING "sgiwd93: Could not register IRQ %d (for host 0).\n", SGI_WD93_0_IRQ);
251#ifdef MODULE
252		wd33c93_release();
253#endif
254		free_page((unsigned long)buf);
255		scsi_unregister(sgiwd93_host);
256		return 0;
257	}
258        /* set up second controller on the Indigo2 */
259	if(!sgi_guiness) {
260		sgiwd93_host1 = scsi_register(SGIblows, sizeof(struct WD33C93_hostdata));
261		if(sgiwd93_host1 != NULL)
262		{
263			sgiwd93_host1->base = (unsigned long) hregs1;
264			sgiwd93_host1->irq = SGI_WD93_1_IRQ;
265
266			buf = (uchar *) get_free_page(GFP_KERNEL);
267			if (!buf) {
268				printk(KERN_WARNING "sgiwd93: Could not allocate memory for host1 buffer.\n");
269				scsi_unregister(sgiwd93_host1);
270				called = 1;
271				return 1; /* We registered host0 so return success*/
272			}
273			init_hpc_chain(buf);
274
275			/* HPC_SCSI_REG1 | 0x03 | KSEG1 */
276			regs.SASR = (unsigned char*) KSEG1ADDR(0x1fbc8003);
277			regs.SCMD = (unsigned char*) KSEG1ADDR(0x1fbc8007);
278			wd33c93_init(sgiwd93_host1, regs, dma_setup, dma_stop,
279			             WD33C93_FS_16_20);
280
281			hdata1 = (struct WD33C93_hostdata *)sgiwd93_host1->hostdata;
282			hdata1->no_sync = 0;
283			hdata1->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf));
284
285			if (request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1)) {
286				printk(KERN_WARNING "sgiwd93: Could not allocate irq %d (for host1).\n", SGI_WD93_1_IRQ);
287#ifdef MODULE
288				wd33c93_release();
289#endif
290				free_page((unsigned long)buf);
291				scsi_unregister(sgiwd93_host1);
292				/* Fall through since host0 registered OK */
293			}
294		}
295	}
296
297	called = 1;
298
299	return 1; /* Found one. */
300}
301
302#define HOSTS_C
303
304#include "sgiwd93.h"
305
306static Scsi_Host_Template driver_template = SGIWD93_SCSI;
307
308#include "scsi_module.c"
309
310int sgiwd93_release(struct Scsi_Host *instance)
311{
312#ifdef MODULE
313	free_irq(SGI_WD93_0_IRQ, sgiwd93_intr);
314	free_page(KSEG0ADDR(hdata->dma_bounce_buffer));
315	wd33c93_release();
316	if(!sgi_guiness) {
317		free_irq(SGI_WD93_1_IRQ, sgiwd93_intr);
318		free_page(KSEG0ADDR(hdata1->dma_bounce_buffer));
319		wd33c93_release();
320	}
321#endif
322	return 1;
323}
324