Blame view

drivers/scsi/atari_scsi.c 26.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * atari_scsi.c -- Device dependent functions for the Atari generic SCSI port
   *
   * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
   *
   *   Loosely based on the work of Robert De Vries' team and added:
   *    - working real DMA
   *    - Falcon support (untested yet!)   ++bjoern fixed and now it works
   *    - lots of extensions and bug fixes.
   *
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file COPYING in the main directory of this archive
   * for more details.
   *
   */
ded155b5e   Finn Thain   atari_scsi: Allow...
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  /*
   * Notes for Falcon SCSI DMA
   *
   * The 5380 device is one of several that all share the DMA chip. Hence
   * "locking" and "unlocking" access to this chip is required.
   *
   * Two possible schemes for ST DMA acquisition by atari_scsi are:
   * 1) The lock is taken for each command separately (i.e. can_queue == 1).
   * 2) The lock is taken when the first command arrives and released
   * when the last command is finished (i.e. can_queue > 1).
   *
   * The first alternative limits SCSI bus utilization, since interleaving
   * commands is not possible. The second gives better performance but is
   * unfair to other drivers needing to use the ST DMA chip. In order to
   * allow the IDE and floppy drivers equal access to the ST DMA chip
   * the default is can_queue == 1.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37
38
39
40
  #include <linux/interrupt.h>
  #include <linux/init.h>
  #include <linux/nvram.h>
  #include <linux/bitops.h>
eff9cf8d6   Arnd Bergmann   [SCSI] atari_scsi...
41
  #include <linux/wait.h>
3ff228af8   Finn Thain   atari_scsi: Conve...
42
  #include <linux/platform_device.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
44
45
46
  
  #include <asm/setup.h>
  #include <asm/atarihw.h>
  #include <asm/atariints.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
47
48
49
  #include <asm/atari_stdma.h>
  #include <asm/atari_stram.h>
  #include <asm/io.h>
3ff228af8   Finn Thain   atari_scsi: Conve...
50
  #include <scsi/scsi_host.h>
e63449c43   Finn Thain   atari_NCR5380: Re...
51
  #define DMA_MIN_SIZE                    32
4e7052052   Finn Thain   atari_scsi: Remov...
52
  /* Definitions for the core NCR5380 driver. */
4e7052052   Finn Thain   atari_scsi: Remov...
53
  #define NCR5380_implementation_fields   /* none */
7c6066314   Finn Thain   scsi: ncr5380: Ex...
54
55
  static u8 (*atari_scsi_reg_read)(unsigned int);
  static void (*atari_scsi_reg_write)(unsigned int, u8);
4e7052052   Finn Thain   atari_scsi: Remov...
56
57
58
59
60
  #define NCR5380_read(reg)               atari_scsi_reg_read(reg)
  #define NCR5380_write(reg, value)       atari_scsi_reg_write(reg, value)
  
  #define NCR5380_queue_command           atari_scsi_queue_command
  #define NCR5380_abort                   atari_scsi_abort
4e7052052   Finn Thain   atari_scsi: Remov...
61
  #define NCR5380_info                    atari_scsi_info
4a98f896b   Finn Thain   scsi: ncr5380: Us...
62
63
64
65
  #define NCR5380_dma_xfer_len            atari_scsi_dma_xfer_len
  #define NCR5380_dma_recv_setup          atari_scsi_dma_recv_setup
  #define NCR5380_dma_send_setup          atari_scsi_dma_send_setup
  #define NCR5380_dma_residual            atari_scsi_dma_residual
4e7052052   Finn Thain   atari_scsi: Remov...
66

a53a21e46   Finn Thain   atari_NCR5380: Mo...
67
  #define NCR5380_acquire_dma_irq(instance)      falcon_get_lock(instance)
e3c3da673   Finn Thain   atari_NCR5380: Re...
68
  #define NCR5380_release_dma_irq(instance)      falcon_release_lock()
3ff228af8   Finn Thain   atari_scsi: Conve...
69
  #include "NCR5380.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70

