diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2014-03-17 20:42:24 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-05-28 06:16:28 -0400 |
commit | 757f5bad2b748dca6f82e660875320d156485ea5 (patch) | |
tree | 546120895d9d01ac96ab9c2c86f4fe135a3ea54a /drivers/scsi | |
parent | 9f6620a318e87d73f8ce3daa7f84efc739d1fa2d (diff) |
scsi/NCR5380: merge sun3_scsi_vme.c into sun3_scsi.c
The sun3 drivers suffer from a whole bunch of duplicated code. Fix this
by following the g_NCR5380_mmio example. (Notionally, sun3_scsi relates to
sun3_scsi_vme in the same way that g_NCR5380 relates to g_NCR5380_mmio.)
Dead code is also removed: we now have working debug macros so
SUN3_SCSI_DEBUG is undesirable. Dead code within #ifdef OLD_DMA is also
dropped, consistent with sun3_scsi_vme.c.
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Acked-by: Sam Creasey <sammy@sammy.net>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/sun3_scsi.c | 223 | ||||
-rw-r--r-- | drivers/scsi/sun3_scsi_vme.c | 583 |
2 files changed, 172 insertions, 634 deletions
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index ac9c29b55a33..9707b7494a89 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c | |||
@@ -3,6 +3,10 @@ | |||
3 | * | 3 | * |
4 | * Sun3 DMA routines added by Sam Creasey (sammy@sammy.net) | 4 | * Sun3 DMA routines added by Sam Creasey (sammy@sammy.net) |
5 | * | 5 | * |
6 | * VME support added by Sam Creasey | ||
7 | * | ||
8 | * TODO: modify this driver to support multiple Sun3 SCSI VME boards | ||
9 | * | ||
6 | * Adapted from mac_scsinew.c: | 10 | * Adapted from mac_scsinew.c: |
7 | */ | 11 | */ |
8 | /* | 12 | /* |
@@ -73,7 +77,7 @@ | |||
73 | #include "sun3_scsi.h" | 77 | #include "sun3_scsi.h" |
74 | #include "NCR5380.h" | 78 | #include "NCR5380.h" |
75 | 79 | ||
76 | /* #define OLDDMA */ | 80 | extern int sun3_map_test(unsigned long, char *); |
77 | 81 | ||
78 | #define USE_WRAPPER | 82 | #define USE_WRAPPER |
79 | /*#define RESET_BOOT */ | 83 | /*#define RESET_BOOT */ |
@@ -89,7 +93,11 @@ | |||
89 | 93 | ||
90 | /* #define SUPPORT_TAGS */ | 94 | /* #define SUPPORT_TAGS */ |
91 | 95 | ||
96 | #ifdef SUN3_SCSI_VME | ||
97 | #define ENABLE_IRQ() | ||
98 | #else | ||
92 | #define ENABLE_IRQ() enable_irq( IRQ_SUN3_SCSI ); | 99 | #define ENABLE_IRQ() enable_irq( IRQ_SUN3_SCSI ); |
100 | #endif | ||
93 | 101 | ||
94 | 102 | ||
95 | static irqreturn_t scsi_sun3_intr(int irq, void *dummy); | 103 | static irqreturn_t scsi_sun3_intr(int irq, void *dummy); |
@@ -126,10 +134,9 @@ static struct scsi_cmnd *sun3_dma_setup_done = NULL; | |||
126 | 134 | ||
127 | static volatile unsigned char *sun3_scsi_regp; | 135 | static volatile unsigned char *sun3_scsi_regp; |
128 | static volatile struct sun3_dma_regs *dregs; | 136 | static volatile struct sun3_dma_regs *dregs; |
129 | #ifdef OLDDMA | 137 | #ifndef SUN3_SCSI_VME |
130 | static unsigned char *dmabuf = NULL; /* dma memory buffer */ | ||
131 | #endif | ||
132 | static struct sun3_udc_regs *udc_regs = NULL; | 138 | static struct sun3_udc_regs *udc_regs = NULL; |
139 | #endif | ||
133 | static unsigned char *sun3_dma_orig_addr = NULL; | 140 | static unsigned char *sun3_dma_orig_addr = NULL; |
134 | static unsigned long sun3_dma_orig_count = 0; | 141 | static unsigned long sun3_dma_orig_count = 0; |
135 | static int sun3_dma_active = 0; | 142 | static int sun3_dma_active = 0; |
@@ -149,6 +156,7 @@ static inline void sun3scsi_write(int reg, int value) | |||
149 | sun3_scsi_regp[reg] = value; | 156 | sun3_scsi_regp[reg] = value; |
150 | } | 157 | } |
151 | 158 | ||
159 | #ifndef SUN3_SCSI_VME | ||
152 | /* dma controller register access functions */ | 160 | /* dma controller register access functions */ |
153 | 161 | ||
154 | static inline unsigned short sun3_udc_read(unsigned char reg) | 162 | static inline unsigned short sun3_udc_read(unsigned char reg) |
@@ -170,6 +178,7 @@ static inline void sun3_udc_write(unsigned short val, unsigned char reg) | |||
170 | dregs->udc_data = val; | 178 | dregs->udc_data = val; |
171 | udelay(SUN3_DMA_DELAY); | 179 | udelay(SUN3_DMA_DELAY); |
172 | } | 180 | } |
181 | #endif | ||
173 | 182 | ||
174 | /* | 183 | /* |
175 | * XXX: status debug | 184 | * XXX: status debug |
@@ -188,17 +197,32 @@ static struct Scsi_Host *default_instance; | |||
188 | * | 197 | * |
189 | */ | 198 | */ |
190 | 199 | ||
191 | int __init sun3scsi_detect(struct scsi_host_template * tpnt) | 200 | static int __init sun3scsi_detect(struct scsi_host_template *tpnt) |
192 | { | 201 | { |
193 | unsigned long ioaddr; | 202 | unsigned long ioaddr, irq; |
194 | static int called = 0; | 203 | static int called = 0; |
195 | struct Scsi_Host *instance; | 204 | struct Scsi_Host *instance; |
205 | #ifdef SUN3_SCSI_VME | ||
206 | int i; | ||
207 | unsigned long addrs[3] = { IOBASE_SUN3_VMESCSI, | ||
208 | IOBASE_SUN3_VMESCSI + 0x4000, | ||
209 | 0 }; | ||
210 | unsigned long vecs[3] = { SUN3_VEC_VMESCSI0, | ||
211 | SUN3_VEC_VMESCSI1, | ||
212 | 0 }; | ||
213 | #endif | ||
196 | 214 | ||
197 | /* check that this machine has an onboard 5380 */ | 215 | /* check that this machine has an onboard 5380 */ |
198 | switch(idprom->id_machtype) { | 216 | switch(idprom->id_machtype) { |
217 | #ifdef SUN3_SCSI_VME | ||
218 | case SM_SUN3|SM_3_160: | ||
219 | case SM_SUN3|SM_3_260: | ||
220 | break; | ||
221 | #else | ||
199 | case SM_SUN3|SM_3_50: | 222 | case SM_SUN3|SM_3_50: |
200 | case SM_SUN3|SM_3_60: | 223 | case SM_SUN3|SM_3_60: |
201 | break; | 224 | break; |
225 | #endif | ||
202 | 226 | ||
203 | default: | 227 | default: |
204 | return 0; | 228 | return 0; |
@@ -207,7 +231,11 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
207 | if(called) | 231 | if(called) |
208 | return 0; | 232 | return 0; |
209 | 233 | ||
234 | #ifdef SUN3_SCSI_VME | ||
235 | tpnt->proc_name = "Sun3 5380 VME SCSI"; | ||
236 | #else | ||
210 | tpnt->proc_name = "Sun3 5380 SCSI"; | 237 | tpnt->proc_name = "Sun3 5380 SCSI"; |
238 | #endif | ||
211 | 239 | ||
212 | /* setup variables */ | 240 | /* setup variables */ |
213 | tpnt->can_queue = | 241 | tpnt->can_queue = |
@@ -224,6 +252,38 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
224 | tpnt->this_id = 7; | 252 | tpnt->this_id = 7; |
225 | } | 253 | } |
226 | 254 | ||
255 | #ifdef SUN3_SCSI_VME | ||
256 | ioaddr = 0; | ||
257 | for (i = 0; addrs[i] != 0; i++) { | ||
258 | unsigned char x; | ||
259 | |||
260 | ioaddr = (unsigned long)sun3_ioremap(addrs[i], PAGE_SIZE, | ||
261 | SUN3_PAGE_TYPE_VME16); | ||
262 | irq = vecs[i]; | ||
263 | sun3_scsi_regp = (unsigned char *)ioaddr; | ||
264 | |||
265 | dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8); | ||
266 | |||
267 | if (sun3_map_test((unsigned long)dregs, &x)) { | ||
268 | unsigned short oldcsr; | ||
269 | |||
270 | oldcsr = dregs->csr; | ||
271 | dregs->csr = 0; | ||
272 | udelay(SUN3_DMA_DELAY); | ||
273 | if (dregs->csr == 0x1400) | ||
274 | break; | ||
275 | |||
276 | dregs->csr = oldcsr; | ||
277 | } | ||
278 | |||
279 | iounmap((void *)ioaddr); | ||
280 | ioaddr = 0; | ||
281 | } | ||
282 | |||
283 | if (!ioaddr) | ||
284 | return 0; | ||
285 | #else | ||
286 | irq = IRQ_SUN3_SCSI; | ||
227 | ioaddr = (unsigned long)ioremap(IOBASE_SUN3_SCSI, PAGE_SIZE); | 287 | ioaddr = (unsigned long)ioremap(IOBASE_SUN3_SCSI, PAGE_SIZE); |
228 | sun3_scsi_regp = (unsigned char *)ioaddr; | 288 | sun3_scsi_regp = (unsigned char *)ioaddr; |
229 | 289 | ||
@@ -234,11 +294,6 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
234 | printk("SUN3 Scsi couldn't allocate DVMA memory!\n"); | 294 | printk("SUN3 Scsi couldn't allocate DVMA memory!\n"); |
235 | return 0; | 295 | return 0; |
236 | } | 296 | } |
237 | #ifdef OLDDMA | ||
238 | if((dmabuf = dvma_malloc_align(SUN3_DVMA_BUFSIZE, 0x10000)) == NULL) { | ||
239 | printk("SUN3 Scsi couldn't allocate DVMA memory!\n"); | ||
240 | return 0; | ||
241 | } | ||
242 | #endif | 297 | #endif |
243 | #ifdef SUPPORT_TAGS | 298 | #ifdef SUPPORT_TAGS |
244 | if (setup_use_tagged_queuing < 0) | 299 | if (setup_use_tagged_queuing < 0) |
@@ -252,7 +307,7 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
252 | default_instance = instance; | 307 | default_instance = instance; |
253 | 308 | ||
254 | instance->io_port = (unsigned long) ioaddr; | 309 | instance->io_port = (unsigned long) ioaddr; |
255 | instance->irq = IRQ_SUN3_SCSI; | 310 | instance->irq = irq; |
256 | 311 | ||
257 | NCR5380_init(instance, 0); | 312 | NCR5380_init(instance, 0); |
258 | 313 | ||
@@ -273,7 +328,8 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
273 | #endif | 328 | #endif |
274 | } | 329 | } |
275 | 330 | ||
276 | printk("scsi%d: Sun3 5380 at port %lX irq", instance->host_no, instance->io_port); | 331 | pr_info("scsi%d: %s at port %lX irq", instance->host_no, |
332 | tpnt->proc_name, instance->io_port); | ||
277 | if (instance->irq == SCSI_IRQ_NONE) | 333 | if (instance->irq == SCSI_IRQ_NONE) |
278 | printk ("s disabled"); | 334 | printk ("s disabled"); |
279 | else | 335 | else |
@@ -290,6 +346,15 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
290 | dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR; | 346 | dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR; |
291 | udelay(SUN3_DMA_DELAY); | 347 | udelay(SUN3_DMA_DELAY); |
292 | dregs->fifo_count = 0; | 348 | dregs->fifo_count = 0; |
349 | #ifdef SUN3_SCSI_VME | ||
350 | dregs->fifo_count_hi = 0; | ||
351 | dregs->dma_addr_hi = 0; | ||
352 | dregs->dma_addr_lo = 0; | ||
353 | dregs->dma_count_hi = 0; | ||
354 | dregs->dma_count_lo = 0; | ||
355 | |||
356 | dregs->ivect = VME_DATA24 | (instance->irq & 0xff); | ||
357 | #endif | ||
293 | 358 | ||
294 | called = 1; | 359 | called = 1; |
295 | 360 | ||
@@ -357,7 +422,8 @@ static void sun3_scsi_reset_boot(struct Scsi_Host *instance) | |||
357 | } | 422 | } |
358 | #endif | 423 | #endif |
359 | 424 | ||
360 | const char * sun3scsi_info (struct Scsi_Host *spnt) { | 425 | static const char *sun3scsi_info(struct Scsi_Host *spnt) |
426 | { | ||
361 | return ""; | 427 | return ""; |
362 | } | 428 | } |
363 | 429 | ||
@@ -369,6 +435,10 @@ static irqreturn_t scsi_sun3_intr(int irq, void *dummy) | |||
369 | unsigned short csr = dregs->csr; | 435 | unsigned short csr = dregs->csr; |
370 | int handled = 0; | 436 | int handled = 0; |
371 | 437 | ||
438 | #ifdef SUN3_SCSI_VME | ||
439 | dregs->csr &= ~CSR_DMA_ENABLE; | ||
440 | #endif | ||
441 | |||
372 | if(csr & ~CSR_GOOD) { | 442 | if(csr & ~CSR_GOOD) { |
373 | if(csr & CSR_DMA_BUSERR) { | 443 | if(csr & CSR_DMA_BUSERR) { |
374 | printk("scsi%d: bus error in dma\n", default_instance->host_no); | 444 | printk("scsi%d: bus error in dma\n", default_instance->host_no); |
@@ -412,31 +482,28 @@ void sun3_sun3_debug (void) | |||
412 | /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ | 482 | /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ |
413 | static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag) | 483 | static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag) |
414 | { | 484 | { |
415 | #ifdef OLDDMA | ||
416 | if(write_flag) | ||
417 | memcpy(dmabuf, data, count); | ||
418 | else { | ||
419 | sun3_dma_orig_addr = data; | ||
420 | sun3_dma_orig_count = count; | ||
421 | } | ||
422 | #else | ||
423 | void *addr; | 485 | void *addr; |
424 | 486 | ||
425 | if(sun3_dma_orig_addr != NULL) | 487 | if(sun3_dma_orig_addr != NULL) |
426 | dvma_unmap(sun3_dma_orig_addr); | 488 | dvma_unmap(sun3_dma_orig_addr); |
427 | 489 | ||
428 | // addr = sun3_dvma_page((unsigned long)data, (unsigned long)dmabuf); | 490 | #ifdef SUN3_SCSI_VME |
491 | addr = (void *)dvma_map_vme((unsigned long) data, count); | ||
492 | #else | ||
429 | addr = (void *)dvma_map((unsigned long) data, count); | 493 | addr = (void *)dvma_map((unsigned long) data, count); |
494 | #endif | ||
430 | 495 | ||
431 | sun3_dma_orig_addr = addr; | 496 | sun3_dma_orig_addr = addr; |
432 | sun3_dma_orig_count = count; | 497 | sun3_dma_orig_count = count; |
433 | #endif | 498 | |
499 | #ifndef SUN3_SCSI_VME | ||
434 | dregs->fifo_count = 0; | 500 | dregs->fifo_count = 0; |
435 | sun3_udc_write(UDC_RESET, UDC_CSR); | 501 | sun3_udc_write(UDC_RESET, UDC_CSR); |
436 | 502 | ||
437 | /* reset fifo */ | 503 | /* reset fifo */ |
438 | dregs->csr &= ~CSR_FIFO; | 504 | dregs->csr &= ~CSR_FIFO; |
439 | dregs->csr |= CSR_FIFO; | 505 | dregs->csr |= CSR_FIFO; |
506 | #endif | ||
440 | 507 | ||
441 | /* set direction */ | 508 | /* set direction */ |
442 | if(write_flag) | 509 | if(write_flag) |
@@ -444,6 +511,17 @@ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int wri | |||
444 | else | 511 | else |
445 | dregs->csr &= ~CSR_SEND; | 512 | dregs->csr &= ~CSR_SEND; |
446 | 513 | ||
514 | #ifdef SUN3_SCSI_VME | ||
515 | dregs->csr |= CSR_PACK_ENABLE; | ||
516 | |||
517 | dregs->dma_addr_hi = ((unsigned long)addr >> 16); | ||
518 | dregs->dma_addr_lo = ((unsigned long)addr & 0xffff); | ||
519 | |||
520 | dregs->dma_count_hi = 0; | ||
521 | dregs->dma_count_lo = 0; | ||
522 | dregs->fifo_count_hi = 0; | ||
523 | dregs->fifo_count = 0; | ||
524 | #else | ||
447 | /* byte count for fifo */ | 525 | /* byte count for fifo */ |
448 | dregs->fifo_count = count; | 526 | dregs->fifo_count = count; |
449 | 527 | ||
@@ -461,13 +539,8 @@ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int wri | |||
461 | } | 539 | } |
462 | 540 | ||
463 | /* setup udc */ | 541 | /* setup udc */ |
464 | #ifdef OLDDMA | ||
465 | udc_regs->addr_hi = ((dvma_vtob(dmabuf) & 0xff0000) >> 8); | ||
466 | udc_regs->addr_lo = (dvma_vtob(dmabuf) & 0xffff); | ||
467 | #else | ||
468 | udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8); | 542 | udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8); |
469 | udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff); | 543 | udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff); |
470 | #endif | ||
471 | udc_regs->count = count/2; /* count in words */ | 544 | udc_regs->count = count/2; /* count in words */ |
472 | udc_regs->mode_hi = UDC_MODE_HIWORD; | 545 | udc_regs->mode_hi = UDC_MODE_HIWORD; |
473 | if(write_flag) { | 546 | if(write_flag) { |
@@ -491,11 +564,13 @@ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int wri | |||
491 | 564 | ||
492 | /* interrupt enable */ | 565 | /* interrupt enable */ |
493 | sun3_udc_write(UDC_INT_ENABLE, UDC_CSR); | 566 | sun3_udc_write(UDC_INT_ENABLE, UDC_CSR); |
567 | #endif | ||
494 | 568 | ||
495 | return count; | 569 | return count; |
496 | 570 | ||
497 | } | 571 | } |
498 | 572 | ||
573 | #ifndef SUN3_SCSI_VME | ||
499 | static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance) | 574 | static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance) |
500 | { | 575 | { |
501 | unsigned short resid; | 576 | unsigned short resid; |
@@ -508,6 +583,7 @@ static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance) | |||
508 | 583 | ||
509 | return (unsigned long) resid; | 584 | return (unsigned long) resid; |
510 | } | 585 | } |
586 | #endif | ||
511 | 587 | ||
512 | static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) | 588 | static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) |
513 | { | 589 | { |
@@ -526,8 +602,23 @@ static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, | |||
526 | 602 | ||
527 | static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data) | 603 | static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data) |
528 | { | 604 | { |
605 | #ifdef SUN3_SCSI_VME | ||
606 | unsigned short csr; | ||
607 | |||
608 | csr = dregs->csr; | ||
609 | |||
610 | dregs->dma_count_hi = (sun3_dma_orig_count >> 16); | ||
611 | dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff); | ||
529 | 612 | ||
613 | dregs->fifo_count_hi = (sun3_dma_orig_count >> 16); | ||
614 | dregs->fifo_count = (sun3_dma_orig_count & 0xffff); | ||
615 | |||
616 | /* if(!(csr & CSR_DMA_ENABLE)) | ||
617 | * dregs->csr |= CSR_DMA_ENABLE; | ||
618 | */ | ||
619 | #else | ||
530 | sun3_udc_write(UDC_CHN_START, UDC_CSR); | 620 | sun3_udc_write(UDC_CHN_START, UDC_CSR); |
621 | #endif | ||
531 | 622 | ||
532 | return 0; | 623 | return 0; |
533 | } | 624 | } |
@@ -535,12 +626,46 @@ static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data) | |||
535 | /* clean up after our dma is done */ | 626 | /* clean up after our dma is done */ |
536 | static int sun3scsi_dma_finish(int write_flag) | 627 | static int sun3scsi_dma_finish(int write_flag) |
537 | { | 628 | { |
538 | unsigned short count; | 629 | unsigned short __maybe_unused count; |
539 | unsigned short fifo; | 630 | unsigned short fifo; |
540 | int ret = 0; | 631 | int ret = 0; |
541 | 632 | ||
542 | sun3_dma_active = 0; | 633 | sun3_dma_active = 0; |
543 | #if 1 | 634 | |
635 | #ifdef SUN3_SCSI_VME | ||
636 | dregs->csr &= ~CSR_DMA_ENABLE; | ||
637 | |||
638 | fifo = dregs->fifo_count; | ||
639 | if (write_flag) { | ||
640 | if ((fifo > 0) && (fifo < sun3_dma_orig_count)) | ||
641 | fifo++; | ||
642 | } | ||
643 | |||
644 | last_residual = fifo; | ||
645 | /* empty bytes from the fifo which didn't make it */ | ||
646 | if ((!write_flag) && (dregs->csr & CSR_LEFT)) { | ||
647 | unsigned char *vaddr; | ||
648 | |||
649 | vaddr = (unsigned char *)dvma_vmetov(sun3_dma_orig_addr); | ||
650 | |||
651 | vaddr += (sun3_dma_orig_count - fifo); | ||
652 | vaddr--; | ||
653 | |||
654 | switch (dregs->csr & CSR_LEFT) { | ||
655 | case CSR_LEFT_3: | ||
656 | *vaddr = (dregs->bpack_lo & 0xff00) >> 8; | ||
657 | vaddr--; | ||
658 | |||
659 | case CSR_LEFT_2: | ||
660 | *vaddr = (dregs->bpack_hi & 0x00ff); | ||
661 | vaddr--; | ||
662 | |||
663 | case CSR_LEFT_1: | ||
664 | *vaddr = (dregs->bpack_hi & 0xff00) >> 8; | ||
665 | break; | ||
666 | } | ||
667 | } | ||
668 | #else | ||
544 | // check to empty the fifo on a read | 669 | // check to empty the fifo on a read |
545 | if(!write_flag) { | 670 | if(!write_flag) { |
546 | int tmo = 20000; /* .2 sec */ | 671 | int tmo = 20000; /* .2 sec */ |
@@ -556,28 +681,8 @@ static int sun3scsi_dma_finish(int write_flag) | |||
556 | udelay(10); | 681 | udelay(10); |
557 | } | 682 | } |
558 | } | 683 | } |
559 | |||
560 | #endif | ||
561 | 684 | ||
562 | count = sun3scsi_dma_count(default_instance); | 685 | count = sun3scsi_dma_count(default_instance); |
563 | #ifdef OLDDMA | ||
564 | |||
565 | /* if we've finished a read, copy out the data we read */ | ||
566 | if(sun3_dma_orig_addr) { | ||
567 | /* check for residual bytes after dma end */ | ||
568 | if(count && (NCR5380_read(BUS_AND_STATUS_REG) & | ||
569 | (BASR_PHASE_MATCH | BASR_ACK))) { | ||
570 | printk("scsi%d: sun3_scsi_finish: read overrun baby... ", default_instance->host_no); | ||
571 | printk("basr now %02x\n", NCR5380_read(BUS_AND_STATUS_REG)); | ||
572 | ret = count; | ||
573 | } | ||
574 | |||
575 | /* copy in what we dma'd no matter what */ | ||
576 | memcpy(sun3_dma_orig_addr, dmabuf, sun3_dma_orig_count); | ||
577 | sun3_dma_orig_addr = NULL; | ||
578 | |||
579 | } | ||
580 | #else | ||
581 | 686 | ||
582 | fifo = dregs->fifo_count; | 687 | fifo = dregs->fifo_count; |
583 | last_residual = fifo; | 688 | last_residual = fifo; |
@@ -595,10 +700,23 @@ static int sun3scsi_dma_finish(int write_flag) | |||
595 | vaddr[-2] = (data & 0xff00) >> 8; | 700 | vaddr[-2] = (data & 0xff00) >> 8; |
596 | vaddr[-1] = (data & 0xff); | 701 | vaddr[-1] = (data & 0xff); |
597 | } | 702 | } |
703 | #endif | ||
598 | 704 | ||
599 | dvma_unmap(sun3_dma_orig_addr); | 705 | dvma_unmap(sun3_dma_orig_addr); |
600 | sun3_dma_orig_addr = NULL; | 706 | sun3_dma_orig_addr = NULL; |
601 | #endif | 707 | |
708 | #ifdef SUN3_SCSI_VME | ||
709 | dregs->dma_addr_hi = 0; | ||
710 | dregs->dma_addr_lo = 0; | ||
711 | dregs->dma_count_hi = 0; | ||
712 | dregs->dma_count_lo = 0; | ||
713 | |||
714 | dregs->fifo_count = 0; | ||
715 | dregs->fifo_count_hi = 0; | ||
716 | |||
717 | dregs->csr &= ~CSR_SEND; | ||
718 | /* dregs->csr |= CSR_DMA_ENABLE; */ | ||
719 | #else | ||
602 | sun3_udc_write(UDC_RESET, UDC_CSR); | 720 | sun3_udc_write(UDC_RESET, UDC_CSR); |
603 | dregs->fifo_count = 0; | 721 | dregs->fifo_count = 0; |
604 | dregs->csr &= ~CSR_SEND; | 722 | dregs->csr &= ~CSR_SEND; |
@@ -606,6 +724,7 @@ static int sun3scsi_dma_finish(int write_flag) | |||
606 | /* reset fifo */ | 724 | /* reset fifo */ |
607 | dregs->csr &= ~CSR_FIFO; | 725 | dregs->csr &= ~CSR_FIFO; |
608 | dregs->csr |= CSR_FIFO; | 726 | dregs->csr |= CSR_FIFO; |
727 | #endif | ||
609 | 728 | ||
610 | sun3_dma_setup_done = NULL; | 729 | sun3_dma_setup_done = NULL; |
611 | 730 | ||
diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c index 9e7974b56f12..1eeece6e2040 100644 --- a/drivers/scsi/sun3_scsi_vme.c +++ b/drivers/scsi/sun3_scsi_vme.c | |||
@@ -1,584 +1,3 @@ | |||
1 | /* | ||
2 | * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl) | ||
3 | * | ||
4 | * Sun3 DMA routines added by Sam Creasey (sammy@sammy.net) | ||
5 | * | ||
6 | * VME support added by Sam Creasey | ||
7 | * | ||
8 | * Adapted from sun3_scsi.c -- see there for other headers | ||
9 | * | ||
10 | * TODO: modify this driver to support multiple Sun3 SCSI VME boards | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #define AUTOSENSE | ||
15 | |||
16 | #include <linux/types.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/ctype.h> | ||
19 | #include <linux/delay.h> | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/signal.h> | ||
23 | #include <linux/ioport.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/blkdev.h> | ||
26 | |||
27 | #include <asm/io.h> | ||
28 | |||
29 | #include <asm/sun3ints.h> | ||
30 | #include <asm/dvma.h> | ||
31 | #include <asm/idprom.h> | ||
32 | #include <asm/machines.h> | ||
33 | |||
34 | #define SUN3_SCSI_VME | 1 | #define SUN3_SCSI_VME |
35 | 2 | ||
36 | #undef SUN3_SCSI_DEBUG | 3 | #include "sun3_scsi.c" |
37 | |||
38 | /* dma on! */ | ||
39 | #define REAL_DMA | ||
40 | |||
41 | #include "scsi.h" | ||
42 | #include "initio.h" | ||
43 | #include <scsi/scsi_host.h> | ||
44 | #include "sun3_scsi.h" | ||
45 | #include "NCR5380.h" | ||
46 | |||
47 | extern int sun3_map_test(unsigned long, char *); | ||
48 | |||
49 | #define USE_WRAPPER | ||
50 | /*#define RESET_BOOT */ | ||
51 | #define DRIVER_SETUP | ||
52 | |||
53 | /* | ||
54 | * BUG can be used to trigger a strange code-size related hang on 2.1 kernels | ||
55 | */ | ||
56 | #ifdef BUG | ||
57 | #undef RESET_BOOT | ||
58 | #undef DRIVER_SETUP | ||
59 | #endif | ||
60 | |||
61 | /* #define SUPPORT_TAGS */ | ||
62 | |||
63 | //#define ENABLE_IRQ() enable_irq( SUN3_VEC_VMESCSI0 ); | ||
64 | #define ENABLE_IRQ() | ||
65 | |||
66 | |||
67 | static irqreturn_t scsi_sun3_intr(int irq, void *dummy); | ||
68 | static inline unsigned char sun3scsi_read(int reg); | ||
69 | static inline void sun3scsi_write(int reg, int value); | ||
70 | |||
71 | static int setup_can_queue = -1; | ||
72 | module_param(setup_can_queue, int, 0); | ||
73 | static int setup_cmd_per_lun = -1; | ||
74 | module_param(setup_cmd_per_lun, int, 0); | ||
75 | static int setup_sg_tablesize = -1; | ||
76 | module_param(setup_sg_tablesize, int, 0); | ||
77 | #ifdef SUPPORT_TAGS | ||
78 | static int setup_use_tagged_queuing = -1; | ||
79 | module_param(setup_use_tagged_queuing, int, 0); | ||
80 | #endif | ||
81 | static int setup_hostid = -1; | ||
82 | module_param(setup_hostid, int, 0); | ||
83 | |||
84 | static struct scsi_cmnd *sun3_dma_setup_done = NULL; | ||
85 | |||
86 | #define AFTER_RESET_DELAY (HZ/2) | ||
87 | |||
88 | /* ms to wait after hitting dma regs */ | ||
89 | #define SUN3_DMA_DELAY 10 | ||
90 | |||
91 | /* dvma buffer to allocate -- 32k should hopefully be more than sufficient */ | ||
92 | #define SUN3_DVMA_BUFSIZE 0xe000 | ||
93 | |||
94 | /* minimum number of bytes to do dma on */ | ||
95 | #define SUN3_DMA_MINSIZE 128 | ||
96 | |||
97 | static volatile unsigned char *sun3_scsi_regp; | ||
98 | static volatile struct sun3_dma_regs *dregs; | ||
99 | #ifdef OLDDMA | ||
100 | static unsigned char *dmabuf = NULL; /* dma memory buffer */ | ||
101 | #endif | ||
102 | static unsigned char *sun3_dma_orig_addr = NULL; | ||
103 | static unsigned long sun3_dma_orig_count = 0; | ||
104 | static int sun3_dma_active = 0; | ||
105 | static unsigned long last_residual = 0; | ||
106 | |||
107 | /* | ||
108 | * NCR 5380 register access functions | ||
109 | */ | ||
110 | |||
111 | static inline unsigned char sun3scsi_read(int reg) | ||
112 | { | ||
113 | return( sun3_scsi_regp[reg] ); | ||
114 | } | ||
115 | |||
116 | static inline void sun3scsi_write(int reg, int value) | ||
117 | { | ||
118 | sun3_scsi_regp[reg] = value; | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * XXX: status debug | ||
123 | */ | ||
124 | static struct Scsi_Host *default_instance; | ||
125 | |||
126 | /* | ||
127 | * Function : int sun3scsi_detect(struct scsi_host_template * tpnt) | ||
128 | * | ||
129 | * Purpose : initializes mac NCR5380 driver based on the | ||
130 | * command line / compile time port and irq definitions. | ||
131 | * | ||
132 | * Inputs : tpnt - template for this SCSI adapter. | ||
133 | * | ||
134 | * Returns : 1 if a host adapter was found, 0 if not. | ||
135 | * | ||
136 | */ | ||
137 | |||
138 | static int __init sun3scsi_detect(struct scsi_host_template * tpnt) | ||
139 | { | ||
140 | unsigned long ioaddr, irq = 0; | ||
141 | static int called = 0; | ||
142 | struct Scsi_Host *instance; | ||
143 | int i; | ||
144 | unsigned long addrs[3] = { IOBASE_SUN3_VMESCSI, | ||
145 | IOBASE_SUN3_VMESCSI + 0x4000, | ||
146 | 0 }; | ||
147 | unsigned long vecs[3] = { SUN3_VEC_VMESCSI0, | ||
148 | SUN3_VEC_VMESCSI1, | ||
149 | 0 }; | ||
150 | /* check that this machine has an onboard 5380 */ | ||
151 | switch(idprom->id_machtype) { | ||
152 | case SM_SUN3|SM_3_160: | ||
153 | case SM_SUN3|SM_3_260: | ||
154 | break; | ||
155 | |||
156 | default: | ||
157 | return 0; | ||
158 | } | ||
159 | |||
160 | if(called) | ||
161 | return 0; | ||
162 | |||
163 | tpnt->proc_name = "Sun3 5380 VME SCSI"; | ||
164 | |||
165 | /* setup variables */ | ||
166 | tpnt->can_queue = | ||
167 | (setup_can_queue > 0) ? setup_can_queue : CAN_QUEUE; | ||
168 | tpnt->cmd_per_lun = | ||
169 | (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : CMD_PER_LUN; | ||
170 | tpnt->sg_tablesize = | ||
171 | (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_TABLESIZE; | ||
172 | |||
173 | if (setup_hostid >= 0) | ||
174 | tpnt->this_id = setup_hostid; | ||
175 | else { | ||
176 | /* use 7 as default */ | ||
177 | tpnt->this_id = 7; | ||
178 | } | ||
179 | |||
180 | ioaddr = 0; | ||
181 | for(i = 0; addrs[i] != 0; i++) { | ||
182 | unsigned char x; | ||
183 | |||
184 | ioaddr = (unsigned long)sun3_ioremap(addrs[i], PAGE_SIZE, | ||
185 | SUN3_PAGE_TYPE_VME16); | ||
186 | irq = vecs[i]; | ||
187 | sun3_scsi_regp = (unsigned char *)ioaddr; | ||
188 | |||
189 | dregs = (struct sun3_dma_regs *)(((unsigned char *)ioaddr) + 8); | ||
190 | |||
191 | if(sun3_map_test((unsigned long)dregs, &x)) { | ||
192 | unsigned short oldcsr; | ||
193 | |||
194 | oldcsr = dregs->csr; | ||
195 | dregs->csr = 0; | ||
196 | udelay(SUN3_DMA_DELAY); | ||
197 | if(dregs->csr == 0x1400) | ||
198 | break; | ||
199 | |||
200 | dregs->csr = oldcsr; | ||
201 | } | ||
202 | |||
203 | iounmap((void *)ioaddr); | ||
204 | ioaddr = 0; | ||
205 | } | ||
206 | |||
207 | if(!ioaddr) | ||
208 | return 0; | ||
209 | |||
210 | #ifdef SUPPORT_TAGS | ||
211 | if (setup_use_tagged_queuing < 0) | ||
212 | setup_use_tagged_queuing = USE_TAGGED_QUEUING; | ||
213 | #endif | ||
214 | |||
215 | instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); | ||
216 | if(instance == NULL) | ||
217 | return 0; | ||
218 | |||
219 | default_instance = instance; | ||
220 | |||
221 | instance->io_port = (unsigned long) ioaddr; | ||
222 | instance->irq = irq; | ||
223 | |||
224 | NCR5380_init(instance, 0); | ||
225 | |||
226 | instance->n_io_port = 32; | ||
227 | |||
228 | ((struct NCR5380_hostdata *)instance->hostdata)->ctrl = 0; | ||
229 | |||
230 | if (request_irq(instance->irq, scsi_sun3_intr, | ||
231 | 0, "Sun3SCSI-5380VME", instance)) { | ||
232 | #ifndef REAL_DMA | ||
233 | printk("scsi%d: IRQ%d not free, interrupts disabled\n", | ||
234 | instance->host_no, instance->irq); | ||
235 | instance->irq = SCSI_IRQ_NONE; | ||
236 | #else | ||
237 | printk("scsi%d: IRQ%d not free, bailing out\n", | ||
238 | instance->host_no, instance->irq); | ||
239 | return 0; | ||
240 | #endif | ||
241 | } | ||
242 | |||
243 | printk("scsi%d: Sun3 5380 VME at port %lX irq", instance->host_no, instance->io_port); | ||
244 | if (instance->irq == SCSI_IRQ_NONE) | ||
245 | printk ("s disabled"); | ||
246 | else | ||
247 | printk (" %d", instance->irq); | ||
248 | printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", | ||
249 | instance->can_queue, instance->cmd_per_lun, | ||
250 | SUN3SCSI_PUBLIC_RELEASE); | ||
251 | printk("\nscsi%d:", instance->host_no); | ||
252 | NCR5380_print_options(instance); | ||
253 | printk("\n"); | ||
254 | |||
255 | dregs->csr = 0; | ||
256 | udelay(SUN3_DMA_DELAY); | ||
257 | dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR; | ||
258 | udelay(SUN3_DMA_DELAY); | ||
259 | dregs->fifo_count = 0; | ||
260 | dregs->fifo_count_hi = 0; | ||
261 | dregs->dma_addr_hi = 0; | ||
262 | dregs->dma_addr_lo = 0; | ||
263 | dregs->dma_count_hi = 0; | ||
264 | dregs->dma_count_lo = 0; | ||
265 | |||
266 | dregs->ivect = VME_DATA24 | (instance->irq & 0xff); | ||
267 | |||
268 | called = 1; | ||
269 | |||
270 | #ifdef RESET_BOOT | ||
271 | sun3_scsi_reset_boot(instance); | ||
272 | #endif | ||
273 | |||
274 | return 1; | ||
275 | } | ||
276 | |||
277 | int sun3scsi_release (struct Scsi_Host *shpnt) | ||
278 | { | ||
279 | if (shpnt->irq != SCSI_IRQ_NONE) | ||
280 | free_irq(shpnt->irq, shpnt); | ||
281 | |||
282 | iounmap((void *)sun3_scsi_regp); | ||
283 | |||
284 | NCR5380_exit(shpnt); | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | #ifdef RESET_BOOT | ||
289 | /* | ||
290 | * Our 'bus reset on boot' function | ||
291 | */ | ||
292 | |||
293 | static void sun3_scsi_reset_boot(struct Scsi_Host *instance) | ||
294 | { | ||
295 | unsigned long end; | ||
296 | |||
297 | NCR5380_local_declare(); | ||
298 | NCR5380_setup(instance); | ||
299 | |||
300 | /* | ||
301 | * Do a SCSI reset to clean up the bus during initialization. No | ||
302 | * messing with the queues, interrupts, or locks necessary here. | ||
303 | */ | ||
304 | |||
305 | printk( "Sun3 SCSI: resetting the SCSI bus..." ); | ||
306 | |||
307 | /* switch off SCSI IRQ - catch an interrupt without IRQ bit set else */ | ||
308 | // sun3_disable_irq( IRQ_SUN3_SCSI ); | ||
309 | |||
310 | /* get in phase */ | ||
311 | NCR5380_write( TARGET_COMMAND_REG, | ||
312 | PHASE_SR_TO_TCR( NCR5380_read(STATUS_REG) )); | ||
313 | |||
314 | /* assert RST */ | ||
315 | NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST ); | ||
316 | |||
317 | /* The min. reset hold time is 25us, so 40us should be enough */ | ||
318 | udelay( 50 ); | ||
319 | |||
320 | /* reset RST and interrupt */ | ||
321 | NCR5380_write( INITIATOR_COMMAND_REG, ICR_BASE ); | ||
322 | NCR5380_read( RESET_PARITY_INTERRUPT_REG ); | ||
323 | |||
324 | for( end = jiffies + AFTER_RESET_DELAY; time_before(jiffies, end); ) | ||
325 | barrier(); | ||
326 | |||
327 | /* switch on SCSI IRQ again */ | ||
328 | // sun3_enable_irq( IRQ_SUN3_SCSI ); | ||
329 | |||
330 | printk( " done\n" ); | ||
331 | } | ||
332 | #endif | ||
333 | |||
334 | static const char * sun3scsi_info (struct Scsi_Host *spnt) { | ||
335 | return ""; | ||
336 | } | ||
337 | |||
338 | // safe bits for the CSR | ||
339 | #define CSR_GOOD 0x060f | ||
340 | |||
341 | static irqreturn_t scsi_sun3_intr(int irq, void *dummy) | ||
342 | { | ||
343 | unsigned short csr = dregs->csr; | ||
344 | int handled = 0; | ||
345 | |||
346 | dregs->csr &= ~CSR_DMA_ENABLE; | ||
347 | |||
348 | |||
349 | #ifdef SUN3_SCSI_DEBUG | ||
350 | printk("scsi_intr csr %x\n", csr); | ||
351 | #endif | ||
352 | |||
353 | if(csr & ~CSR_GOOD) { | ||
354 | if(csr & CSR_DMA_BUSERR) { | ||
355 | printk("scsi%d: bus error in dma\n", default_instance->host_no); | ||
356 | #ifdef SUN3_SCSI_DEBUG | ||
357 | printk("scsi: residual %x count %x addr %p dmaaddr %x\n", | ||
358 | dregs->fifo_count, | ||
359 | dregs->dma_count_lo | (dregs->dma_count_hi << 16), | ||
360 | sun3_dma_orig_addr, | ||
361 | dregs->dma_addr_lo | (dregs->dma_addr_hi << 16)); | ||
362 | #endif | ||
363 | } | ||
364 | |||
365 | if(csr & CSR_DMA_CONFLICT) { | ||
366 | printk("scsi%d: dma conflict\n", default_instance->host_no); | ||
367 | } | ||
368 | handled = 1; | ||
369 | } | ||
370 | |||
371 | if(csr & (CSR_SDB_INT | CSR_DMA_INT)) { | ||
372 | NCR5380_intr(irq, dummy); | ||
373 | handled = 1; | ||
374 | } | ||
375 | |||
376 | return IRQ_RETVAL(handled); | ||
377 | } | ||
378 | |||
379 | /* | ||
380 | * Debug stuff - to be called on NMI, or sysrq key. Use at your own risk; | ||
381 | * reentering NCR5380_print_status seems to have ugly side effects | ||
382 | */ | ||
383 | |||
384 | /* this doesn't seem to get used at all -- sam */ | ||
385 | #if 0 | ||
386 | void sun3_sun3_debug (void) | ||
387 | { | ||
388 | unsigned long flags; | ||
389 | NCR5380_local_declare(); | ||
390 | |||
391 | if (default_instance) { | ||
392 | local_irq_save(flags); | ||
393 | NCR5380_print_status(default_instance); | ||
394 | local_irq_restore(flags); | ||
395 | } | ||
396 | } | ||
397 | #endif | ||
398 | |||
399 | |||
400 | /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ | ||
401 | static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int write_flag) | ||
402 | { | ||
403 | void *addr; | ||
404 | |||
405 | if(sun3_dma_orig_addr != NULL) | ||
406 | dvma_unmap(sun3_dma_orig_addr); | ||
407 | |||
408 | // addr = sun3_dvma_page((unsigned long)data, (unsigned long)dmabuf); | ||
409 | addr = (void *)dvma_map_vme((unsigned long) data, count); | ||
410 | |||
411 | sun3_dma_orig_addr = addr; | ||
412 | sun3_dma_orig_count = count; | ||
413 | |||
414 | #ifdef SUN3_SCSI_DEBUG | ||
415 | printk("scsi: dma_setup addr %p count %x\n", addr, count); | ||
416 | #endif | ||
417 | |||
418 | // dregs->fifo_count = 0; | ||
419 | #if 0 | ||
420 | /* reset fifo */ | ||
421 | dregs->csr &= ~CSR_FIFO; | ||
422 | dregs->csr |= CSR_FIFO; | ||
423 | #endif | ||
424 | /* set direction */ | ||
425 | if(write_flag) | ||
426 | dregs->csr |= CSR_SEND; | ||
427 | else | ||
428 | dregs->csr &= ~CSR_SEND; | ||
429 | |||
430 | /* reset fifo */ | ||
431 | // dregs->csr &= ~CSR_FIFO; | ||
432 | // dregs->csr |= CSR_FIFO; | ||
433 | |||
434 | dregs->csr |= CSR_PACK_ENABLE; | ||
435 | |||
436 | dregs->dma_addr_hi = ((unsigned long)addr >> 16); | ||
437 | dregs->dma_addr_lo = ((unsigned long)addr & 0xffff); | ||
438 | |||
439 | dregs->dma_count_hi = 0; | ||
440 | dregs->dma_count_lo = 0; | ||
441 | dregs->fifo_count_hi = 0; | ||
442 | dregs->fifo_count = 0; | ||
443 | |||
444 | #ifdef SUN3_SCSI_DEBUG | ||
445 | printk("scsi: dma_setup done csr %x\n", dregs->csr); | ||
446 | #endif | ||
447 | return count; | ||
448 | |||
449 | } | ||
450 | |||
451 | static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) | ||
452 | { | ||
453 | return last_residual; | ||
454 | } | ||
455 | |||
456 | static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, | ||
457 | struct scsi_cmnd *cmd, | ||
458 | int write_flag) | ||
459 | { | ||
460 | if (cmd->request->cmd_type == REQ_TYPE_FS) | ||
461 | return wanted; | ||
462 | else | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static int sun3scsi_dma_start(unsigned long count, char *data) | ||
467 | { | ||
468 | |||
469 | unsigned short csr; | ||
470 | |||
471 | csr = dregs->csr; | ||
472 | #ifdef SUN3_SCSI_DEBUG | ||
473 | printk("scsi: dma_start data %p count %x csr %x fifo %x\n", data, count, csr, dregs->fifo_count); | ||
474 | #endif | ||
475 | |||
476 | dregs->dma_count_hi = (sun3_dma_orig_count >> 16); | ||
477 | dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff); | ||
478 | |||
479 | dregs->fifo_count_hi = (sun3_dma_orig_count >> 16); | ||
480 | dregs->fifo_count = (sun3_dma_orig_count & 0xffff); | ||
481 | |||
482 | // if(!(csr & CSR_DMA_ENABLE)) | ||
483 | // dregs->csr |= CSR_DMA_ENABLE; | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | /* clean up after our dma is done */ | ||
489 | static int sun3scsi_dma_finish(int write_flag) | ||
490 | { | ||
491 | unsigned short fifo; | ||
492 | int ret = 0; | ||
493 | |||
494 | sun3_dma_active = 0; | ||
495 | |||
496 | dregs->csr &= ~CSR_DMA_ENABLE; | ||
497 | |||
498 | fifo = dregs->fifo_count; | ||
499 | if(write_flag) { | ||
500 | if((fifo > 0) && (fifo < sun3_dma_orig_count)) | ||
501 | fifo++; | ||
502 | } | ||
503 | |||
504 | last_residual = fifo; | ||
505 | #ifdef SUN3_SCSI_DEBUG | ||
506 | printk("scsi: residual %x total %x\n", fifo, sun3_dma_orig_count); | ||
507 | #endif | ||
508 | /* empty bytes from the fifo which didn't make it */ | ||
509 | if((!write_flag) && (dregs->csr & CSR_LEFT)) { | ||
510 | unsigned char *vaddr; | ||
511 | |||
512 | #ifdef SUN3_SCSI_DEBUG | ||
513 | printk("scsi: got left over bytes\n"); | ||
514 | #endif | ||
515 | |||
516 | vaddr = (unsigned char *)dvma_vmetov(sun3_dma_orig_addr); | ||
517 | |||
518 | vaddr += (sun3_dma_orig_count - fifo); | ||
519 | vaddr--; | ||
520 | |||
521 | switch(dregs->csr & CSR_LEFT) { | ||
522 | case CSR_LEFT_3: | ||
523 | *vaddr = (dregs->bpack_lo & 0xff00) >> 8; | ||
524 | vaddr--; | ||
525 | |||
526 | case CSR_LEFT_2: | ||
527 | *vaddr = (dregs->bpack_hi & 0x00ff); | ||
528 | vaddr--; | ||
529 | |||
530 | case CSR_LEFT_1: | ||
531 | *vaddr = (dregs->bpack_hi & 0xff00) >> 8; | ||
532 | break; | ||
533 | } | ||
534 | |||
535 | |||
536 | } | ||
537 | |||
538 | dvma_unmap(sun3_dma_orig_addr); | ||
539 | sun3_dma_orig_addr = NULL; | ||
540 | |||
541 | dregs->dma_addr_hi = 0; | ||
542 | dregs->dma_addr_lo = 0; | ||
543 | dregs->dma_count_hi = 0; | ||
544 | dregs->dma_count_lo = 0; | ||
545 | |||
546 | dregs->fifo_count = 0; | ||
547 | dregs->fifo_count_hi = 0; | ||
548 | |||
549 | dregs->csr &= ~CSR_SEND; | ||
550 | |||
551 | // dregs->csr |= CSR_DMA_ENABLE; | ||
552 | |||
553 | #if 0 | ||
554 | /* reset fifo */ | ||
555 | dregs->csr &= ~CSR_FIFO; | ||
556 | dregs->csr |= CSR_FIFO; | ||
557 | #endif | ||
558 | sun3_dma_setup_done = NULL; | ||
559 | |||
560 | return ret; | ||
561 | |||
562 | } | ||
563 | |||
564 | #include "sun3_NCR5380.c" | ||
565 | |||
566 | static struct scsi_host_template driver_template = { | ||
567 | .name = SUN3_SCSI_NAME, | ||
568 | .detect = sun3scsi_detect, | ||
569 | .release = sun3scsi_release, | ||
570 | .info = sun3scsi_info, | ||
571 | .queuecommand = sun3scsi_queue_command, | ||
572 | .eh_abort_handler = sun3scsi_abort, | ||
573 | .eh_bus_reset_handler = sun3scsi_bus_reset, | ||
574 | .can_queue = CAN_QUEUE, | ||
575 | .this_id = 7, | ||
576 | .sg_tablesize = SG_TABLESIZE, | ||
577 | .cmd_per_lun = CMD_PER_LUN, | ||
578 | .use_clustering = DISABLE_CLUSTERING | ||
579 | }; | ||
580 | |||
581 | |||
582 | #include "scsi_module.c" | ||
583 | |||
584 | MODULE_LICENSE("GPL"); | ||