blob: bb660fe4739d6e6ff832f9e35161217d51647acd [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>
26#include <linux/stddef.h>
27#include <linux/ctype.h>
28#include <linux/delay.h>
29
30#include <linux/module.h>
31#include <linux/signal.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <linux/ioport.h>
33#include <linux/init.h>
34#include <linux/blkdev.h>
35
36#include <asm/io.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
38#include <asm/sun3ints.h>
39#include <asm/dvma.h>
40#include <asm/idprom.h>
41#include <asm/machines.h>
42
43/* dma on! */
44#define REAL_DMA
45
Linus Torvalds1da177e2005-04-16 15:20:36 -070046#include <scsi/scsi_host.h>
47#include "sun3_scsi.h"
Finn Thain9f6620a2014-03-18 11:42:23 +110048#include "NCR5380.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Finn Thain757f5ba2014-03-18 11:42:24 +110050extern int sun3_map_test(unsigned long, char *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Linus Torvalds1da177e2005-04-16 15:20:36 -070052/*#define RESET_BOOT */
Linus Torvalds1da177e2005-04-16 15:20:36 -070053/* #define SUPPORT_TAGS */
54
Finn Thain757f5ba2014-03-18 11:42:24 +110055#ifdef SUN3_SCSI_VME
56#define ENABLE_IRQ()
57#else
Linus Torvalds1da177e2005-04-16 15:20:36 -070058#define ENABLE_IRQ() enable_irq( IRQ_SUN3_SCSI );
Finn Thain757f5ba2014-03-18 11:42:24 +110059#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
61
David Howells7d12e782006-10-05 14:55:46 +010062static irqreturn_t scsi_sun3_intr(int irq, void *dummy);
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64static int setup_can_queue = -1;
65module_param(setup_can_queue, int, 0);
66static int setup_cmd_per_lun = -1;
67module_param(setup_cmd_per_lun, int, 0);
68static int setup_sg_tablesize = -1;
69module_param(setup_sg_tablesize, int, 0);
70#ifdef SUPPORT_TAGS
71static int setup_use_tagged_queuing = -1;
72module_param(setup_use_tagged_queuing, int, 0);
73#endif
74static int setup_hostid = -1;
75module_param(setup_hostid, int, 0);
76
Henne811c9362006-10-03 19:51:59 +020077static struct scsi_cmnd *sun3_dma_setup_done = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070078
Michael Schmitz2b0f8342014-05-02 20:43:01 +120079#define RESET_RUN_DONE
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081#define AFTER_RESET_DELAY (HZ/2)
82
83/* ms to wait after hitting dma regs */
84#define SUN3_DMA_DELAY 10
85
86/* dvma buffer to allocate -- 32k should hopefully be more than sufficient */
87#define SUN3_DVMA_BUFSIZE 0xe000
88
89/* minimum number of bytes to do dma on */
90#define SUN3_DMA_MINSIZE 128
91
92static volatile unsigned char *sun3_scsi_regp;
93static volatile struct sun3_dma_regs *dregs;
Finn Thain757f5ba2014-03-18 11:42:24 +110094#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -070095static struct sun3_udc_regs *udc_regs = NULL;
Finn Thain757f5ba2014-03-18 11:42:24 +110096#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070097static unsigned char *sun3_dma_orig_addr = NULL;
98static unsigned long sun3_dma_orig_count = 0;
99static int sun3_dma_active = 0;
100static unsigned long last_residual = 0;
101
102/*
103 * NCR 5380 register access functions
104 */
105
106static inline unsigned char sun3scsi_read(int reg)
107{
108 return( sun3_scsi_regp[reg] );
109}
110
111static inline void sun3scsi_write(int reg, int value)
112{
113 sun3_scsi_regp[reg] = value;
114}
115
Finn Thain757f5ba2014-03-18 11:42:24 +1100116#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117/* dma controller register access functions */
118
119static inline unsigned short sun3_udc_read(unsigned char reg)
120{
121 unsigned short ret;
122
123 dregs->udc_addr = UDC_CSR;
124 udelay(SUN3_DMA_DELAY);
125 ret = dregs->udc_data;
126 udelay(SUN3_DMA_DELAY);
127
128 return ret;
129}
130
131static inline void sun3_udc_write(unsigned short val, unsigned char reg)
132{
133 dregs->udc_addr = reg;
134 udelay(SUN3_DMA_DELAY);
135 dregs->udc_data = val;
136 udelay(SUN3_DMA_DELAY);
137}
Finn Thain757f5ba2014-03-18 11:42:24 +1100138#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
140/*
141 * XXX: status debug
142 */
143static struct Scsi_Host *default_instance;
144
145/*
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100146 * Function : int sun3scsi_detect(struct scsi_host_template * tpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 *
148 * Purpose : initializes mac NCR5380 driver based on the
149 * command line / compile time port and irq definitions.
150 *
151 * Inputs : tpnt - template for this SCSI adapter.
152 *
153 * Returns : 1 if a host adapter was found, 0 if not.
154 *
155 */
156
Finn Thain757f5ba2014-03-18 11:42:24 +1100157static int __init sun3scsi_detect(struct scsi_host_template *tpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158{
Finn Thain757f5ba2014-03-18 11:42:24 +1100159 unsigned long ioaddr, irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 static int called = 0;
161 struct Scsi_Host *instance;
Finn Thain757f5ba2014-03-18 11:42:24 +1100162#ifdef SUN3_SCSI_VME
163 int i;
164 unsigned long addrs[3] = { IOBASE_SUN3_VMESCSI,
165 IOBASE_SUN3_VMESCSI + 0x4000,
166 0 };
167 unsigned long vecs[3] = { SUN3_VEC_VMESCSI0,
168 SUN3_VEC_VMESCSI1,
169 0 };
170#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
172 /* check that this machine has an onboard 5380 */
173 switch(idprom->id_machtype) {
Finn Thain757f5ba2014-03-18 11:42:24 +1100174#ifdef SUN3_SCSI_VME
175 case SM_SUN3|SM_3_160:
176 case SM_SUN3|SM_3_260:
177 break;
178#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179 case SM_SUN3|SM_3_50:
180 case SM_SUN3|SM_3_60:
181 break;
Finn Thain757f5ba2014-03-18 11:42:24 +1100182#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
184 default:
185 return 0;
186 }
187
188 if(called)
189 return 0;
190
Finn Thain757f5ba2014-03-18 11:42:24 +1100191#ifdef SUN3_SCSI_VME
192 tpnt->proc_name = "Sun3 5380 VME SCSI";
193#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 tpnt->proc_name = "Sun3 5380 SCSI";
Finn Thain757f5ba2014-03-18 11:42:24 +1100195#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196
197 /* setup variables */
Finn Thaind572f652014-11-12 16:12:00 +1100198 if (setup_can_queue > 0)
199 tpnt->can_queue = setup_can_queue;
200 if (setup_cmd_per_lun > 0)
201 tpnt->cmd_per_lun = setup_cmd_per_lun;
202 if (setup_sg_tablesize >= 0)
203 tpnt->sg_tablesize = setup_sg_tablesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
205 if (setup_hostid >= 0)
206 tpnt->this_id = setup_hostid;
207 else {
208 /* use 7 as default */
209 tpnt->this_id = 7;
210 }
211
Finn Thain757f5ba2014-03-18 11:42:24 +1100212#ifdef SUN3_SCSI_VME
213 ioaddr = 0;
214 for (i = 0; addrs[i] != 0; i++) {
215 unsigned char x;
216
217 ioaddr = (unsigned long)sun3_ioremap(addrs[i], PAGE_SIZE,
218 SUN3_PAGE_TYPE_VME16);
219 irq = vecs[i];
220 sun3_scsi_regp = (unsigned char *)ioaddr;
221
222 dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8);
223
224 if (sun3_map_test((unsigned long)dregs, &x)) {
225 unsigned short oldcsr;
226
227 oldcsr = dregs->csr;
228 dregs->csr = 0;
229 udelay(SUN3_DMA_DELAY);
230 if (dregs->csr == 0x1400)
231 break;
232
233 dregs->csr = oldcsr;
234 }
235
236 iounmap((void *)ioaddr);
237 ioaddr = 0;
238 }
239
240 if (!ioaddr)
241 return 0;
242#else
243 irq = IRQ_SUN3_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 ioaddr = (unsigned long)ioremap(IOBASE_SUN3_SCSI, PAGE_SIZE);
245 sun3_scsi_regp = (unsigned char *)ioaddr;
246
247 dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8);
248
249 if((udc_regs = dvma_malloc(sizeof(struct sun3_udc_regs)))
250 == NULL) {
251 printk("SUN3 Scsi couldn't allocate DVMA memory!\n");
252 return 0;
253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254#endif
255#ifdef SUPPORT_TAGS
256 if (setup_use_tagged_queuing < 0)
Finn Thaind572f652014-11-12 16:12:00 +1100257 setup_use_tagged_queuing = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258#endif
259
260 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
261 if(instance == NULL)
262 return 0;
263
264 default_instance = instance;
265
266 instance->io_port = (unsigned long) ioaddr;
Finn Thain757f5ba2014-03-18 11:42:24 +1100267 instance->irq = irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
269 NCR5380_init(instance, 0);
270
271 instance->n_io_port = 32;
272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 if (request_irq(instance->irq, scsi_sun3_intr,
Jeff Garzik1e641662007-11-11 19:52:05 -0500274 0, "Sun3SCSI-5380", instance)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275#ifndef REAL_DMA
276 printk("scsi%d: IRQ%d not free, interrupts disabled\n",
277 instance->host_no, instance->irq);
Finn Thain22f5f102014-11-12 16:11:56 +1100278 instance->irq = NO_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279#else
280 printk("scsi%d: IRQ%d not free, bailing out\n",
281 instance->host_no, instance->irq);
282 return 0;
283#endif
284 }
285
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 dregs->csr = 0;
287 udelay(SUN3_DMA_DELAY);
288 dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR;
289 udelay(SUN3_DMA_DELAY);
290 dregs->fifo_count = 0;
Finn Thain757f5ba2014-03-18 11:42:24 +1100291#ifdef SUN3_SCSI_VME
292 dregs->fifo_count_hi = 0;
293 dregs->dma_addr_hi = 0;
294 dregs->dma_addr_lo = 0;
295 dregs->dma_count_hi = 0;
296 dregs->dma_count_lo = 0;
297
298 dregs->ivect = VME_DATA24 | (instance->irq & 0xff);
299#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 called = 1;
302
303#ifdef RESET_BOOT
304 sun3_scsi_reset_boot(instance);
305#endif
306
307 return 1;
308}
309
Finn Thained8b9e72014-11-12 16:11:51 +1100310static int sun3scsi_release(struct Scsi_Host *shpnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311{
Finn Thain22f5f102014-11-12 16:11:56 +1100312 if (shpnt->irq != NO_IRQ)
Jeff Garzik1e641662007-11-11 19:52:05 -0500313 free_irq(shpnt->irq, shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
315 iounmap((void *)sun3_scsi_regp);
316
Geert Uytterhoeven19b6c512011-06-13 20:39:19 +0200317 NCR5380_exit(shpnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 return 0;
319}
320
321#ifdef RESET_BOOT
322/*
323 * Our 'bus reset on boot' function
324 */
325
326static void sun3_scsi_reset_boot(struct Scsi_Host *instance)
327{
328 unsigned long end;
329
330 NCR5380_local_declare();
331 NCR5380_setup(instance);
332
333 /*
334 * Do a SCSI reset to clean up the bus during initialization. No
335 * messing with the queues, interrupts, or locks necessary here.
336 */
337
338 printk( "Sun3 SCSI: resetting the SCSI bus..." );
339
340 /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */
341// sun3_disable_irq( IRQ_SUN3_SCSI );
342
343 /* get in phase */
344 NCR5380_write( TARGET_COMMAND_REG,
345 PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) ));
346
347 /* assert RST */
348 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST );
349
350 /* The min. reset hold time is 25us, so 40us should be enough */
351 udelay( 50 );
352
353 /* reset RST and interrupt */
354 NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE );
355 NCR5380_read( RESET_PARITY_INTERRUPT_REG );
356
357 for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); )
358 barrier();
359
360 /* switch on SCSI IRQ again */
361// sun3_enable_irq( IRQ_SUN3_SCSI );
362
363 printk( " done\n" );
364}
365#endif
366
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367// safe bits for the CSR
368#define CSR_GOOD 0x060f
369
David Howells7d12e782006-10-05 14:55:46 +0100370static irqreturn_t scsi_sun3_intr(int irq, void *dummy)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371{
372 unsigned short csr = dregs->csr;
373 int handled = 0;
374
Finn Thain757f5ba2014-03-18 11:42:24 +1100375#ifdef SUN3_SCSI_VME
376 dregs->csr &= ~CSR_DMA_ENABLE;
377#endif
378
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 if(csr & ~CSR_GOOD) {
380 if(csr & CSR_DMA_BUSERR) {
381 printk("scsi%d: bus error in dma\n", default_instance->host_no);
382 }
383
384 if(csr & CSR_DMA_CONFLICT) {
385 printk("scsi%d: dma conflict\n", default_instance->host_no);
386 }
387 handled = 1;
388 }
389
390 if(csr & (CSR_SDB_INT | CSR_DMA_INT)) {
David Howells7d12e782006-10-05 14:55:46 +0100391 NCR5380_intr(irq, dummy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 handled = 1;
393 }
394
395 return IRQ_RETVAL(handled);
396}
397
398/*
399 * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk;
400 * reentering NCR5380_print_status seems to have ugly side effects
401 */
402
403/* this doesn't seem to get used at all -- sam */
404#if 0
405void sun3_sun3_debug (void)
406{
407 unsigned long flags;
408 NCR5380_local_declare();
409
410 if (default_instance) {
411 local_irq_save(flags);
412 NCR5380_print_status(default_instance);
413 local_irq_restore(flags);
414 }
415}
416#endif
417
418
419/* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */
420static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag)
421{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 void *addr;
423
424 if(sun3_dma_orig_addr != NULL)
425 dvma_unmap(sun3_dma_orig_addr);
426
Finn Thain757f5ba2014-03-18 11:42:24 +1100427#ifdef SUN3_SCSI_VME
428 addr = (void *)dvma_map_vme((unsigned long) data, count);
429#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 addr = (void *)dvma_map((unsigned long) data, count);
Finn Thain757f5ba2014-03-18 11:42:24 +1100431#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
433 sun3_dma_orig_addr = addr;
434 sun3_dma_orig_count = count;
Finn Thain757f5ba2014-03-18 11:42:24 +1100435
436#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 dregs->fifo_count = 0;
438 sun3_udc_write(UDC_RESET, UDC_CSR);
439
440 /* reset fifo */
441 dregs->csr &= ~CSR_FIFO;
442 dregs->csr |= CSR_FIFO;
Finn Thain757f5ba2014-03-18 11:42:24 +1100443#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444
445 /* set direction */
446 if(write_flag)
447 dregs->csr |= CSR_SEND;
448 else
449 dregs->csr &= ~CSR_SEND;
450
Finn Thain757f5ba2014-03-18 11:42:24 +1100451#ifdef SUN3_SCSI_VME
452 dregs->csr |= CSR_PACK_ENABLE;
453
454 dregs->dma_addr_hi = ((unsigned long)addr >> 16);
455 dregs->dma_addr_lo = ((unsigned long)addr & 0xffff);
456
457 dregs->dma_count_hi = 0;
458 dregs->dma_count_lo = 0;
459 dregs->fifo_count_hi = 0;
460 dregs->fifo_count = 0;
461#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 /* byte count for fifo */
463 dregs->fifo_count = count;
464
465 sun3_udc_write(UDC_RESET, UDC_CSR);
466
467 /* reset fifo */
468 dregs->csr &= ~CSR_FIFO;
469 dregs->csr |= CSR_FIFO;
470
471 if(dregs->fifo_count != count) {
472 printk("scsi%d: fifo_mismatch %04x not %04x\n",
473 default_instance->host_no, dregs->fifo_count,
474 (unsigned int) count);
Finn Thaind614f062014-03-18 11:42:16 +1100475 NCR5380_dprint(NDEBUG_DMA, default_instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 }
477
478 /* setup udc */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8);
480 udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 udc_regs->count = count/2; /* count in words */
482 udc_regs->mode_hi = UDC_MODE_HIWORD;
483 if(write_flag) {
484 if(count & 1)
485 udc_regs->count++;
486 udc_regs->mode_lo = UDC_MODE_LSEND;
487 udc_regs->rsel = UDC_RSEL_SEND;
488 } else {
489 udc_regs->mode_lo = UDC_MODE_LRECV;
490 udc_regs->rsel = UDC_RSEL_RECV;
491 }
492
493 /* announce location of regs block */
494 sun3_udc_write(((dvma_vtob(udc_regs) & 0xff0000) >> 8),
495 UDC_CHN_HI);
496
497 sun3_udc_write((dvma_vtob(udc_regs) & 0xffff), UDC_CHN_LO);
498
499 /* set dma master on */
500 sun3_udc_write(0xd, UDC_MODE);
501
502 /* interrupt enable */
503 sun3_udc_write(UDC_INT_ENABLE, UDC_CSR);
Finn Thain757f5ba2014-03-18 11:42:24 +1100504#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
506 return count;
507
508}
509
Finn Thain757f5ba2014-03-18 11:42:24 +1100510#ifndef SUN3_SCSI_VME
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance)
512{
513 unsigned short resid;
514
515 dregs->udc_addr = 0x32;
516 udelay(SUN3_DMA_DELAY);
517 resid = dregs->udc_data;
518 udelay(SUN3_DMA_DELAY);
519 resid *= 2;
520
521 return (unsigned long) resid;
522}
Finn Thain757f5ba2014-03-18 11:42:24 +1100523#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524
525static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance)
526{
527 return last_residual;
528}
529
Henne811c9362006-10-03 19:51:59 +0200530static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted,
531 struct scsi_cmnd *cmd,
532 int write_flag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533{
Christoph Hellwig33659eb2010-08-07 18:17:56 +0200534 if (cmd->request->cmd_type == REQ_TYPE_FS)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 return wanted;
536 else
537 return 0;
538}
539
540static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data)
541{
Finn Thain757f5ba2014-03-18 11:42:24 +1100542#ifdef SUN3_SCSI_VME
543 unsigned short csr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544
Finn Thain757f5ba2014-03-18 11:42:24 +1100545 csr = dregs->csr;
546
547 dregs->dma_count_hi = (sun3_dma_orig_count >> 16);
548 dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff);
549
550 dregs->fifo_count_hi = (sun3_dma_orig_count >> 16);
551 dregs->fifo_count = (sun3_dma_orig_count & 0xffff);
552
553/* if(!(csr & CSR_DMA_ENABLE))
554 * dregs->csr |= CSR_DMA_ENABLE;
555 */
556#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 sun3_udc_write(UDC_CHN_START, UDC_CSR);
Finn Thain757f5ba2014-03-18 11:42:24 +1100558#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
560 return 0;
561}
562
563/* clean up after our dma is done */
564static int sun3scsi_dma_finish(int write_flag)
565{
Finn Thain757f5ba2014-03-18 11:42:24 +1100566 unsigned short __maybe_unused count;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 unsigned short fifo;
568 int ret = 0;
569
570 sun3_dma_active = 0;
Finn Thain757f5ba2014-03-18 11:42:24 +1100571
572#ifdef SUN3_SCSI_VME
573 dregs->csr &= ~CSR_DMA_ENABLE;
574
575 fifo = dregs->fifo_count;
576 if (write_flag) {
577 if ((fifo > 0) && (fifo < sun3_dma_orig_count))
578 fifo++;
579 }
580
581 last_residual = fifo;
582 /* empty bytes from the fifo which didn't make it */
583 if ((!write_flag) && (dregs->csr & CSR_LEFT)) {
584 unsigned char *vaddr;
585
586 vaddr = (unsigned char *)dvma_vmetov(sun3_dma_orig_addr);
587
588 vaddr += (sun3_dma_orig_count - fifo);
589 vaddr--;
590
591 switch (dregs->csr & CSR_LEFT) {
592 case CSR_LEFT_3:
593 *vaddr = (dregs->bpack_lo & 0xff00) >> 8;
594 vaddr--;
595
596 case CSR_LEFT_2:
597 *vaddr = (dregs->bpack_hi & 0x00ff);
598 vaddr--;
599
600 case CSR_LEFT_1:
601 *vaddr = (dregs->bpack_hi & 0xff00) >> 8;
602 break;
603 }
604 }
605#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 // check to empty the fifo on a read
607 if(!write_flag) {
608 int tmo = 20000; /* .2 sec */
609
610 while(1) {
611 if(dregs->csr & CSR_FIFO_EMPTY)
612 break;
613
614 if(--tmo <= 0) {
615 printk("sun3scsi: fifo failed to empty!\n");
616 return 1;
617 }
618 udelay(10);
619 }
620 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622 count = sun3scsi_dma_count(default_instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
624 fifo = dregs->fifo_count;
625 last_residual = fifo;
626
627 /* empty bytes from the fifo which didn't make it */
628 if((!write_flag) && (count - fifo) == 2) {
629 unsigned short data;
630 unsigned char *vaddr;
631
632 data = dregs->fifo_data;
633 vaddr = (unsigned char *)dvma_btov(sun3_dma_orig_addr);
634
635 vaddr += (sun3_dma_orig_count - fifo);
636
637 vaddr[-2] = (data & 0xff00) >> 8;
638 vaddr[-1] = (data & 0xff);
639 }
Finn Thain757f5ba2014-03-18 11:42:24 +1100640#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
642 dvma_unmap(sun3_dma_orig_addr);
643 sun3_dma_orig_addr = NULL;
Finn Thain757f5ba2014-03-18 11:42:24 +1100644
645#ifdef SUN3_SCSI_VME
646 dregs->dma_addr_hi = 0;
647 dregs->dma_addr_lo = 0;
648 dregs->dma_count_hi = 0;
649 dregs->dma_count_lo = 0;
650
651 dregs->fifo_count = 0;
652 dregs->fifo_count_hi = 0;
653
654 dregs->csr &= ~CSR_SEND;
655/* dregs->csr |= CSR_DMA_ENABLE; */
656#else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 sun3_udc_write(UDC_RESET, UDC_CSR);
658 dregs->fifo_count = 0;
659 dregs->csr &= ~CSR_SEND;
660
661 /* reset fifo */
662 dregs->csr &= ~CSR_FIFO;
663 dregs->csr |= CSR_FIFO;
Finn Thain757f5ba2014-03-18 11:42:24 +1100664#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
666 sun3_dma_setup_done = NULL;
667
668 return ret;
669
670}
671
672#include "sun3_NCR5380.c"
673
Christoph Hellwigd0be4a7d2005-10-31 18:31:40 +0100674static struct scsi_host_template driver_template = {
Geert Uytterhoeven9dcc26c2013-04-10 13:52:09 +0200675 .show_info = sun3scsi_show_info,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 .name = SUN3_SCSI_NAME,
677 .detect = sun3scsi_detect,
678 .release = sun3scsi_release,
679 .info = sun3scsi_info,
680 .queuecommand = sun3scsi_queue_command,
681 .eh_abort_handler = sun3scsi_abort,
682 .eh_bus_reset_handler = sun3scsi_bus_reset,
Finn Thaind572f652014-11-12 16:12:00 +1100683 .can_queue = 16,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 .this_id = 7,
Finn Thaind572f652014-11-12 16:12:00 +1100685 .sg_tablesize = SG_NONE,
686 .cmd_per_lun = 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 .use_clustering = DISABLE_CLUSTERING
688};
689
690
691#include "scsi_module.c"
692
693MODULE_LICENSE("GPL");