• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/scsi/
1
2#define AUTOSENSE
3#define PSEUDO_DMA
4#define DONT_USE_INTR
5#define UNSAFE			/* Leave interrupts enabled during pseudo-dma I/O */
6#define xNDEBUG (NDEBUG_INTR+NDEBUG_RESELECTION+\
7		 NDEBUG_SELECTION+NDEBUG_ARBITRATION)
8#define DMA_WORKS_RIGHT
9
10
11/*
12 * DTC 3180/3280 driver, by
13 *	Ray Van Tassle	rayvt@comm.mot.com
14 *
15 *	taken from ...
16 *	Trantor T128/T128F/T228 driver by...
17 *
18 * 	Drew Eckhardt
19 *	Visionary Computing
20 *	(Unix and Linux consulting and custom programming)
21 *	drew@colorado.edu
22 *      +1 (303) 440-4894
23 *
24 * DISTRIBUTION RELEASE 1.
25 *
26 * For more information, please consult
27 *
28 * NCR 5380 Family
29 * SCSI Protocol Controller
30 * Databook
31*/
32
33/*
34 * Options :
35 * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically
36 *      for commands that return with a CHECK CONDITION status.
37 *
38 * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance
39 * increase compared to polled I/O.
40 *
41 * PARITY - enable parity checking.  Not supported.
42 *
43 * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.
44 *		You probably want this.
45 *
46 * The card is detected and initialized in one of several ways :
47 * 1.  Autoprobe (default) - since the board is memory mapped,
48 *     a BIOS signature is scanned for to locate the registers.
49 *     An interrupt is triggered to autoprobe for the interrupt
50 *     line.
51 *
52 * 2.  With command line overrides - dtc=address,irq may be
53 *     used on the LILO command line to override the defaults.
54 *
55*/
56
57/*----------------------------------------------------------------*/
58/* the following will set the monitor border color (useful to find
59 where something crashed or gets stuck at */
60/* 1 = blue
61 2 = green
62 3 = cyan
63 4 = red
64 5 = magenta
65 6 = yellow
66 7 = white
67*/
68#define rtrc(i) {}
69
70
71#include <asm/system.h>
72#include <linux/module.h>
73#include <linux/signal.h>
74#include <linux/blkdev.h>
75#include <linux/delay.h>
76#include <linux/stat.h>
77#include <linux/string.h>
78#include <linux/init.h>
79#include <linux/interrupt.h>
80#include <linux/io.h>
81#include "scsi.h"
82#include <scsi/scsi_host.h>
83#include "dtc.h"
84#define AUTOPROBE_IRQ
85#include "NCR5380.h"
86
87
88#define DTC_PUBLIC_RELEASE 2
89
90/*
91 * The DTC3180 & 3280 boards are memory mapped.
92 *
93 */
94
95/*
96 */
97/* Offset from DTC_5380_OFFSET */
98#define DTC_CONTROL_REG		0x100	/* rw */
99#define D_CR_ACCESS		0x80	/* ro set=can access 3280 registers */
100#define CSR_DIR_READ		0x40	/* rw direction, 1 = read 0 = write */
101
102#define CSR_RESET              0x80	/* wo  Resets 53c400 */
103#define CSR_5380_REG           0x80	/* ro  5380 registers can be accessed */
104#define CSR_TRANS_DIR          0x40	/* rw  Data transfer direction */
105#define CSR_SCSI_BUFF_INTR     0x20	/* rw  Enable int on transfer ready */
106#define CSR_5380_INTR          0x10	/* rw  Enable 5380 interrupts */
107#define CSR_SHARED_INTR        0x08	/* rw  Interrupt sharing */
108#define CSR_HOST_BUF_NOT_RDY   0x04	/* ro  Host buffer not ready */
109#define CSR_SCSI_BUF_RDY       0x02	/* ro  SCSI buffer ready */
110#define CSR_GATED_5380_IRQ     0x01	/* ro  Last block xferred */
111#define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR)
112
113
114#define DTC_BLK_CNT		0x101	/* rw
115					 * # of 128-byte blocks to transfer */
116
117
118#define D_CR_ACCESS             0x80	/* ro set=can access 3280 registers */
119
120#define DTC_SWITCH_REG		0x3982	/* ro - DIP switches */
121#define DTC_RESUME_XFER		0x3982	/* wo - resume data xfer
122					 * after disconnect/reconnect*/
123
124#define DTC_5380_OFFSET		0x3880	/* 8 registers here, see NCR5380.h */
125
126/*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */
127#define DTC_DATA_BUF		0x3900	/* rw 128 bytes long */
128
129static struct override {
130	unsigned int address;
131	int irq;
132} overrides
133#ifdef OVERRIDE
134[] __initdata = OVERRIDE;
135#else
136[4] __initdata = {
137	{ 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }
138};
139#endif
140
141#define NO_OVERRIDES ARRAY_SIZE(overrides)
142
143static struct base {
144	unsigned long address;
145	int noauto;
146} bases[] __initdata = {
147	{ 0xcc000, 0 },
148	{ 0xc8000, 0 },
149	{ 0xdc000, 0 },
150	{ 0xd8000, 0 }
151};
152
153#define NO_BASES ARRAY_SIZE(bases)
154
155static const struct signature {
156	const char *string;
157	int offset;
158} signatures[] = {
159	{"DATA TECHNOLOGY CORPORATION BIOS", 0x25},
160};
161
162#define NO_SIGNATURES ARRAY_SIZE(signatures)
163
164#ifndef MODULE
165/*
166 * Function : dtc_setup(char *str, int *ints)
167 *
168 * Purpose : LILO command line initialization of the overrides array,
169 *
170 * Inputs : str - unused, ints - array of integer parameters with ints[0]
171 *	equal to the number of ints.
172 *
173 */
174
175static void __init dtc_setup(char *str, int *ints)
176{
177	static int commandline_current = 0;
178	int i;
179	if (ints[0] != 2)
180		printk("dtc_setup: usage dtc=address,irq\n");
181	else if (commandline_current < NO_OVERRIDES) {
182		overrides[commandline_current].address = ints[1];
183		overrides[commandline_current].irq = ints[2];
184		for (i = 0; i < NO_BASES; ++i)
185			if (bases[i].address == ints[1]) {
186				bases[i].noauto = 1;
187				break;
188			}
189		++commandline_current;
190	}
191}
192#endif
193
194/*
195 * Function : int dtc_detect(struct scsi_host_template * tpnt)
196 *
197 * Purpose : detects and initializes DTC 3180/3280 controllers
198 *	that were autoprobed, overridden on the LILO command line,
199 *	or specified at compile time.
200 *
201 * Inputs : tpnt - template for this SCSI adapter.
202 *
203 * Returns : 1 if a host adapter was found, 0 if not.
204 *
205*/
206
207static int __init dtc_detect(struct scsi_host_template * tpnt)
208{
209	static int current_override = 0, current_base = 0;
210	struct Scsi_Host *instance;
211	unsigned int addr;
212	void __iomem *base;
213	int sig, count;
214
215	tpnt->proc_name = "dtc3x80";
216	tpnt->proc_info = &dtc_proc_info;
217
218	for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
219		addr = 0;
220		base = NULL;
221
222		if (overrides[current_override].address) {
223			addr = overrides[current_override].address;
224			base = ioremap(addr, 0x2000);
225			if (!base)
226				addr = 0;
227		} else
228			for (; !addr && (current_base < NO_BASES); ++current_base) {
229#if (DTCDEBUG & DTCDEBUG_INIT)
230				printk(KERN_DEBUG "scsi-dtc : probing address %08x\n", bases[current_base].address);
231#endif
232				if (bases[current_base].noauto)
233					continue;
234				base = ioremap(bases[current_base].address, 0x2000);
235				if (!base)
236					continue;
237				for (sig = 0; sig < NO_SIGNATURES; ++sig) {
238					if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) {
239						addr = bases[current_base].address;
240#if (DTCDEBUG & DTCDEBUG_INIT)
241						printk(KERN_DEBUG "scsi-dtc : detected board.\n");
242#endif
243						goto found;
244					}
245				}
246				iounmap(base);
247			}
248
249#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
250		printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr);
251#endif
252
253		if (!addr)
254			break;
255
256found:
257		instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
258		if (instance == NULL)
259			break;
260
261		instance->base = addr;
262		((struct NCR5380_hostdata *)(instance)->hostdata)->base = base;
263
264		NCR5380_init(instance, 0);
265
266		NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);	/* Enable int's */
267		if (overrides[current_override].irq != IRQ_AUTO)
268			instance->irq = overrides[current_override].irq;
269		else
270			instance->irq = NCR5380_probe_irq(instance, DTC_IRQS);
271
272#ifndef DONT_USE_INTR
273		/* With interrupts enabled, it will sometimes hang when doing heavy
274		 * reads. So better not enable them until I finger it out. */
275		if (instance->irq != SCSI_IRQ_NONE)
276			if (request_irq(instance->irq, dtc_intr, IRQF_DISABLED,
277					"dtc", instance)) {
278				printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
279				instance->irq = SCSI_IRQ_NONE;
280			}
281
282		if (instance->irq == SCSI_IRQ_NONE) {
283			printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
284			printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
285		}
286#else
287		if (instance->irq != SCSI_IRQ_NONE)
288			printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no);
289		instance->irq = SCSI_IRQ_NONE;
290#endif
291#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT)
292		printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
293#endif
294
295		printk(KERN_INFO "scsi%d : at 0x%05X", instance->host_no, (int) instance->base);
296		if (instance->irq == SCSI_IRQ_NONE)
297			printk(" interrupts disabled");
298		else
299			printk(" irq %d", instance->irq);
300		printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, DTC_PUBLIC_RELEASE);
301		NCR5380_print_options(instance);
302		printk("\n");
303
304		++current_override;
305		++count;
306	}
307	return count;
308}
309
310/*
311 * Function : int dtc_biosparam(Disk * disk, struct block_device *dev, int *ip)
312 *
313 * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for
314 *	the specified device / size.
315 *
316 * Inputs : size = size of device in sectors (512 bytes), dev = block device
317 *	major / minor, ip[] = {heads, sectors, cylinders}
318 *
319 * Returns : always 0 (success), initializes ip
320 *
321*/
322
323
324static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev,
325			 sector_t capacity, int *ip)
326{
327	int size = capacity;
328
329	ip[0] = 64;
330	ip[1] = 32;
331	ip[2] = size >> 11;
332	return 0;
333}
334
335
336/****************************************************************
337 * Function : int NCR5380_pread (struct Scsi_Host *instance,
338 *	unsigned char *dst, int len)
339 *
340 * Purpose : Fast 5380 pseudo-dma read function, reads len bytes to
341 *	dst
342 *
343 * Inputs : dst = destination, len = length in bytes
344 *
345 * Returns : 0 on success, non zero on a failure such as a watchdog
346 * 	timeout.
347*/
348
349static int dtc_maxi = 0;
350static int dtc_wmaxi = 0;
351
352static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
353{
354	unsigned char *d = dst;
355	int i;			/* For counting time spent in the poll-loop */
356	NCR5380_local_declare();
357	NCR5380_setup(instance);
358
359	i = 0;
360	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
361	NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
362	if (instance->irq == SCSI_IRQ_NONE)
363		NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ);
364	else
365		NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE);
366	NCR5380_write(DTC_BLK_CNT, len >> 7);	/* Block count */
367	rtrc(1);
368	while (len > 0) {
369		rtrc(2);
370		while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
371			++i;
372		rtrc(3);
373		memcpy_fromio(d, base + DTC_DATA_BUF, 128);
374		d += 128;
375		len -= 128;
376		rtrc(7);
377		/*** with int's on, it sometimes hangs after here.
378		 * Looks like something makes HBNR go away. */
379	}
380	rtrc(4);
381	while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
382		++i;
383	NCR5380_write(MODE_REG, 0);	/* Clear the operating mode */
384	rtrc(0);
385	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
386	if (i > dtc_maxi)
387		dtc_maxi = i;
388	return (0);
389}
390
391/****************************************************************
392 * Function : int NCR5380_pwrite (struct Scsi_Host *instance,
393 *	unsigned char *src, int len)
394 *
395 * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
396 *	src
397 *
398 * Inputs : src = source, len = length in bytes
399 *
400 * Returns : 0 on success, non zero on a failure such as a watchdog
401 * 	timeout.
402*/
403
404static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
405{
406	int i;
407	NCR5380_local_declare();
408	NCR5380_setup(instance);
409
410	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
411	NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE);
412	/* set direction (write) */
413	if (instance->irq == SCSI_IRQ_NONE)
414		NCR5380_write(DTC_CONTROL_REG, 0);
415	else
416		NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR);
417	NCR5380_write(DTC_BLK_CNT, len >> 7);	/* Block count */
418	for (i = 0; len > 0; ++i) {
419		rtrc(5);
420		/* Poll until the host buffer can accept data. */
421		while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY)
422			++i;
423		rtrc(3);
424		memcpy_toio(base + DTC_DATA_BUF, src, 128);
425		src += 128;
426		len -= 128;
427	}
428	rtrc(4);
429	while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS))
430		++i;
431	rtrc(6);
432	/* Wait until the last byte has been sent to the disk */
433	while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT))
434		++i;
435	rtrc(7);
436	NCR5380_write(MODE_REG, 0);	/* Clear the operating mode */
437	rtrc(0);
438	if (i > dtc_wmaxi)
439		dtc_wmaxi = i;
440	return (0);
441}
442
443MODULE_LICENSE("GPL");
444
445#include "NCR5380.c"
446
447static int dtc_release(struct Scsi_Host *shost)
448{
449	NCR5380_local_declare();
450	NCR5380_setup(shost);
451	if (shost->irq)
452		free_irq(shost->irq, shost);
453	NCR5380_exit(shost);
454	if (shost->io_port && shost->n_io_port)
455		release_region(shost->io_port, shost->n_io_port);
456	scsi_unregister(shost);
457	iounmap(base);
458	return 0;
459}
460
461static struct scsi_host_template driver_template = {
462	.name				= "DTC 3180/3280 ",
463	.detect				= dtc_detect,
464	.release			= dtc_release,
465	.queuecommand			= dtc_queue_command,
466	.eh_abort_handler		= dtc_abort,
467	.eh_bus_reset_handler		= dtc_bus_reset,
468	.bios_param     		= dtc_biosparam,
469	.can_queue      		= CAN_QUEUE,
470	.this_id        		= 7,
471	.sg_tablesize   		= SG_ALL,
472	.cmd_per_lun    		= CMD_PER_LUN,
473	.use_clustering 		= DISABLE_CLUSTERING,
474};
475#include "scsi_module.c"
476