blob: 3e6386252953bdd698b08d7fc34c8a4777b1d395 [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
23 *
24 * ALPHA RELEASE 1.
Linus Torvalds1da177e2005-04-16 15:20:36 -070025 */
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/types.h>
28#include <linux/stddef.h>
29#include <linux/ctype.h>
30#include <linux/delay.h>
31
32#include <linux/module.h>
33#include <linux/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070034#include <linux/ioport.h>
35#include <linux/init.h>
36#include <linux/blkdev.h>
37
38#include <asm/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40#include <asm/sun3ints.h>
41#include <asm/dvma.h>
42#include <asm/idprom.h>
43#include <asm/machines.h>
44
45/* dma on! */
46#define REAL_DMA
47
48#include "scsi.h"
49#include <scsi/scsi_host.h>
50#include "sun3_scsi.h"
Finn Thain9f6620a2014-03-18 11:42:23 +110051#include "NCR5380.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
Finn Thain757f5ba2014-03-18 11:42:24 +110053extern int sun3_map_test(unsigned long, char *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
Linus Torvalds1da177e2005-04-16 15:20:36 -070055/*#define RESET_BOOT */
Linus Torvalds1da177e2005-04-16 15:20:36 -070056/* #define SUPPORT_TAGS */
57
Finn Thain757f5ba2014-03-18 11:42:24 +110058#ifdef SUN3_SCSI_VME
59#define ENABLE_IRQ()
60#else
Linus Torvalds1da177e2005-04-16 15:20:36 -070061#define ENABLE_IRQ() enable_irq( IRQ_SUN3_SCSI );
Finn Thain757f5ba2014-03-18 11:42:24 +110062#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64
David Howells7d12e782006-10-05 14:55:46 +010065static irqreturn_t scsi_sun3_intr(int irq, void *dummy);
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67static int setup_can_queue = -1;
68module_param(setup_can_queue, int, 0);
69static int setup_cmd_per_lun = -1;
70module_param(setup_cmd_per_lun, int, 0);
71static int setup_sg_tablesize = -1;
72module_param(setup_sg_tablesize, int, 0);
73#ifdef SUPPORT_TAGS
74static int setup_use_tagged_queuing = -1;
75module_param(setup_use_tagged_queuing, int, 0);
76#endif
77static int setup_hostid = -1;
78module_param(setup_hostid, int, 0);
79
Henne811c9362006-10-03 19:51:59 +020080static struct scsi_cmnd *sun3_dma_setup_done = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070081
Michael Schmitz2b0f8342014-05-02 20:43:01 +120082#define RESET_RUN_DONE
83
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#define AFTER_RESET_DELAY (HZ/2)
85
86/* ms to wait after hitting dma regs */
87#define SUN3_DMA_DELAY 10
88
89/* dvma buffer to allocate -- 32k should hopefully be more than sufficient */
90#define SUN3_DVMA_BUFSIZE 0xe000
91
92/* minimum number of bytes to do dma on */
93#define SUN3_DMA_MINSIZE 128
94
95static volatile unsigned char *sun3_scsi_regp;
96static volatile struct sun3_dma_regs *dregs;
Finn Thain757f5ba2014-03-18 11:42:24 +110097#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -070098static struct sun3_udc_regs *udc_regs = NULL;
Finn Thain757f5ba2014-03-18 11:42:24 +110099#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100static unsigned char *sun3_dma_orig_addr = NULL;
101static unsigned long sun3_dma_orig_count = 0;
102static int sun3_dma_active = 0;
103static unsigned long last_residual = 0;
104
105/*
106 * NCR 5380 register access functions
107 */
108
109static inline unsigned char sun3scsi_read(int reg)
110{
111 return( sun3_scsi_regp[reg] );
112}
113
114static inline void sun3scsi_write(int reg, int value)
115{
116 sun3_scsi_regp[reg] = value;
117}
118
Finn Thain757f5ba2014-03-18 11:42:24 +1100119#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120/* dma controller register access functions */
121
122static inline unsigned short sun3_udc_read(unsigned char reg)
123{
124 unsigned short ret;
125
126 dregs->udc_addr = UDC_CSR;
127 udelay(SUN3_DMA_DELAY);
128 ret = dregs->udc_data;
129 udelay(SUN3_DMA_DELAY);
130
131 return ret;
132}
133
134static inline void sun3_udc_write(unsigned short val, unsigned char reg)
135{
136 dregs->udc_addr = reg;
137 udelay(SUN3_DMA_DELAY);
138 dregs->udc_data = val;
139 udelay(SUN3_DMA_DELAY);
140}
Finn Thain757f5ba2014-03-18 11:42:24 +1100141#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143/*
144 * XXX: status debug
145 */
146static struct Scsi_Host *default_instance;
147
148/*
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100149 * Function : int sun3scsi_detect(struct scsi_host_template * tpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 *
151 * Purpose : initializes mac NCR5380 driver based on the
152 * command line / compile time port and irq definitions.
153 *
154 * Inputs : tpnt - template for this SCSI adapter.
155 *
156 * Returns : 1 if a host adapter was found, 0 if not.
157 *
158 */
159
Finn Thain757f5ba2014-03-18 11:42:24 +1100160static int __init sun3scsi_detect(struct scsi_host_template *tpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161{
Finn Thain757f5ba2014-03-18 11:42:24 +1100162 unsigned long ioaddr, irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 static int called = 0;
164 struct Scsi_Host *instance;
Finn Thain757f5ba2014-03-18 11:42:24 +1100165#ifdef SUN3_SCSI_VME
166 int i;
167 unsigned long addrs[3] = { IOBASE_SUN3_VMESCSI,
168 IOBASE_SUN3_VMESCSI + 0x4000,
169 0 };
170 unsigned long vecs[3] = { SUN3_VEC_VMESCSI0,
171 SUN3_VEC_VMESCSI1,
172 0 };
173#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174
175 /* check that this machine has an onboard 5380 */
176 switch(idprom->id_machtype) {
Finn Thain757f5ba2014-03-18 11:42:24 +1100177#ifdef SUN3_SCSI_VME
178 case SM_SUN3|SM_3_160:
179 case SM_SUN3|SM_3_260:
180 break;
181#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 case SM_SUN3|SM_3_50:
183 case SM_SUN3|SM_3_60:
184 break;
Finn Thain757f5ba2014-03-18 11:42:24 +1100185#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186
187 default:
188 return 0;
189 }
190
191 if(called)
192 return 0;
193
Finn Thain757f5ba2014-03-18 11:42:24 +1100194#ifdef SUN3_SCSI_VME
195 tpnt->proc_name = "Sun3 5380 VME SCSI";
196#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 tpnt->proc_name = "Sun3 5380 SCSI";
Finn Thain757f5ba2014-03-18 11:42:24 +1100198#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
200 /* setup variables */
201 tpnt->can_queue =
202 (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE;
203 tpnt->cmd_per_lun =
204 (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN;
205 tpnt->sg_tablesize =
206 (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE;
207
208 if (setup_hostid >= 0)
209 tpnt->this_id = setup_hostid;
210 else {
211 /* use 7 as default */
212 tpnt->this_id = 7;
213 }
214
Finn Thain757f5ba2014-03-18 11:42:24 +1100215#ifdef SUN3_SCSI_VME
216 ioaddr = 0;
217 for (i = 0; addrs[i] != 0; i++) {
218 unsigned char x;
219
220 ioaddr = (unsigned long)sun3_ioremap(addrs[i], PAGE_SIZE,
221 SUN3_PAGE_TYPE_VME16);
222 irq = vecs[i];
223 sun3_scsi_regp = (unsigned char *)ioaddr;
224
225 dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8);
226
227 if (sun3_map_test((unsigned long)dregs, &x)) {
228 unsigned short oldcsr;
229
230 oldcsr = dregs->csr;
231 dregs->csr = 0;
232 udelay(SUN3_DMA_DELAY);
233 if (dregs->csr == 0x1400)
234 break;
235
236 dregs->csr = oldcsr;
237 }
238
239 iounmap((void *)ioaddr);
240 ioaddr = 0;
241 }
242
243 if (!ioaddr)
244 return 0;
245#else
246 irq = IRQ_SUN3_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 ioaddr = (unsigned long)ioremap(IOBASE_SUN3_SCSI, PAGE_SIZE);
248 sun3_scsi_regp = (unsigned char *)ioaddr;
249
250 dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8);
251
252 if((udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs)))
253 == NULL) {
254 printk("SUN3 Scsi couldn't allocate DVMA memory!\n");
255 return 0;
256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257#endif
258#ifdef SUPPORT_TAGS
259 if (setup_use_tagged_queuing < 0)
260 setup_use_tagged_queuing = USE_TAGGED_QUEUING;
261#endif
262
263 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
264 if(instance == NULL)
265 return 0;
266
267 default_instance = instance;
268
269 instance->io_port = (unsigned long) ioaddr;
Finn Thain757f5ba2014-03-18 11:42:24 +1100270 instance->irq = irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
272 NCR5380_init(instance, 0);
273
274 instance->n_io_port = 32;
275
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 if (request_irq(instance->irq, scsi_sun3_intr,
Jeff Garzik1e641662007-11-11 19:52:05 -0500277 0, "Sun3SCSI-5380", instance)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278#ifndef REAL_DMA
279 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
280 instance->host_no, instance->irq);
Finn Thain22f5f102014-11-12 16:11:56 +1100281 instance->irq = NO_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282#else
283 printk("scsi%d: IRQ%d not free, bailing out\n",
284 instance->host_no, instance->irq);
285 return 0;
286#endif
287 }
288
Finn Thain757f5ba2014-03-18 11:42:24 +1100289 pr_info("scsi%d: %s at port %lX irq", instance->host_no,
290 tpnt->proc_name, instance->io_port);
Finn Thain22f5f102014-11-12 16:11:56 +1100291 if (instance->irq == NO_IRQ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 printk ("s disabled");
293 else
294 printk (" %d", instance->irq);
295 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
296 instance->can_queue, instance->cmd_per_lun,
297 SUN3SCSI_PUBLIC_RELEASE);
298 printk("\nscsi%d:", instance->host_no);
299 NCR5380_print_options(instance);
300 printk("\n");
301
302 dregs->csr = 0;
303 udelay(SUN3_DMA_DELAY);
304 dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
305 udelay(SUN3_DMA_DELAY);
306 dregs->fifo_count = 0;
Finn Thain757f5ba2014-03-18 11:42:24 +1100307#ifdef SUN3_SCSI_VME
308 dregs->fifo_count_hi = 0;
309 dregs->dma_addr_hi = 0;
310 dregs->dma_addr_lo = 0;
311 dregs->dma_count_hi = 0;
312 dregs->dma_count_lo = 0;
313
314 dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
315#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316
317 called = 1;
318
319#ifdef RESET_BOOT
320 sun3_scsi_reset_boot(instance);
321#endif
322
323 return 1;
324}
325
Finn Thained8b9e72014-11-12 16:11:51 +1100326static int sun3scsi_release(struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327{
Finn Thain22f5f102014-11-12 16:11:56 +1100328 if (shpnt->irq != NO_IRQ)
Jeff Garzik1e641662007-11-11 19:52:05 -0500329 free_irq(shpnt->irq, shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330
331 iounmap((void *)sun3_scsi_regp);
332
Geert Uytterhoeven19b6c512011-06-13 20:39:19 +0200333 NCR5380_exit(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334 return 0;
335}
336
337#ifdef RESET_BOOT
338/*
339 * Our 'bus reset on boot' function
340 */
341
342static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
343{
344 unsigned long end;
345
346 NCR5380_local_declare();
347 NCR5380_setup(instance);
348
349 /*
350 * Do a SCSI reset to clean up the bus during initialization. No
351 * messing with the queues, interrupts, or locks necessary here.
352 */
353
354 printk( "Sun3 SCSI: resetting the SCSI bus..." );
355
356 /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
357// sun3_disable_irq( IRQ_SUN3_SCSI );
358
359 /* get in phase */
360 NCR5380_write( TARGET_COMMAND_REG,
361 PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
362
363 /* assert RST */
364 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
365
366 /* The min. reset hold time is 25us, so 40us should be enough */
367 udelay( 50 );
368
369 /* reset RST and interrupt */
370 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
371 NCR5380_read( RESET_PARITY_INTERRUPT_REG );
372
373 for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
374 barrier();
375
376 /* switch on SCSI IRQ again */
377// sun3_enable_irq( IRQ_SUN3_SCSI );
378
379 printk( " done\n" );
380}
381#endif
382
Finn Thain757f5ba2014-03-18 11:42:24 +1100383static const char *sun3scsi_info(struct Scsi_Host *spnt)
384{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 return "";
386}
387
388// safe bits for the CSR
389#define CSR_GOOD 0x060f
390
David Howells7d12e782006-10-05 14:55:46 +0100391static irqreturn_t scsi_sun3_intr(int irq, void *dummy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
393 unsigned short csr = dregs->csr;
394 int handled = 0;
395
Finn Thain757f5ba2014-03-18 11:42:24 +1100396#ifdef SUN3_SCSI_VME
397 dregs->csr &= ~CSR_DMA_ENABLE;
398#endif
399
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 if(csr & ~CSR_GOOD) {
401 if(csr & CSR_DMA_BUSERR) {
402 printk("scsi%d: bus error in dma\n", default_instance->host_no);
403 }
404
405 if(csr & CSR_DMA_CONFLICT) {
406 printk("scsi%d: dma conflict\n", default_instance->host_no);
407 }
408 handled = 1;
409 }
410
411 if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
David Howells7d12e782006-10-05 14:55:46 +0100412 NCR5380_intr(irq, dummy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 handled = 1;
414 }
415
416 return IRQ_RETVAL(handled);
417}
418
419/*
420 * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk;
421 * reentering NCR5380_print_status seems to have ugly side effects
422 */
423
424/* this doesn't seem to get used at all -- sam */
425#if 0
426void sun3_sun3_debug (void)
427{
428 unsigned long flags;
429 NCR5380_local_declare();
430
431 if (default_instance) {
432 local_irq_save(flags);
433 NCR5380_print_status(default_instance);
434 local_irq_restore(flags);
435 }
436}
437#endif
438
439
440/* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */
441static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag)
442{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 void *addr;
444
445 if(sun3_dma_orig_addr != NULL)
446 dvma_unmap(sun3_dma_orig_addr);
447
Finn Thain757f5ba2014-03-18 11:42:24 +1100448#ifdef SUN3_SCSI_VME
449 addr = (void *)dvma_map_vme((unsigned long) data, count);
450#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 addr = (void *)dvma_map((unsigned long) data, count);
Finn Thain757f5ba2014-03-18 11:42:24 +1100452#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453
454 sun3_dma_orig_addr = addr;
455 sun3_dma_orig_count = count;
Finn Thain757f5ba2014-03-18 11:42:24 +1100456
457#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 dregs->fifo_count = 0;
459 sun3_udc_write(UDC_RESET, UDC_CSR);
460
461 /* reset fifo */
462 dregs->csr &= ~CSR_FIFO;
463 dregs->csr |= CSR_FIFO;
Finn Thain757f5ba2014-03-18 11:42:24 +1100464#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
466 /* set direction */
467 if(write_flag)
468 dregs->csr |= CSR_SEND;
469 else
470 dregs->csr &= ~CSR_SEND;
471
Finn Thain757f5ba2014-03-18 11:42:24 +1100472#ifdef SUN3_SCSI_VME
473 dregs->csr |= CSR_PACK_ENABLE;
474
475 dregs->dma_addr_hi = ((unsigned long)addr >> 16);
476 dregs->dma_addr_lo = ((unsigned long)addr & 0xffff);
477
478 dregs->dma_count_hi = 0;
479 dregs->dma_count_lo = 0;
480 dregs->fifo_count_hi = 0;
481 dregs->fifo_count = 0;
482#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 /* byte count for fifo */
484 dregs->fifo_count = count;
485
486 sun3_udc_write(UDC_RESET, UDC_CSR);
487
488 /* reset fifo */
489 dregs->csr &= ~CSR_FIFO;
490 dregs->csr |= CSR_FIFO;
491
492 if(dregs->fifo_count != count) {
493 printk("scsi%d: fifo_mismatch %04x not %04x\n",
494 default_instance->host_no, dregs->fifo_count,
495 (unsigned int) count);
Finn Thaind614f062014-03-18 11:42:16 +1100496 NCR5380_dprint(NDEBUG_DMA, default_instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 }
498
499 /* setup udc */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8);
501 udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 udc_regs->count = count/2; /* count in words */
503 udc_regs->mode_hi = UDC_MODE_HIWORD;
504 if(write_flag) {
505 if(count & 1)
506 udc_regs->count++;
507 udc_regs->mode_lo = UDC_MODE_LSEND;
508 udc_regs->rsel = UDC_RSEL_SEND;
509 } else {
510 udc_regs->mode_lo = UDC_MODE_LRECV;
511 udc_regs->rsel = UDC_RSEL_RECV;
512 }
513
514 /* announce location of regs block */
515 sun3_udc_write(((dvma_vtob(udc_regs) & 0xff0000) >> 8),
516 UDC_CHN_HI);
517
518 sun3_udc_write((dvma_vtob(udc_regs) & 0xffff), UDC_CHN_LO);
519
520 /* set dma master on */
521 sun3_udc_write(0xd, UDC_MODE);
522
523 /* interrupt enable */
524 sun3_udc_write(UDC_INT_ENABLE, UDC_CSR);
Finn Thain757f5ba2014-03-18 11:42:24 +1100525#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526
527 return count;
528
529}
530
Finn Thain757f5ba2014-03-18 11:42:24 +1100531#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance)
533{
534 unsigned short resid;
535
536 dregs->udc_addr = 0x32;
537 udelay(SUN3_DMA_DELAY);
538 resid = dregs->udc_data;
539 udelay(SUN3_DMA_DELAY);
540 resid *= 2;
541
542 return (unsigned long) resid;
543}
Finn Thain757f5ba2014-03-18 11:42:24 +1100544#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
546static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance)
547{
548 return last_residual;
549}
550
Henne811c9362006-10-03 19:51:59 +0200551static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted,
552 struct scsi_cmnd *cmd,
553 int write_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554{
Christoph Hellwig33659eb2010-08-07 18:17:56 +0200555 if (cmd->request->cmd_type == REQ_TYPE_FS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 return wanted;
557 else
558 return 0;
559}
560
561static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data)
562{
Finn Thain757f5ba2014-03-18 11:42:24 +1100563#ifdef SUN3_SCSI_VME
564 unsigned short csr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565
Finn Thain757f5ba2014-03-18 11:42:24 +1100566 csr = dregs->csr;
567
568 dregs->dma_count_hi = (sun3_dma_orig_count >> 16);
569 dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff);
570
571 dregs->fifo_count_hi = (sun3_dma_orig_count >> 16);
572 dregs->fifo_count = (sun3_dma_orig_count & 0xffff);
573
574/* if(!(csr & CSR_DMA_ENABLE))
575 * dregs->csr |= CSR_DMA_ENABLE;
576 */
577#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 sun3_udc_write(UDC_CHN_START, UDC_CSR);
Finn Thain757f5ba2014-03-18 11:42:24 +1100579#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
581 return 0;
582}
583
584/* clean up after our dma is done */
585static int sun3scsi_dma_finish(int write_flag)
586{
Finn Thain757f5ba2014-03-18 11:42:24 +1100587 unsigned short __maybe_unused count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 unsigned short fifo;
589 int ret = 0;
590
591 sun3_dma_active = 0;
Finn Thain757f5ba2014-03-18 11:42:24 +1100592
593#ifdef SUN3_SCSI_VME
594 dregs->csr &= ~CSR_DMA_ENABLE;
595
596 fifo = dregs->fifo_count;
597 if (write_flag) {
598 if ((fifo > 0) && (fifo < sun3_dma_orig_count))
599 fifo++;
600 }
601
602 last_residual = fifo;
603 /* empty bytes from the fifo which didn't make it */
604 if ((!write_flag) && (dregs->csr & CSR_LEFT)) {
605 unsigned char *vaddr;
606
607 vaddr = (unsigned char *)dvma_vmetov(sun3_dma_orig_addr);
608
609 vaddr += (sun3_dma_orig_count - fifo);
610 vaddr--;
611
612 switch (dregs->csr & CSR_LEFT) {
613 case CSR_LEFT_3:
614 *vaddr = (dregs->bpack_lo & 0xff00) >> 8;
615 vaddr--;
616
617 case CSR_LEFT_2:
618 *vaddr = (dregs->bpack_hi & 0x00ff);
619 vaddr--;
620
621 case CSR_LEFT_1:
622 *vaddr = (dregs->bpack_hi & 0xff00) >> 8;
623 break;
624 }
625 }
626#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 // check to empty the fifo on a read
628 if(!write_flag) {
629 int tmo = 20000; /* .2 sec */
630
631 while(1) {
632 if(dregs->csr & CSR_FIFO_EMPTY)
633 break;
634
635 if(--tmo <= 0) {
636 printk("sun3scsi: fifo failed to empty!\n");
637 return 1;
638 }
639 udelay(10);
640 }
641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
643 count = sun3scsi_dma_count(default_instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
645 fifo = dregs->fifo_count;
646 last_residual = fifo;
647
648 /* empty bytes from the fifo which didn't make it */
649 if((!write_flag) && (count - fifo) == 2) {
650 unsigned short data;
651 unsigned char *vaddr;
652
653 data = dregs->fifo_data;
654 vaddr = (unsigned char *)dvma_btov(sun3_dma_orig_addr);
655
656 vaddr += (sun3_dma_orig_count - fifo);
657
658 vaddr[-2] = (data & 0xff00) >> 8;
659 vaddr[-1] = (data & 0xff);
660 }
Finn Thain757f5ba2014-03-18 11:42:24 +1100661#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
663 dvma_unmap(sun3_dma_orig_addr);
664 sun3_dma_orig_addr = NULL;
Finn Thain757f5ba2014-03-18 11:42:24 +1100665
666#ifdef SUN3_SCSI_VME
667 dregs->dma_addr_hi = 0;
668 dregs->dma_addr_lo = 0;
669 dregs->dma_count_hi = 0;
670 dregs->dma_count_lo = 0;
671
672 dregs->fifo_count = 0;
673 dregs->fifo_count_hi = 0;
674
675 dregs->csr &= ~CSR_SEND;
676/* dregs->csr |= CSR_DMA_ENABLE; */
677#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 sun3_udc_write(UDC_RESET, UDC_CSR);
679 dregs->fifo_count = 0;
680 dregs->csr &= ~CSR_SEND;
681
682 /* reset fifo */
683 dregs->csr &= ~CSR_FIFO;
684 dregs->csr |= CSR_FIFO;
Finn Thain757f5ba2014-03-18 11:42:24 +1100685#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
687 sun3_dma_setup_done = NULL;
688
689 return ret;
690
691}
692
693#include "sun3_NCR5380.c"
694
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100695static struct scsi_host_template driver_template = {
Geert Uytterhoeven9dcc26c2013-04-10 13:52:09 +0200696 .show_info = sun3scsi_show_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 .name = SUN3_SCSI_NAME,
698 .detect = sun3scsi_detect,
699 .release = sun3scsi_release,
700 .info = sun3scsi_info,
701 .queuecommand = sun3scsi_queue_command,
702 .eh_abort_handler = sun3scsi_abort,
703 .eh_bus_reset_handler = sun3scsi_bus_reset,
704 .can_queue = CAN_QUEUE,
705 .this_id = 7,
706 .sg_tablesize = SG_TABLESIZE,
707 .cmd_per_lun = CMD_PER_LUN,
708 .use_clustering = DISABLE_CLUSTERING
709};
710
711
712#include "scsi_module.c"
713
714MODULE_LICENSE("GPL");