4e7052052   Finn Thain   atari_scsi: Remov...
71

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  #define	IS_A_TT()	ATARIHW_PRESENT(TT_SCSI)
  
  #define	SCSI_DMA_WRITE_P(elt,val)				\
  	do {							\
  		unsigned long v = val;				\
  		tt_scsi_dma.elt##_lo = v & 0xff;		\
  		v >>= 8;					\
  		tt_scsi_dma.elt##_lmd = v & 0xff;		\
  		v >>= 8;					\
  		tt_scsi_dma.elt##_hmd = v & 0xff;		\
  		v >>= 8;					\
  		tt_scsi_dma.elt##_hi = v & 0xff;		\
  	} while(0)
  
  #define	SCSI_DMA_READ_P(elt)					\
  	(((((((unsigned long)tt_scsi_dma.elt##_hi << 8) |	\
  	     (unsigned long)tt_scsi_dma.elt##_hmd) << 8) |	\
  	   (unsigned long)tt_scsi_dma.elt##_lmd) << 8) |	\
  	 (unsigned long)tt_scsi_dma.elt##_lo)
  
  
  static inline void SCSI_DMA_SETADR(unsigned long adr)
  {
  	st_dma.dma_lo = (unsigned char)adr;
  	MFPDELAY();
  	adr >>= 8;
  	st_dma.dma_md = (unsigned char)adr;
  	MFPDELAY();
  	adr >>= 8;
  	st_dma.dma_hi = (unsigned char)adr;
  	MFPDELAY();
  }
  
  static inline unsigned long SCSI_DMA_GETADR(void)
  {
  	unsigned long adr;
  	adr = st_dma.dma_lo;
  	MFPDELAY();
  	adr |= (st_dma.dma_md & 0xff) << 8;
  	MFPDELAY();
  	adr |= (st_dma.dma_hi & 0xff) << 16;
  	MFPDELAY();
  	return adr;
  }
c28bda251   Roman Zippel   m68k: Reformat th...
116
  static void atari_scsi_fetch_restbytes(void);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
117

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
119
120
  static unsigned long	atari_dma_residual, atari_dma_startaddr;
  static short		atari_dma_active;
  /* pointer to the dribble buffer */
c28bda251   Roman Zippel   m68k: Reformat th...
121
  static char		*atari_dma_buffer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
127
128
129
130
131
132
133
134
135
  /* precalculated physical address of the dribble buffer */
  static unsigned long	atari_dma_phys_buffer;
  /* != 0 tells the Falcon int handler to copy data from the dribble buffer */
  static char		*atari_dma_orig_addr;
  /* size of the dribble buffer; 4k seems enough, since the Falcon cannot use
   * scatter-gather anyway, so most transfers are 1024 byte only. In the rare
   * cases where requests to physical contiguous buffers have been merged, this
   * request is <= 4k (one page). So I don't think we have to split transfers
   * just due to this buffer size...
   */
  #define	STRAM_BUFFER_SIZE	(4096)
  /* mask for address bits that can't be used with the ST-DMA */
  static unsigned long	atari_dma_stram_mask;
  #define STRAM_ADDR(a)	(((a) & atari_dma_stram_mask) == 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
  
  static int setup_can_queue = -1;
8d3b33f67   Rusty Russell   [PATCH] Remove MO...
138
  module_param(setup_can_queue, int, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
  static int setup_cmd_per_lun = -1;
8d3b33f67   Rusty Russell   [PATCH] Remove MO...
140
  module_param(setup_cmd_per_lun, int, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
141
  static int setup_sg_tablesize = -1;
8d3b33f67   Rusty Russell   [PATCH] Remove MO...
142
  module_param(setup_sg_tablesize, int, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
143
  static int setup_hostid = -1;
8d3b33f67   Rusty Russell   [PATCH] Remove MO...
144
  module_param(setup_hostid, int, 0);
9c3f0e2b5   Finn Thain   atari_NCR5380: Re...
145
146
  static int setup_toshiba_delay = -1;
  module_param(setup_toshiba_delay, int, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147

c28bda251   Roman Zippel   m68k: Reformat th...
148
  static int scsi_dma_is_ignored_buserr(unsigned char dma_stat)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
150
  {
  	int i;
c28bda251   Roman Zippel   m68k: Reformat th...
151
  	unsigned long addr = SCSI_DMA_READ_P(dma_addr), end_addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152
153
154
155
156
157
158
  
  	if (dma_stat & 0x01) {
  
  		/* A bus error happens when DMA-ing from the last page of a
  		 * physical memory chunk (DMA prefetch!), but that doesn't hurt.
  		 * Check for this case:
  		 */
c28bda251   Roman Zippel   m68k: Reformat th...
159
160
161
  
  		for (i = 0; i < m68k_num_memory; ++i) {
  			end_addr = m68k_memory[i].addr + m68k_memory[i].size;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
  			if (end_addr <= addr && addr <= end_addr + 4)
c28bda251   Roman Zippel   m68k: Reformat th...
163
  				return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
  		}
  	}
c28bda251   Roman Zippel   m68k: Reformat th...
166
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
167
  }
cd46140a9   Finn Thain   atari_scsi, sun3_...
168
  static irqreturn_t scsi_tt_intr(int irq, void *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
  {
cd46140a9   Finn Thain   atari_scsi, sun3_...
170
171
  	struct Scsi_Host *instance = dev;
  	struct NCR5380_hostdata *hostdata = shost_priv(instance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
172
173
174
  	int dma_stat;
  
  	dma_stat = tt_scsi_dma.dma_ctrl;
cd46140a9   Finn Thain   atari_scsi, sun3_...
175
176
177
  	dsprintk(NDEBUG_INTR, instance, "NCR5380 interrupt, DMA status = %02x
  ",
  	         dma_stat & 0xff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
181
182
  
  	/* Look if it was the DMA that has interrupted: First possibility
  	 * is that a bus error occurred...
  	 */
  	if (dma_stat & 0x80) {
c28bda251   Roman Zippel   m68k: Reformat th...
183
  		if (!scsi_dma_is_ignored_buserr(dma_stat)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  			printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx
  ",
  			       SCSI_DMA_READ_P(dma_addr));
  			printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!");
  		}
  	}
  
  	/* If the DMA is active but not finished, we have the case
  	 * that some other 5380 interrupt occurred within the DMA transfer.
  	 * This means we have residual bytes, if the desired end address
  	 * is not yet reached. Maybe we have to fetch some bytes from the
  	 * rest data register, too. The residual must be calculated from
  	 * the address pointer, not the counter register, because only the
  	 * addr reg counts bytes not yet written and pending in the rest
  	 * data reg!
  	 */
  	if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
cd46140a9   Finn Thain   atari_scsi, sun3_...
201
202
  		atari_dma_residual = hostdata->dma_len -
  			(SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
203

d65e634a8   Finn Thain   scsi/NCR5380: ado...
204
205
  		dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
208
209
210
  			   atari_dma_residual);
  
  		if ((signed int)atari_dma_residual < 0)
  			atari_dma_residual = 0;
  		if ((dma_stat & 1) == 0) {
c28bda251   Roman Zippel   m68k: Reformat th...
211
212
213
214
  			/*
  			 * After read operations, we maybe have to
  			 * transport some rest bytes
  			 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
  			atari_scsi_fetch_restbytes();
c28bda251   Roman Zippel   m68k: Reformat th...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  		} else {
  			/*
  			 * There seems to be a nasty bug in some SCSI-DMA/NCR
  			 * combinations: If a target disconnects while a write
  			 * operation is going on, the address register of the
  			 * DMA may be a few bytes farer than it actually read.
  			 * This is probably due to DMA prefetching and a delay
  			 * between DMA and NCR.  Experiments showed that the
  			 * dma_addr is 9 bytes to high, but this could vary.
  			 * The problem is, that the residual is thus calculated
  			 * wrong and the next transfer will start behind where
  			 * it should.  So we round up the residual to the next
  			 * multiple of a sector size, if it isn't already a
  			 * multiple and the originally expected transfer size
  			 * was.  The latter condition is there to ensure that
  			 * the correction is taken only for "real" data
  			 * transfers and not for, e.g., the parameters of some
  			 * other command.  These shouldn't disconnect anyway.
  			 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
  			if (atari_dma_residual & 0x1ff) {
d65e634a8   Finn Thain   scsi/NCR5380: ado...
236
  				dprintk(NDEBUG_DMA, "SCSI DMA: DMA bug corrected, "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
  					   "difference %ld bytes
  ",
  					   512 - (atari_dma_residual & 0x1ff));
  				atari_dma_residual = (atari_dma_residual + 511) & ~0x1ff;
  			}
  		}
  		tt_scsi_dma.dma_ctrl = 0;
  	}
  
  	/* If the DMA is finished, fetch the rest bytes and turn it off */
  	if (dma_stat & 0x40) {
  		atari_dma_residual = 0;
  		if ((dma_stat & 1) == 0)
  			atari_scsi_fetch_restbytes();
  		tt_scsi_dma.dma_ctrl = 0;
  	}
cd46140a9   Finn Thain   atari_scsi, sun3_...
253
  	NCR5380_intr(irq, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
  	return IRQ_HANDLED;
  }
cd46140a9   Finn Thain   atari_scsi, sun3_...
257
  static irqreturn_t scsi_falcon_intr(int irq, void *dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  {
cd46140a9   Finn Thain   atari_scsi, sun3_...
259
260
  	struct Scsi_Host *instance = dev;
  	struct NCR5380_hostdata *hostdata = shost_priv(instance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
  	int dma_stat;
  
  	/* Turn off DMA and select sector counter register before
  	 * accessing the status register (Atari recommendation!)
  	 */
  	st_dma.dma_mode_status = 0x90;
  	dma_stat = st_dma.dma_mode_status;
  
  	/* Bit 0 indicates some error in the DMA process... don't know
  	 * what happened exactly (no further docu).
  	 */
  	if (!(dma_stat & 0x01)) {
  		/* DMA error */
  		printk(KERN_CRIT "SCSI DMA error near 0x%08lx!
  ", SCSI_DMA_GETADR());
  	}
  
  	/* If the DMA was active, but now bit 1 is not clear, it is some
  	 * other 5380 interrupt that finishes the DMA transfer. We have to
  	 * calculate the number of residual bytes and give a warning if
  	 * bytes are stuck in the ST-DMA fifo (there's no way to reach them!)
  	 */
  	if (atari_dma_active && (dma_stat & 0x02)) {
c28bda251   Roman Zippel   m68k: Reformat th...
284
  		unsigned long transferred;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
286
287
288
289
290
291
292
293
294
295
  
  		transferred = SCSI_DMA_GETADR() - atari_dma_startaddr;
  		/* The ST-DMA address is incremented in 2-byte steps, but the
  		 * data are written only in 16-byte chunks. If the number of
  		 * transferred bytes is not divisible by 16, the remainder is
  		 * lost somewhere in outer space.
  		 */
  		if (transferred & 15)
  			printk(KERN_ERR "SCSI DMA error: %ld bytes lost in "
  			       "ST-DMA fifo
  ", transferred & 15);
cd46140a9   Finn Thain   atari_scsi, sun3_...
296
  		atari_dma_residual = hostdata->dma_len - transferred;
d65e634a8   Finn Thain   scsi/NCR5380: ado...
297
298
  		dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
  			   atari_dma_residual);
c28bda251   Roman Zippel   m68k: Reformat th...
300
  	} else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
302
303
304
305
306
307
308
  		atari_dma_residual = 0;
  	atari_dma_active = 0;
  
  	if (atari_dma_orig_addr) {
  		/* If the dribble buffer was used on a read operation, copy the DMA-ed
  		 * data to the original destination address.
  		 */
  		memcpy(atari_dma_orig_addr, phys_to_virt(atari_dma_startaddr),
cd46140a9   Finn Thain   atari_scsi, sun3_...
309
  		       hostdata->dma_len - atari_dma_residual);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
311
  		atari_dma_orig_addr = NULL;
  	}
cd46140a9   Finn Thain   atari_scsi, sun3_...
312
  	NCR5380_intr(irq, dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
  	return IRQ_HANDLED;
  }
c28bda251   Roman Zippel   m68k: Reformat th...
315
  static void atari_scsi_fetch_restbytes(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316
317
318
319
320
321
322
323
324
325
326
327
  {
  	int nr;
  	char *src, *dst;
  	unsigned long phys_dst;
  
  	/* fetch rest bytes in the DMA register */
  	phys_dst = SCSI_DMA_READ_P(dma_addr);
  	nr = phys_dst & 3;
  	if (nr) {
  		/* there are 'nr' bytes left for the last long address
  		   before the DMA pointer */
  		phys_dst ^= nr;
d65e634a8   Finn Thain   scsi/NCR5380: ado...
328
  		dprintk(NDEBUG_DMA, "SCSI DMA: there are %d rest bytes for phys addr 0x%08lx",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
  			   nr, phys_dst);
  		/* The content of the DMA pointer is a physical address!  */
  		dst = phys_to_virt(phys_dst);
d65e634a8   Finn Thain   scsi/NCR5380: ado...
332
333
  		dprintk(NDEBUG_DMA, " = virt addr %p
  ", dst);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
  		for (src = (char *)&tt_scsi_dma.dma_restdata; nr != 0; --nr)
  			*dst++ = *src++;
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  /* This function releases the lock on the DMA chip if there is no
16b29e75a   Finn Thain   atari_scsi: Fix a...
340
   * connected command and the disconnected queue is empty.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
   */
e3c3da673   Finn Thain   atari_NCR5380: Re...
342
  static void falcon_release_lock(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
343
  {
c28bda251   Roman Zippel   m68k: Reformat th...
344
345
  	if (IS_A_TT())
  		return;
e3c3da673   Finn Thain   atari_NCR5380: Re...
346
  	if (stdma_is_locked_by(scsi_falcon_intr))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  		stdma_release();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
351
352
353
  }
  
  /* This function manages the locking of the ST-DMA.
   * If the DMA isn't locked already for SCSI, it tries to lock it by
   * calling stdma_lock(). But if the DMA is locked by the SCSI code and
   * there are other drivers waiting for the chip, we do not issue the
16b29e75a   Finn Thain   atari_scsi: Fix a...
354
   * command immediately but tell the SCSI mid-layer to defer.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
   */
a53a21e46   Finn Thain   atari_NCR5380: Mo...
356
  static int falcon_get_lock(struct Scsi_Host *instance)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  {
c28bda251   Roman Zippel   m68k: Reformat th...
358
  	if (IS_A_TT())
16b29e75a   Finn Thain   atari_scsi: Fix a...
359
  		return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
360

ded155b5e   Finn Thain   atari_scsi: Allow...
361
362
363
  	if (stdma_is_locked_by(scsi_falcon_intr) &&
  	    instance->hostt->can_queue > 1)
  		return 1;
16b29e75a   Finn Thain   atari_scsi: Fix a...
364
  	if (in_interrupt())
a53a21e46   Finn Thain   atari_NCR5380: Mo...
365
  		return stdma_try_lock(scsi_falcon_intr, instance);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366

a53a21e46   Finn Thain   atari_NCR5380: Mo...
367
  	stdma_lock(scsi_falcon_intr, instance);
16b29e75a   Finn Thain   atari_scsi: Fix a...
368
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
  }
7b54e43a8   Geert Uytterhoeven   scsi/atari: Reviv...
370
371
  #ifndef MODULE
  static int __init atari_scsi_setup(char *str)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
372
373
374
  {
  	/* Format of atascsi parameter is:
  	 *   atascsi=<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
3ff228af8   Finn Thain   atari_scsi: Conve...
375
  	 * Defaults depend on TT or Falcon, determined at run time.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
  	 * Negative values mean don't change.
  	 */
9c3f0e2b5   Finn Thain   atari_NCR5380: Re...
378
  	int ints[8];
7b54e43a8   Geert Uytterhoeven   scsi/atari: Reviv...
379
380
  
  	get_options(str, ARRAY_SIZE(ints), ints);
c28bda251   Roman Zippel   m68k: Reformat th...
381

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
382
  	if (ints[0] < 1) {
c28bda251   Roman Zippel   m68k: Reformat th...
383
384
  		printk("atari_scsi_setup: no arguments!
  ");
7b54e43a8   Geert Uytterhoeven   scsi/atari: Reviv...
385
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
  	}
3ff228af8   Finn Thain   atari_scsi: Conve...
387
388
389
390
391
392
393
394
  	if (ints[0] >= 1)
  		setup_can_queue = ints[1];
  	if (ints[0] >= 2)
  		setup_cmd_per_lun = ints[2];
  	if (ints[0] >= 3)
  		setup_sg_tablesize = ints[3];
  	if (ints[0] >= 4)
  		setup_hostid = ints[4];
c4ec6f924   Finn Thain   ncr5380: Remove d...
395
  	/* ints[5] (use_tagged_queuing) is ignored */
9c3f0e2b5   Finn Thain   atari_NCR5380: Re...
396
397
398
  	/* ints[6] (use_pdma) is ignored */
  	if (ints[0] >= 7)
  		setup_toshiba_delay = ints[7];
7b54e43a8   Geert Uytterhoeven   scsi/atari: Reviv...
399
400
  
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
  }
7b54e43a8   Geert Uytterhoeven   scsi/atari: Reviv...
402
403
  __setup("atascsi=", atari_scsi_setup);
  #endif /* !MODULE */
4a98f896b   Finn Thain   scsi: ncr5380: Us...
404
  static unsigned long atari_scsi_dma_setup(struct NCR5380_hostdata *hostdata,
107b5d530   Geert Uytterhoeven   scsi/atari: Make ...
405
406
  					  void *data, unsigned long count,
  					  int dir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
  {
c28bda251   Roman Zippel   m68k: Reformat th...
408
  	unsigned long addr = virt_to_phys(data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409

4a98f896b   Finn Thain   scsi: ncr5380: Us...
410
411
412
  	dprintk(NDEBUG_DMA, "scsi%d: setting up dma, data = %p, phys = %lx, count = %ld, dir = %d
  ",
  	        hostdata->host->host_no, data, addr, count, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
413
414
415
416
417
418
419
420
  
  	if (!IS_A_TT() && !STRAM_ADDR(addr)) {
  		/* If we have a non-DMAable address on a Falcon, use the dribble
  		 * buffer; 'orig_addr' != 0 in the read case tells the interrupt
  		 * handler to copy data from the dribble buffer to the originally
  		 * wanted address.
  		 */
  		if (dir)
c28bda251   Roman Zippel   m68k: Reformat th...
421
  			memcpy(atari_dma_buffer, data, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
423
424
425
  		else
  			atari_dma_orig_addr = data;
  		addr = atari_dma_phys_buffer;
  	}
c28bda251   Roman Zippel   m68k: Reformat th...
426

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
  	atari_dma_startaddr = addr;	/* Needed for calculating residual later. */
c28bda251   Roman Zippel   m68k: Reformat th...
428

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
429
430
431
432
433
  	/* Cache cleanup stuff: On writes, push any dirty cache out before sending
  	 * it to the peripheral. (Must be done before DMA setup, since at least
  	 * the ST-DMA begins to fill internal buffers right after setup. For
  	 * reads, invalidate any cache, may be altered after DMA without CPU
  	 * knowledge.
c28bda251   Roman Zippel   m68k: Reformat th...
434
  	 *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
437
  	 * ++roman: For the Medusa, there's no need at all for that cache stuff,
  	 * because the hardware does bus snooping (fine!).
  	 */
c28bda251   Roman Zippel   m68k: Reformat th...
438
  	dma_cache_maintenance(addr, count, dir);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
441
  	if (IS_A_TT()) {
  		tt_scsi_dma.dma_ctrl = dir;
c28bda251   Roman Zippel   m68k: Reformat th...
442
443
  		SCSI_DMA_WRITE_P(dma_addr, addr);
  		SCSI_DMA_WRITE_P(dma_cnt, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  		tt_scsi_dma.dma_ctrl = dir | 2;
c28bda251   Roman Zippel   m68k: Reformat th...
445
  	} else { /* ! IS_A_TT */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446
  		/* set address */
c28bda251   Roman Zippel   m68k: Reformat th...
447
  		SCSI_DMA_SETADR(addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
  
  		/* toggle direction bit to clear FIFO and set DMA direction */
  		dir <<= 8;
  		st_dma.dma_mode_status = 0x90 | dir;
  		st_dma.dma_mode_status = 0x90 | (dir ^ 0x100);
  		st_dma.dma_mode_status = 0x90 | dir;
  		udelay(40);
  		/* On writes, round up the transfer length to the next multiple of 512
  		 * (see also comment at atari_dma_xfer_len()). */
  		st_dma.fdc_acces_seccount = (count + (dir ? 511 : 0)) >> 9;
  		udelay(40);
  		st_dma.dma_mode_status = 0x10 | dir;
  		udelay(40);
  		/* need not restore value of dir, only boolean value is tested */
  		atari_dma_active = 1;
  	}
c28bda251   Roman Zippel   m68k: Reformat th...
464
  	return count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
  }
4a98f896b   Finn Thain   scsi: ncr5380: Us...
466
467
468
469
470
471
472
473
474
475
476
  static inline int atari_scsi_dma_recv_setup(struct NCR5380_hostdata *hostdata,
                                              unsigned char *data, int count)
  {
  	return atari_scsi_dma_setup(hostdata, data, count, 0);
  }
  
  static inline int atari_scsi_dma_send_setup(struct NCR5380_hostdata *hostdata,
                                              unsigned char *data, int count)
  {
  	return atari_scsi_dma_setup(hostdata, data, count, 1);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477

4a98f896b   Finn Thain   scsi: ncr5380: Us...
478
  static int atari_scsi_dma_residual(struct NCR5380_hostdata *hostdata)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
  {
c28bda251   Roman Zippel   m68k: Reformat th...
480
  	return atari_dma_residual;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
481
482
483
484
485
486
  }
  
  
  #define	CMD_SURELY_BLOCK_MODE	0
  #define	CMD_SURELY_BYTE_MODE	1
  #define	CMD_MODE_UNKNOWN		2
710ddd0d5   Finn Thain   ncr5380: Drop leg...
487
  static int falcon_classify_cmd(struct scsi_cmnd *cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
489
  {
  	unsigned char opcode = cmd->cmnd[0];
c28bda251   Roman Zippel   m68k: Reformat th...
490

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
  	if (opcode == READ_DEFECT_DATA || opcode == READ_LONG ||
c28bda251   Roman Zippel   m68k: Reformat th...
492
493
  	    opcode == READ_BUFFER)
  		return CMD_SURELY_BYTE_MODE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494
495
496
497
498
499
500
  	else if (opcode == READ_6 || opcode == READ_10 ||
  		 opcode == 0xa8 /* READ_12 */ || opcode == READ_REVERSE ||
  		 opcode == RECOVER_BUFFERED_DATA) {
  		/* In case of a sequential-access target (tape), special care is
  		 * needed here: The transfer is block-mode only if the 'fixed' bit is
  		 * set! */
  		if (cmd->device->type == TYPE_TAPE && !(cmd->cmnd[1] & 1))
c28bda251   Roman Zippel   m68k: Reformat th...
501
  			return CMD_SURELY_BYTE_MODE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
  		else
c28bda251   Roman Zippel   m68k: Reformat th...
503
504
505
  			return CMD_SURELY_BLOCK_MODE;
  	} else
  		return CMD_MODE_UNKNOWN;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
506
507
508
509
510
511
512
513
514
515
516
  }
  
  
  /* This function calculates the number of bytes that can be transferred via
   * DMA. On the TT, this is arbitrary, but on the Falcon we have to use the
   * ST-DMA chip. There are only multiples of 512 bytes possible and max.
   * 255*512 bytes :-( This means also, that defining READ_OVERRUNS is not
   * possible on the Falcon, since that would require to program the DMA for
   * n*512 - atari_read_overrun bytes. But it seems that the Falcon doesn't have
   * the overrun problem, so this question is academic :-)
   */
4a98f896b   Finn Thain   scsi: ncr5380: Us...
517
518
  static int atari_scsi_dma_xfer_len(struct NCR5380_hostdata *hostdata,
                                     struct scsi_cmnd *cmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
  {
4a98f896b   Finn Thain   scsi: ncr5380: Us...
520
521
  	int wanted_len = cmd->SCp.this_residual;
  	int possible_len, limit;
29c8a2467   Adrian Bunk   m68k: Remove the ...
522

e63449c43   Finn Thain   atari_NCR5380: Re...
523
524
  	if (wanted_len < DMA_MIN_SIZE)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525
526
  	if (IS_A_TT())
  		/* TT SCSI DMA can transfer arbitrary #bytes */
c28bda251   Roman Zippel   m68k: Reformat th...
527
  		return wanted_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
  
  	/* ST DMA chip is stupid -- only multiples of 512 bytes! (and max.
  	 * 255*512 bytes, but this should be enough)
  	 *
  	 * ++roman: Aaargl! Another Falcon-SCSI problem... There are some commands
  	 * that return a number of bytes which cannot be known beforehand. In this
  	 * case, the given transfer length is an "allocation length". Now it
  	 * can happen that this allocation length is a multiple of 512 bytes and
  	 * the DMA is used. But if not n*512 bytes really arrive, some input data
  	 * will be lost in the ST-DMA's FIFO :-( Thus, we have to distinguish
  	 * between commands that do block transfers and those that do byte
  	 * transfers. But this isn't easy... there are lots of vendor specific
  	 * commands, and the user can issue any command via the
  	 * SCSI_IOCTL_SEND_COMMAND.
  	 *
  	 * The solution: We classify SCSI commands in 1) surely block-mode cmd.s,
  	 * 2) surely byte-mode cmd.s and 3) cmd.s with unknown mode. In case 1)
  	 * and 3), the thing to do is obvious: allow any number of blocks via DMA
  	 * or none. In case 2), we apply some heuristic: Byte mode is assumed if
  	 * the transfer (allocation) length is < 1024, hoping that no cmd. not
  	 * explicitly known as byte mode have such big allocation lengths...
  	 * BTW, all the discussion above applies only to reads. DMA writes are
  	 * unproblematic anyways, since the targets aborts the transfer after
  	 * receiving a sufficient number of bytes.
  	 *
  	 * Another point: If the transfer is from/to an non-ST-RAM address, we
  	 * use the dribble buffer and thus can do only STRAM_BUFFER_SIZE bytes.
  	 */
4a98f896b   Finn Thain   scsi: ncr5380: Us...
556
  	if (cmd->sc_data_direction == DMA_TO_DEVICE) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
560
561
  		/* Write operation can always use the DMA, but the transfer size must
  		 * be rounded up to the next multiple of 512 (atari_dma_setup() does
  		 * this).
  		 */
  		possible_len = wanted_len;
c28bda251   Roman Zippel   m68k: Reformat th...
562
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
564
565
566
567
568
569
570
571
  		/* Read operations: if the wanted transfer length is not a multiple of
  		 * 512, we cannot use DMA, since the ST-DMA cannot split transfers
  		 * (no interrupt on DMA finished!)
  		 */
  		if (wanted_len & 0x1ff)
  			possible_len = 0;
  		else {
  			/* Now classify the command (see above) and decide whether it is
  			 * allowed to do DMA at all */
c28bda251   Roman Zippel   m68k: Reformat th...
572
573
  			switch (falcon_classify_cmd(cmd)) {
  			case CMD_SURELY_BLOCK_MODE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
574
575
  				possible_len = wanted_len;
  				break;
c28bda251   Roman Zippel   m68k: Reformat th...
576
  			case CMD_SURELY_BYTE_MODE:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
578
  				possible_len = 0; /* DMA prohibited */
  				break;
c28bda251   Roman Zippel   m68k: Reformat th...
579
580
  			case CMD_MODE_UNKNOWN:
  			default:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
582
583
584
585
586
587
  				/* For unknown commands assume block transfers if the transfer
  				 * size/allocation length is >= 1024 */
  				possible_len = (wanted_len < 1024) ? 0 : wanted_len;
  				break;
  			}
  		}
  	}
c28bda251   Roman Zippel   m68k: Reformat th...
588

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
  	/* Last step: apply the hard limit on DMA transfers */
c28bda251   Roman Zippel   m68k: Reformat th...
590
  	limit = (atari_dma_buffer && !STRAM_ADDR(virt_to_phys(cmd->SCp.ptr))) ?
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
593
594
595
  		    STRAM_BUFFER_SIZE : 255*512;
  	if (possible_len > limit)
  		possible_len = limit;
  
  	if (possible_len != wanted_len)
4a98f896b   Finn Thain   scsi: ncr5380: Us...
596
597
598
  		dprintk(NDEBUG_DMA, "DMA transfer now %d bytes instead of %d
  ",
  		        possible_len, wanted_len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599

c28bda251   Roman Zippel   m68k: Reformat th...
600
  	return possible_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
602
603
604
605
606
607
  /* NCR5380 register access functions
   *
   * There are separate functions for TT and Falcon, because the access
   * methods are quite different. The calling macros NCR5380_read and
   * NCR5380_write call these functions via function pointers.
   */
61e1ce588   Finn Thain   scsi: ncr5380: Us...
608
  static u8 atari_scsi_tt_reg_read(unsigned int reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
  {
c28bda251   Roman Zippel   m68k: Reformat th...
610
  	return tt_scsi_regp[reg * 2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
611
  }
61e1ce588   Finn Thain   scsi: ncr5380: Us...
612
  static void atari_scsi_tt_reg_write(unsigned int reg, u8 value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
613
614
615
  {
  	tt_scsi_regp[reg * 2] = value;
  }
61e1ce588   Finn Thain   scsi: ncr5380: Us...
616
  static u8 atari_scsi_falcon_reg_read(unsigned int reg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
617
  {
abd12b092   Finn Thain   scsi: atari_scsi:...
618
  	unsigned long flags;
61e1ce588   Finn Thain   scsi: ncr5380: Us...
619
  	u8 result;
abd12b092   Finn Thain   scsi: atari_scsi:...
620
621
622
623
  
  	reg += 0x88;
  	local_irq_save(flags);
  	dma_wd.dma_mode_status = (u_short)reg;
61e1ce588   Finn Thain   scsi: ncr5380: Us...
624
  	result = (u8)dma_wd.fdc_acces_seccount;
abd12b092   Finn Thain   scsi: atari_scsi:...
625
626
  	local_irq_restore(flags);
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  }
61e1ce588   Finn Thain   scsi: ncr5380: Us...
628
  static void atari_scsi_falcon_reg_write(unsigned int reg, u8 value)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
  {
abd12b092   Finn Thain   scsi: atari_scsi:...
630
631
632
633
634
  	unsigned long flags;
  
  	reg += 0x88;
  	local_irq_save(flags);
  	dma_wd.dma_mode_status = (u_short)reg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
635
  	dma_wd.fdc_acces_seccount = (u_short)value;
abd12b092   Finn Thain   scsi: atari_scsi:...
636
  	local_irq_restore(flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
  }
52d3e561c   Finn Thain   atari_scsi: Adopt...
638
  #include "NCR5380.c"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639

12e5fc665   Hannes Reinecke   scsi: NCR5380: Mo...
640
  static int atari_scsi_host_reset(struct scsi_cmnd *cmd)
4d3d2a54f   Finn Thain   ncr5380: Remove m...
641
642
  {
  	int rv;
e3c3da673   Finn Thain   atari_NCR5380: Re...
643
644
645
  	unsigned long flags;
  
  	local_irq_save(flags);
4d3d2a54f   Finn Thain   ncr5380: Remove m...
646

e3c3da673   Finn Thain   atari_NCR5380: Re...
647
648
  	/* Abort a maybe active DMA transfer */
  	if (IS_A_TT()) {
4d3d2a54f   Finn Thain   ncr5380: Remove m...
649
  		tt_scsi_dma.dma_ctrl = 0;
4d3d2a54f   Finn Thain   ncr5380: Remove m...
650
  	} else {
546a4d181   Finn Thain   scsi: atari_scsi:...
651
652
  		if (stdma_is_locked_by(scsi_falcon_intr))
  			st_dma.dma_mode_status = 0x90;
4d3d2a54f   Finn Thain   ncr5380: Remove m...
653
654
  		atari_dma_active = 0;
  		atari_dma_orig_addr = NULL;
4d3d2a54f   Finn Thain   ncr5380: Remove m...
655
  	}
12e5fc665   Hannes Reinecke   scsi: NCR5380: Mo...
656
  	rv = NCR5380_host_reset(cmd);
4d3d2a54f   Finn Thain   ncr5380: Remove m...
657

e3c3da673   Finn Thain   atari_NCR5380: Re...
658
659
660
661
662
  	/* The 5380 raises its IRQ line while _RST is active but the ST DMA
  	 * "lock" has been released so this interrupt may end up handled by
  	 * floppy or IDE driver (if one of them holds the lock). The NCR5380
  	 * interrupt flag has been cleared already.
  	 */
4d3d2a54f   Finn Thain   ncr5380: Remove m...
663

e3c3da673   Finn Thain   atari_NCR5380: Re...
664
  	local_irq_restore(flags);
4d3d2a54f   Finn Thain   ncr5380: Remove m...
665
666
667
  
  	return rv;
  }
3ff228af8   Finn Thain   atari_scsi: Conve...
668
669
670
671
672
673
  #define DRV_MODULE_NAME         "atari_scsi"
  #define PFX                     DRV_MODULE_NAME ": "
  
  static struct scsi_host_template atari_scsi_template = {
  	.module			= THIS_MODULE,
  	.proc_name		= DRV_MODULE_NAME,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
674
  	.name			= "Atari native SCSI",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675
676
677
  	.info			= atari_scsi_info,
  	.queuecommand		= atari_scsi_queue_command,
  	.eh_abort_handler	= atari_scsi_abort,
12e5fc665   Hannes Reinecke   scsi: NCR5380: Mo...
678
  	.eh_host_reset_handler	= atari_scsi_host_reset,
3ff228af8   Finn Thain   atari_scsi: Conve...
679
  	.this_id		= 7,
a5217a863   Finn Thain   atari_scsi: Set a...
680
  	.cmd_per_lun		= 2,
4af14d113   Christoph Hellwig   scsi: remove the ...
681
  	.dma_boundary		= PAGE_SIZE - 1,
32b26a104   Finn Thain   ncr5380: Use stan...
682
  	.cmd_size		= NCR5380_CMD_SIZE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683
  };
3ff228af8   Finn Thain   atari_scsi: Conve...
684
685
686
687
688
  static int __init atari_scsi_probe(struct platform_device *pdev)
  {
  	struct Scsi_Host *instance;
  	int error;
  	struct resource *irq;
ef1081cbf   Finn Thain   atari_NCR5380: Re...
689
  	int host_flags = 0;
3ff228af8   Finn Thain   atari_scsi: Conve...
690
691
692
693
694
695
696
697
698
699
700
701
  
  	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  	if (!irq)
  		return -ENODEV;
  
  	if (ATARIHW_PRESENT(TT_SCSI)) {
  		atari_scsi_reg_read  = atari_scsi_tt_reg_read;
  		atari_scsi_reg_write = atari_scsi_tt_reg_write;
  	} else {
  		atari_scsi_reg_read  = atari_scsi_falcon_reg_read;
  		atari_scsi_reg_write = atari_scsi_falcon_reg_write;
  	}
3ff228af8   Finn Thain   atari_scsi: Conve...
702
703
  	if (ATARIHW_PRESENT(TT_SCSI)) {
  		atari_scsi_template.can_queue    = 16;
3ff228af8   Finn Thain   atari_scsi: Conve...
704
705
  		atari_scsi_template.sg_tablesize = SG_ALL;
  	} else {
ded155b5e   Finn Thain   atari_scsi: Allow...
706
  		atari_scsi_template.can_queue    = 1;
79172ab20   Finn Thain   scsi: atari_scsi:...
707
  		atari_scsi_template.sg_tablesize = 1;
3ff228af8   Finn Thain   atari_scsi: Conve...
708
709
710
711
712
713
714
  	}
  
  	if (setup_can_queue > 0)
  		atari_scsi_template.can_queue = setup_can_queue;
  
  	if (setup_cmd_per_lun > 0)
  		atari_scsi_template.cmd_per_lun = setup_cmd_per_lun;
79172ab20   Finn Thain   scsi: atari_scsi:...
715
716
  	/* Don't increase sg_tablesize on Falcon! */
  	if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize > 0)
3ff228af8   Finn Thain   atari_scsi: Conve...
717
718
719
720
  		atari_scsi_template.sg_tablesize = setup_sg_tablesize;
  
  	if (setup_hostid >= 0) {
  		atari_scsi_template.this_id = setup_hostid & 7;
83d2aed44   Finn Thain   scsi/atari_scsi: ...
721
  	} else if (IS_REACHABLE(CONFIG_NVRAM)) {
3ff228af8   Finn Thain   atari_scsi: Conve...
722
  		/* Test if a host id is set in the NVRam */
1278cf66c   Finn Thain   nvram: Replace nv...
723
724
725
726
  		if (ATARIHW_PRESENT(TT_CLK)) {
  			unsigned char b;
  			loff_t offset = 16;
  			ssize_t count = nvram_read(&b, 1, &offset);
3ff228af8   Finn Thain   atari_scsi: Conve...
727
728
729
730
  
  			/* Arbitration enabled? (for TOS)
  			 * If yes, use configured host ID
  			 */
1278cf66c   Finn Thain   nvram: Replace nv...
731
  			if ((count == 1) && (b & 0x80))
3ff228af8   Finn Thain   atari_scsi: Conve...
732
733
734
  				atari_scsi_template.this_id = b & 7;
  		}
  	}
3ff228af8   Finn Thain   atari_scsi: Conve...
735
736
737
738
739
740
  	/* If running on a Falcon and if there's TT-Ram (i.e., more than one
  	 * memory block, since there's always ST-Ram in a Falcon), then
  	 * allocate a STRAM_BUFFER_SIZE byte dribble buffer for transfers
  	 * from/to alternative Ram.
  	 */
  	if (ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(EXTD_DMA) &&
6ff8a3b2a   Michael Schmitz   scsi: atari_scsi:...
741
  	    m68k_realnum_memory > 1) {
3ff228af8   Finn Thain   atari_scsi: Conve...
742
743
744
745
746
747
748
  		atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI");
  		if (!atari_dma_buffer) {
  			pr_err(PFX "can't allocate ST-RAM double buffer
  ");
  			return -ENOMEM;
  		}
  		atari_dma_phys_buffer = atari_stram_to_phys(atari_dma_buffer);
4ab2a7878   Finn Thain   scsi: ncr5380: Re...
749
  		atari_dma_orig_addr = NULL;
3ff228af8   Finn Thain   atari_scsi: Conve...
750
  	}
3ff228af8   Finn Thain   atari_scsi: Conve...
751
752
753
754
755
756
757
  
  	instance = scsi_host_alloc(&atari_scsi_template,
  	                           sizeof(struct NCR5380_hostdata));
  	if (!instance) {
  		error = -ENOMEM;
  		goto fail_alloc;
  	}
3ff228af8   Finn Thain   atari_scsi: Conve...
758

3ff228af8   Finn Thain   atari_scsi: Conve...
759
  	instance->irq = irq->start;
ef1081cbf   Finn Thain   atari_NCR5380: Re...
760
  	host_flags |= IS_A_TT() ? 0 : FLAG_LATE_DMA_SETUP;
9c3f0e2b5   Finn Thain   atari_NCR5380: Re...
761
  	host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0;
ca513fc94   Finn Thain   atari_NCR5380: In...
762

0ad0eff98   Finn Thain   ncr5380: Introduc...
763
764
765
  	error = NCR5380_init(instance, host_flags);
  	if (error)
  		goto fail_init;
3ff228af8   Finn Thain   atari_scsi: Conve...
766
767
768
769
770
771
772
773
774
775
776
  
  	if (IS_A_TT()) {
  		error = request_irq(instance->irq, scsi_tt_intr, 0,
  		                    "NCR5380", instance);
  		if (error) {
  			pr_err(PFX "request irq %d failed, aborting
  ",
  			       instance->irq);
  			goto fail_irq;
  		}
  		tt_mfp.active_edge |= 0x80;	/* SCSI int on L->H */
e4dec6806   Finn Thain   ncr5380: Remove R...
777

3ff228af8   Finn Thain   atari_scsi: Conve...
778
779
780
781
782
783
784
785
786
787
788
  		tt_scsi_dma.dma_ctrl = 0;
  		atari_dma_residual = 0;
  
  		/* While the read overruns (described by Drew Eckhardt in
  		 * NCR5380.c) never happened on TTs, they do in fact on the
  		 * Medusa (This was the cause why SCSI didn't work right for
  		 * so long there.) Since handling the overruns slows down
  		 * a bit, I turned the #ifdef's into a runtime condition.
  		 *
  		 * In principle it should be sufficient to do max. 1 byte with
  		 * PIO, but there is another problem on the Medusa with the DMA
ef1081cbf   Finn Thain   atari_NCR5380: Re...
789
  		 * rest data register. So read_overruns is currently set
3ff228af8   Finn Thain   atari_scsi: Conve...
790
791
792
  		 * to 4 to avoid having transfers that aren't a multiple of 4.
  		 * If the rest data bug is fixed, this can be lowered to 1.
  		 */
ef1081cbf   Finn Thain   atari_NCR5380: Re...
793
794
795
796
797
798
  		if (MACH_IS_MEDUSA) {
  			struct NCR5380_hostdata *hostdata =
  				shost_priv(instance);
  
  			hostdata->read_overruns = 4;
  		}
3ff228af8   Finn Thain   atari_scsi: Conve...
799
800
801
802
  	} else {
  		/* Nothing to do for the interrupt: the ST-DMA is initialized
  		 * already.
  		 */
3ff228af8   Finn Thain   atari_scsi: Conve...
803
804
805
806
  		atari_dma_residual = 0;
  		atari_dma_active = 0;
  		atari_dma_stram_mask = (ATARIHW_PRESENT(EXTD_DMA) ? 0x00000000
  					: 0xff000000);
3ff228af8   Finn Thain   atari_scsi: Conve...
807
  	}
9c3f0e2b5   Finn Thain   atari_NCR5380: Re...
808
  	NCR5380_maybe_reset_bus(instance);
3ff228af8   Finn Thain   atari_scsi: Conve...
809
810
811
812
813
814
815
816
817
818
819
820
821
822
  	error = scsi_add_host(instance, NULL);
  	if (error)
  		goto fail_host;
  
  	platform_set_drvdata(pdev, instance);
  
  	scsi_scan_host(instance);
  	return 0;
  
  fail_host:
  	if (IS_A_TT())
  		free_irq(instance->irq, instance);
  fail_irq:
  	NCR5380_exit(instance);
0ad0eff98   Finn Thain   ncr5380: Introduc...
823
  fail_init:
3ff228af8   Finn Thain   atari_scsi: Conve...
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
  	scsi_host_put(instance);
  fail_alloc:
  	if (atari_dma_buffer)
  		atari_stram_free(atari_dma_buffer);
  	return error;
  }
  
  static int __exit atari_scsi_remove(struct platform_device *pdev)
  {
  	struct Scsi_Host *instance = platform_get_drvdata(pdev);
  
  	scsi_remove_host(instance);
  	if (IS_A_TT())
  		free_irq(instance->irq, instance);
  	NCR5380_exit(instance);
  	scsi_host_put(instance);
  	if (atari_dma_buffer)
  		atari_stram_free(atari_dma_buffer);
  	return 0;
  }
  
  static struct platform_driver atari_scsi_driver = {
  	.remove = __exit_p(atari_scsi_remove),
  	.driver = {
  		.name	= DRV_MODULE_NAME,
3ff228af8   Finn Thain   atari_scsi: Conve...
849
850
  	},
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
851

3ff228af8   Finn Thain   atari_scsi: Conve...
852
  module_platform_driver_probe(atari_scsi_driver, atari_scsi_probe);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
853

3ff228af8   Finn Thain   atari_scsi: Conve...
854
  MODULE_ALIAS("platform:" DRV_MODULE_NAME);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
855
  MODULE_LICENSE("GPL");