blob: 985a6b36756e7d89699a18193c437a82870e8e80 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl)
3 *
4 * Sun3 DMA routines added by Sam Creasey (sammy@sammy.net)
5 *
Finn Thain757f5ba2014-03-18 11:42:24 +11006 * VME support added by Sam Creasey
7 *
8 * TODO: modify this driver to support multiple Sun3 SCSI VME boards
9 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 * Adapted from mac_scsinew.c:
11 */
12/*
13 * Generic Macintosh NCR5380 driver
14 *
15 * Copyright 1998, Michael Schmitz <mschmitz@lbl.gov>
16 *
17 * derived in part from:
18 */
19/*
20 * Generic Generic NCR5380 driver
21 *
22 * Copyright 1995, Russell King
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 */
24
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/types.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/ioport.h>
29#include <linux/init.h>
30#include <linux/blkdev.h>
Finn Thain0d31f872014-11-13 12:21:28 +110031#include <linux/platform_device.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032
33#include <asm/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <asm/dvma.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <scsi/scsi_host.h>
37#include "sun3_scsi.h"
Finn Thain2231ef82014-11-12 16:12:12 +110038
39/* Definitions for the core NCR5380 driver. */
40
41#define REAL_DMA
42#define RESET_RUN_DONE
43/* #define SUPPORT_TAGS */
Finn Thain8dad0c52014-11-12 16:12:17 +110044/* minimum number of bytes to do dma on */
45#define DMA_MIN_SIZE 129
Finn Thain2231ef82014-11-12 16:12:12 +110046
47/* #define MAX_TAGS 32 */
48
49#define NCR5380_implementation_fields /* none */
50
51#define NCR5380_read(reg) sun3scsi_read(reg)
52#define NCR5380_write(reg, value) sun3scsi_write(reg, value)
53
54#define NCR5380_queue_command sun3scsi_queue_command
55#define NCR5380_bus_reset sun3scsi_bus_reset
56#define NCR5380_abort sun3scsi_abort
57#define NCR5380_show_info sun3scsi_show_info
58#define NCR5380_info sun3scsi_info
59
60#define NCR5380_dma_read_setup(instance, data, count) \
61 sun3scsi_dma_setup(data, count, 0)
62#define NCR5380_dma_write_setup(instance, data, count) \
63 sun3scsi_dma_setup(data, count, 1)
64#define NCR5380_dma_residual(instance) \
65 sun3scsi_dma_residual(instance)
66#define NCR5380_dma_xfer_len(instance, cmd, phase) \
67 sun3scsi_dma_xfer_len(cmd->SCp.this_residual, cmd, !((phase) & SR_IO))
68
Finn Thain8dad0c52014-11-12 16:12:17 +110069#define NCR5380_acquire_dma_irq(instance) (1)
70#define NCR5380_release_dma_irq(instance)
71
Finn Thain9f6620a2014-03-18 11:42:23 +110072#include "NCR5380.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070073
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Finn Thain2231ef82014-11-12 16:12:12 +110075extern int sun3_map_test(unsigned long, char *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070076
Linus Torvalds1da177e2005-04-16 15:20:36 -070077static int setup_can_queue = -1;
78module_param(setup_can_queue, int, 0);
79static int setup_cmd_per_lun = -1;
80module_param(setup_cmd_per_lun, int, 0);
81static int setup_sg_tablesize = -1;
82module_param(setup_sg_tablesize, int, 0);
83#ifdef SUPPORT_TAGS
84static int setup_use_tagged_queuing = -1;
85module_param(setup_use_tagged_queuing, int, 0);
86#endif
87static int setup_hostid = -1;
88module_param(setup_hostid, int, 0);
89
Finn Thain2231ef82014-11-12 16:12:12 +110090/* #define RESET_BOOT */
Michael Schmitz2b0f8342014-05-02 20:43:01 +120091
Linus Torvalds1da177e2005-04-16 15:20:36 -070092#define AFTER_RESET_DELAY (HZ/2)
93
94/* ms to wait after hitting dma regs */
95#define SUN3_DMA_DELAY 10
96
97/* dvma buffer to allocate -- 32k should hopefully be more than sufficient */
98#define SUN3_DVMA_BUFSIZE 0xe000
99
Finn Thain2231ef82014-11-12 16:12:12 +1100100static struct scsi_cmnd *sun3_dma_setup_done;
Finn Thain0d31f872014-11-13 12:21:28 +1100101static unsigned char *sun3_scsi_regp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102static volatile struct sun3_dma_regs *dregs;
Finn Thain0d31f872014-11-13 12:21:28 +1100103static struct sun3_udc_regs *udc_regs;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104static unsigned char *sun3_dma_orig_addr = NULL;
105static unsigned long sun3_dma_orig_count = 0;
106static int sun3_dma_active = 0;
107static unsigned long last_residual = 0;
Finn Thain0d31f872014-11-13 12:21:28 +1100108static struct Scsi_Host *default_instance;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109
110/*
111 * NCR 5380 register access functions
112 */
113
114static inline unsigned char sun3scsi_read(int reg)
115{
Finn Thain0d31f872014-11-13 12:21:28 +1100116 return in_8(sun3_scsi_regp + reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117}
118
119static inline void sun3scsi_write(int reg, int value)
120{
Finn Thain0d31f872014-11-13 12:21:28 +1100121 out_8(sun3_scsi_regp + reg, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122}
123
Finn Thain757f5ba2014-03-18 11:42:24 +1100124#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125/* dma controller register access functions */
126
127static inline unsigned short sun3_udc_read(unsigned char reg)
128{
129 unsigned short ret;
130
131 dregs->udc_addr = UDC_CSR;
132 udelay(SUN3_DMA_DELAY);
133 ret = dregs->udc_data;
134 udelay(SUN3_DMA_DELAY);
135
136 return ret;
137}
138
139static inline void sun3_udc_write(unsigned short val, unsigned char reg)
140{
141 dregs->udc_addr = reg;
142 udelay(SUN3_DMA_DELAY);
143 dregs->udc_data = val;
144 udelay(SUN3_DMA_DELAY);
145}
Finn Thain757f5ba2014-03-18 11:42:24 +1100146#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148#ifdef RESET_BOOT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
150{
151 unsigned long end;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152
153 /*
154 * Do a SCSI reset to clean up the bus during initialization. No
155 * messing with the queues, interrupts, or locks necessary here.
156 */
157
158 printk( "Sun3 SCSI: resetting the SCSI bus..." );
159
160 /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
161// sun3_disable_irq( IRQ_SUN3_SCSI );
162
163 /* get in phase */
164 NCR5380_write( TARGET_COMMAND_REG,
165 PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
166
167 /* assert RST */
168 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
169
170 /* The min. reset hold time is 25us, so 40us should be enough */
171 udelay( 50 );
172
173 /* reset RST and interrupt */
174 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
175 NCR5380_read( RESET_PARITY_INTERRUPT_REG );
176
177 for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
178 barrier();
179
180 /* switch on SCSI IRQ again */
181// sun3_enable_irq( IRQ_SUN3_SCSI );
182
183 printk( " done\n" );
184}
185#endif
186
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187// safe bits for the CSR
188#define CSR_GOOD 0x060f
189
David Howells7d12e782006-10-05 14:55:46 +0100190static irqreturn_t scsi_sun3_intr(int irq, void *dummy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191{
192 unsigned short csr = dregs->csr;
193 int handled = 0;
194
Finn Thain757f5ba2014-03-18 11:42:24 +1100195#ifdef SUN3_SCSI_VME
196 dregs->csr &= ~CSR_DMA_ENABLE;
197#endif
198
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 if(csr & ~CSR_GOOD) {
200 if(csr & CSR_DMA_BUSERR) {
201 printk("scsi%d: bus error in dma\n", default_instance->host_no);
202 }
203
204 if(csr & CSR_DMA_CONFLICT) {
205 printk("scsi%d: dma conflict\n", default_instance->host_no);
206 }
207 handled = 1;
208 }
209
210 if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
David Howells7d12e782006-10-05 14:55:46 +0100211 NCR5380_intr(irq, dummy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212 handled = 1;
213 }
214
215 return IRQ_RETVAL(handled);
216}
217
218/*
219 * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk;
220 * reentering NCR5380_print_status seems to have ugly side effects
221 */
222
223/* this doesn't seem to get used at all -- sam */
224#if 0
225void sun3_sun3_debug (void)
226{
227 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
229 if (default_instance) {
230 local_irq_save(flags);
231 NCR5380_print_status(default_instance);
232 local_irq_restore(flags);
233 }
234}
235#endif
236
237
238/* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */
239static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag)
240{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 void *addr;
242
243 if(sun3_dma_orig_addr != NULL)
244 dvma_unmap(sun3_dma_orig_addr);
245
Finn Thain757f5ba2014-03-18 11:42:24 +1100246#ifdef SUN3_SCSI_VME
247 addr = (void *)dvma_map_vme((unsigned long) data, count);
248#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 addr = (void *)dvma_map((unsigned long) data, count);
Finn Thain757f5ba2014-03-18 11:42:24 +1100250#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
252 sun3_dma_orig_addr = addr;
253 sun3_dma_orig_count = count;
Finn Thain757f5ba2014-03-18 11:42:24 +1100254
255#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 dregs->fifo_count = 0;
257 sun3_udc_write(UDC_RESET, UDC_CSR);
258
259 /* reset fifo */
260 dregs->csr &= ~CSR_FIFO;
261 dregs->csr |= CSR_FIFO;
Finn Thain757f5ba2014-03-18 11:42:24 +1100262#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
264 /* set direction */
265 if(write_flag)
266 dregs->csr |= CSR_SEND;
267 else
268 dregs->csr &= ~CSR_SEND;
269
Finn Thain757f5ba2014-03-18 11:42:24 +1100270#ifdef SUN3_SCSI_VME
271 dregs->csr |= CSR_PACK_ENABLE;
272
273 dregs->dma_addr_hi = ((unsigned long)addr >> 16);
274 dregs->dma_addr_lo = ((unsigned long)addr & 0xffff);
275
276 dregs->dma_count_hi = 0;
277 dregs->dma_count_lo = 0;
278 dregs->fifo_count_hi = 0;
279 dregs->fifo_count = 0;
280#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 /* byte count for fifo */
282 dregs->fifo_count = count;
283
284 sun3_udc_write(UDC_RESET, UDC_CSR);
285
286 /* reset fifo */
287 dregs->csr &= ~CSR_FIFO;
288 dregs->csr |= CSR_FIFO;
289
290 if(dregs->fifo_count != count) {
291 printk("scsi%d: fifo_mismatch %04x not %04x\n",
292 default_instance->host_no, dregs->fifo_count,
293 (unsigned int) count);
Finn Thaind614f062014-03-18 11:42:16 +1100294 NCR5380_dprint(NDEBUG_DMA, default_instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 }
296
297 /* setup udc */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8);
299 udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 udc_regs->count = count/2; /* count in words */
301 udc_regs->mode_hi = UDC_MODE_HIWORD;
302 if(write_flag) {
303 if(count & 1)
304 udc_regs->count++;
305 udc_regs->mode_lo = UDC_MODE_LSEND;
306 udc_regs->rsel = UDC_RSEL_SEND;
307 } else {
308 udc_regs->mode_lo = UDC_MODE_LRECV;
309 udc_regs->rsel = UDC_RSEL_RECV;
310 }
311
312 /* announce location of regs block */
313 sun3_udc_write(((dvma_vtob(udc_regs) & 0xff0000) >> 8),
314 UDC_CHN_HI);
315
316 sun3_udc_write((dvma_vtob(udc_regs) & 0xffff), UDC_CHN_LO);
317
318 /* set dma master on */
319 sun3_udc_write(0xd, UDC_MODE);
320
321 /* interrupt enable */
322 sun3_udc_write(UDC_INT_ENABLE, UDC_CSR);
Finn Thain757f5ba2014-03-18 11:42:24 +1100323#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
325 return count;
326
327}
328
Finn Thain757f5ba2014-03-18 11:42:24 +1100329#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance)
331{
332 unsigned short resid;
333
334 dregs->udc_addr = 0x32;
335 udelay(SUN3_DMA_DELAY);
336 resid = dregs->udc_data;
337 udelay(SUN3_DMA_DELAY);
338 resid *= 2;
339
340 return (unsigned long) resid;
341}
Finn Thain757f5ba2014-03-18 11:42:24 +1100342#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343
344static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance)
345{
346 return last_residual;
347}
348
Henne811c9362006-10-03 19:51:59 +0200349static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted,
350 struct scsi_cmnd *cmd,
351 int write_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352{
Christoph Hellwig33659eb2010-08-07 18:17:56 +0200353 if (cmd->request->cmd_type == REQ_TYPE_FS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 return wanted;
355 else
356 return 0;
357}
358
359static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data)
360{
Finn Thain757f5ba2014-03-18 11:42:24 +1100361#ifdef SUN3_SCSI_VME
362 unsigned short csr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Finn Thain757f5ba2014-03-18 11:42:24 +1100364 csr = dregs->csr;
365
366 dregs->dma_count_hi = (sun3_dma_orig_count >> 16);
367 dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff);
368
369 dregs->fifo_count_hi = (sun3_dma_orig_count >> 16);
370 dregs->fifo_count = (sun3_dma_orig_count & 0xffff);
371
372/* if(!(csr & CSR_DMA_ENABLE))
373 * dregs->csr |= CSR_DMA_ENABLE;
374 */
375#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 sun3_udc_write(UDC_CHN_START, UDC_CSR);
Finn Thain757f5ba2014-03-18 11:42:24 +1100377#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 return 0;
380}
381
382/* clean up after our dma is done */
383static int sun3scsi_dma_finish(int write_flag)
384{
Finn Thain757f5ba2014-03-18 11:42:24 +1100385 unsigned short __maybe_unused count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 unsigned short fifo;
387 int ret = 0;
388
389 sun3_dma_active = 0;
Finn Thain757f5ba2014-03-18 11:42:24 +1100390
391#ifdef SUN3_SCSI_VME
392 dregs->csr &= ~CSR_DMA_ENABLE;
393
394 fifo = dregs->fifo_count;
395 if (write_flag) {
396 if ((fifo > 0) && (fifo < sun3_dma_orig_count))
397 fifo++;
398 }
399
400 last_residual = fifo;
401 /* empty bytes from the fifo which didn't make it */
402 if ((!write_flag) && (dregs->csr & CSR_LEFT)) {
403 unsigned char *vaddr;
404
405 vaddr = (unsigned char *)dvma_vmetov(sun3_dma_orig_addr);
406
407 vaddr += (sun3_dma_orig_count - fifo);
408 vaddr--;
409
410 switch (dregs->csr & CSR_LEFT) {
411 case CSR_LEFT_3:
412 *vaddr = (dregs->bpack_lo & 0xff00) >> 8;
413 vaddr--;
414
415 case CSR_LEFT_2:
416 *vaddr = (dregs->bpack_hi & 0x00ff);
417 vaddr--;
418
419 case CSR_LEFT_1:
420 *vaddr = (dregs->bpack_hi & 0xff00) >> 8;
421 break;
422 }
423 }
424#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 // check to empty the fifo on a read
426 if(!write_flag) {
427 int tmo = 20000; /* .2 sec */
428
429 while(1) {
430 if(dregs->csr & CSR_FIFO_EMPTY)
431 break;
432
433 if(--tmo <= 0) {
434 printk("sun3scsi: fifo failed to empty!\n");
435 return 1;
436 }
437 udelay(10);
438 }
439 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
441 count = sun3scsi_dma_count(default_instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
443 fifo = dregs->fifo_count;
444 last_residual = fifo;
445
446 /* empty bytes from the fifo which didn't make it */
447 if((!write_flag) && (count - fifo) == 2) {
448 unsigned short data;
449 unsigned char *vaddr;
450
451 data = dregs->fifo_data;
452 vaddr = (unsigned char *)dvma_btov(sun3_dma_orig_addr);
453
454 vaddr += (sun3_dma_orig_count - fifo);
455
456 vaddr[-2] = (data & 0xff00) >> 8;
457 vaddr[-1] = (data & 0xff);
458 }
Finn Thain757f5ba2014-03-18 11:42:24 +1100459#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
461 dvma_unmap(sun3_dma_orig_addr);
462 sun3_dma_orig_addr = NULL;
Finn Thain757f5ba2014-03-18 11:42:24 +1100463
464#ifdef SUN3_SCSI_VME
465 dregs->dma_addr_hi = 0;
466 dregs->dma_addr_lo = 0;
467 dregs->dma_count_hi = 0;
468 dregs->dma_count_lo = 0;
469
470 dregs->fifo_count = 0;
471 dregs->fifo_count_hi = 0;
472
473 dregs->csr &= ~CSR_SEND;
474/* dregs->csr |= CSR_DMA_ENABLE; */
475#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 sun3_udc_write(UDC_RESET, UDC_CSR);
477 dregs->fifo_count = 0;
478 dregs->csr &= ~CSR_SEND;
479
480 /* reset fifo */
481 dregs->csr &= ~CSR_FIFO;
482 dregs->csr |= CSR_FIFO;
Finn Thain757f5ba2014-03-18 11:42:24 +1100483#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
485 sun3_dma_setup_done = NULL;
486
487 return ret;
488
489}
490
Finn Thain8dad0c52014-11-12 16:12:17 +1100491#include "atari_NCR5380.c"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
Finn Thain0d31f872014-11-13 12:21:28 +1100493#ifdef SUN3_SCSI_VME
494#define SUN3_SCSI_NAME "Sun3 NCR5380 VME SCSI"
495#define DRV_MODULE_NAME "sun3_scsi_vme"
496#else
497#define SUN3_SCSI_NAME "Sun3 NCR5380 SCSI"
498#define DRV_MODULE_NAME "sun3_scsi"
499#endif
500
501#define PFX DRV_MODULE_NAME ": "
502
503static struct scsi_host_template sun3_scsi_template = {
504 .module = THIS_MODULE,
505 .proc_name = DRV_MODULE_NAME,
Geert Uytterhoeven9dcc26c2013-04-10 13:52:09 +0200506 .show_info = sun3scsi_show_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 .name = SUN3_SCSI_NAME,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 .info = sun3scsi_info,
509 .queuecommand = sun3scsi_queue_command,
510 .eh_abort_handler = sun3scsi_abort,
511 .eh_bus_reset_handler = sun3scsi_bus_reset,
Finn Thaind572f652014-11-12 16:12:00 +1100512 .can_queue = 16,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 .this_id = 7,
Finn Thaind572f652014-11-12 16:12:00 +1100514 .sg_tablesize = SG_NONE,
515 .cmd_per_lun = 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 .use_clustering = DISABLE_CLUSTERING
517};
518
Finn Thain0d31f872014-11-13 12:21:28 +1100519static int __init sun3_scsi_probe(struct platform_device *pdev)
520{
521 struct Scsi_Host *instance;
522 int error;
523 struct resource *irq, *mem;
524 unsigned char *ioaddr;
525#ifdef SUN3_SCSI_VME
526 int i;
527#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528
Finn Thain0d31f872014-11-13 12:21:28 +1100529 if (setup_can_queue > 0)
530 sun3_scsi_template.can_queue = setup_can_queue;
531 if (setup_cmd_per_lun > 0)
532 sun3_scsi_template.cmd_per_lun = setup_cmd_per_lun;
533 if (setup_sg_tablesize >= 0)
534 sun3_scsi_template.sg_tablesize = setup_sg_tablesize;
535 if (setup_hostid >= 0)
536 sun3_scsi_template.this_id = setup_hostid & 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
Finn Thain0d31f872014-11-13 12:21:28 +1100538#ifdef SUPPORT_TAGS
539 if (setup_use_tagged_queuing < 0)
540 setup_use_tagged_queuing = 1;
541#endif
542
543#ifdef SUN3_SCSI_VME
544 ioaddr = NULL;
545 for (i = 0; i < 2; i++) {
546 unsigned char x;
547
548 irq = platform_get_resource(pdev, IORESOURCE_IRQ, i);
549 mem = platform_get_resource(pdev, IORESOURCE_MEM, i);
550 if (!irq || !mem)
551 break;
552
553 ioaddr = sun3_ioremap(mem->start, resource_size(mem),
554 SUN3_PAGE_TYPE_VME16);
555 dregs = (struct sun3_dma_regs *)(ioaddr + 8);
556
557 if (sun3_map_test((unsigned long)dregs, &x)) {
558 unsigned short oldcsr;
559
560 oldcsr = dregs->csr;
561 dregs->csr = 0;
562 udelay(SUN3_DMA_DELAY);
563 if (dregs->csr == 0x1400)
564 break;
565
566 dregs->csr = oldcsr;
567 }
568
569 iounmap(ioaddr);
570 ioaddr = NULL;
571 }
572 if (!ioaddr)
573 return -ENODEV;
574#else
575 irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
576 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
577 if (!irq || !mem)
578 return -ENODEV;
579
580 ioaddr = ioremap(mem->start, resource_size(mem));
581 dregs = (struct sun3_dma_regs *)(ioaddr + 8);
582
583 udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs));
584 if (!udc_regs) {
585 pr_err(PFX "couldn't allocate DVMA memory!\n");
586 iounmap(ioaddr);
587 return -ENOMEM;
588 }
589#endif
590
591 sun3_scsi_regp = ioaddr;
592
593 instance = scsi_host_alloc(&sun3_scsi_template,
594 sizeof(struct NCR5380_hostdata));
595 if (!instance) {
596 error = -ENOMEM;
597 goto fail_alloc;
598 }
599 default_instance = instance;
600
601 instance->io_port = (unsigned long)ioaddr;
602 instance->irq = irq->start;
603
604 NCR5380_init(instance, 0);
605
606 error = request_irq(instance->irq, scsi_sun3_intr, 0,
607 "NCR5380", instance);
608 if (error) {
609#ifdef REAL_DMA
610 pr_err(PFX "scsi%d: IRQ %d not free, bailing out\n",
611 instance->host_no, instance->irq);
612 goto fail_irq;
613#else
614 pr_warn(PFX "scsi%d: IRQ %d not free, interrupts disabled\n",
615 instance->host_no, instance->irq);
616 instance->irq = NO_IRQ;
617#endif
618 }
619
620 dregs->csr = 0;
621 udelay(SUN3_DMA_DELAY);
622 dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
623 udelay(SUN3_DMA_DELAY);
624 dregs->fifo_count = 0;
625#ifdef SUN3_SCSI_VME
626 dregs->fifo_count_hi = 0;
627 dregs->dma_addr_hi = 0;
628 dregs->dma_addr_lo = 0;
629 dregs->dma_count_hi = 0;
630 dregs->dma_count_lo = 0;
631
632 dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
633#endif
634
635#ifdef RESET_BOOT
636 sun3_scsi_reset_boot(instance);
637#endif
638
639 error = scsi_add_host(instance, NULL);
640 if (error)
641 goto fail_host;
642
643 platform_set_drvdata(pdev, instance);
644
645 scsi_scan_host(instance);
646 return 0;
647
648fail_host:
649 if (instance->irq != NO_IRQ)
650 free_irq(instance->irq, instance);
651fail_irq:
652 NCR5380_exit(instance);
653 scsi_host_put(instance);
654fail_alloc:
655 if (udc_regs)
656 dvma_free(udc_regs);
657 iounmap(sun3_scsi_regp);
658 return error;
659}
660
661static int __exit sun3_scsi_remove(struct platform_device *pdev)
662{
663 struct Scsi_Host *instance = platform_get_drvdata(pdev);
664
665 scsi_remove_host(instance);
666 if (instance->irq != NO_IRQ)
667 free_irq(instance->irq, instance);
668 NCR5380_exit(instance);
669 scsi_host_put(instance);
670 if (udc_regs)
671 dvma_free(udc_regs);
672 iounmap(sun3_scsi_regp);
673 return 0;
674}
675
676static struct platform_driver sun3_scsi_driver = {
677 .remove = __exit_p(sun3_scsi_remove),
678 .driver = {
679 .name = DRV_MODULE_NAME,
680 .owner = THIS_MODULE,
681 },
682};
683
684module_platform_driver_probe(sun3_scsi_driver, sun3_scsi_probe);
685
686MODULE_ALIAS("platform:" DRV_MODULE_NAME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687MODULE_LICENSE("GPL");