diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-09 21:54:06 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-09 21:54:06 -0400 |
| commit | 1c54fc1efe6922b4e7ffd591739d72050976ccd6 (patch) | |
| tree | 0f7f0eaa91fa06bba11da240915eb6a4040b482a /drivers/scsi/sun3_scsi.c | |
| parent | f4f9b8fc73f9aa93744f0e91e18f367d7766f523 (diff) | |
| parent | b4c43993f448d0e25fe40690d9e9c81a8ebda623 (diff) | |
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This patch consists of the usual driver updates (qla2xxx, qla4xxx,
lpfc, be2iscsi, fnic, ufs, NCR5380) The NCR5380 is the addition to
maintained status of a long neglected driver for older hardware. In
addition there are a lot of minor fixes and cleanups and some more
updates to make scsi mq ready"
* tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (130 commits)
include/scsi/osd_protocol.h: remove unnecessary __constant
mvsas: Recognise device/subsystem 9485/9485 as 88SE9485
Revert "be2iscsi: Fix processing cqe for cxn whose endpoint is freed"
mptfusion: fix msgContext in mptctl_hp_hostinfo
acornscsi: remove linked command support
scsi/NCR5380: dprintk macro
fusion: Remove use of DEF_SCSI_QCMD
fusion: Add free msg frames to the head, not tail of list
mpt2sas: Add free smids to the head, not tail of list
mpt2sas: Remove use of DEF_SCSI_QCMD
mpt2sas: Remove uses of serial_number
mpt3sas: Remove use of DEF_SCSI_QCMD
mpt3sas: Remove uses of serial_number
qla2xxx: Use kmemdup instead of kmalloc + memcpy
qla4xxx: Use kmemdup instead of kmalloc + memcpy
qla2xxx: fix incorrect debug printk
be2iscsi: Bump the driver version
be2iscsi: Fix processing cqe for cxn whose endpoint is freed
be2iscsi: Fix destroy MCC-CQ before MCC-EQ is destroyed
be2iscsi: Fix memory corruption in MBX path
...
Diffstat (limited to 'drivers/scsi/sun3_scsi.c')
| -rw-r--r-- | drivers/scsi/sun3_scsi.c | 241 |
1 files changed, 175 insertions, 66 deletions
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index e2c009b033ce..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 | /* |
| @@ -45,10 +49,6 @@ | |||
| 45 | * USLEEP - enable support for devices that don't disconnect. Untested. | 49 | * USLEEP - enable support for devices that don't disconnect. Untested. |
| 46 | */ | 50 | */ |
| 47 | 51 | ||
| 48 | /* | ||
| 49 | * $Log: sun3_NCR5380.c,v $ | ||
| 50 | */ | ||
| 51 | |||
| 52 | #define AUTOSENSE | 52 | #define AUTOSENSE |
| 53 | 53 | ||
| 54 | #include <linux/types.h> | 54 | #include <linux/types.h> |
| @@ -69,23 +69,15 @@ | |||
| 69 | #include <asm/idprom.h> | 69 | #include <asm/idprom.h> |
| 70 | #include <asm/machines.h> | 70 | #include <asm/machines.h> |
| 71 | 71 | ||
| 72 | #define NDEBUG 0 | ||
| 73 | |||
| 74 | #define NDEBUG_ABORT 0x00100000 | ||
| 75 | #define NDEBUG_TAGS 0x00200000 | ||
| 76 | #define NDEBUG_MERGING 0x00400000 | ||
| 77 | |||
| 78 | /* dma on! */ | 72 | /* dma on! */ |
| 79 | #define REAL_DMA | 73 | #define REAL_DMA |
| 80 | 74 | ||
| 81 | #include "scsi.h" | 75 | #include "scsi.h" |
| 82 | #include "initio.h" | ||
| 83 | #include <scsi/scsi_host.h> | 76 | #include <scsi/scsi_host.h> |
| 84 | #include "sun3_scsi.h" | 77 | #include "sun3_scsi.h" |
| 78 | #include "NCR5380.h" | ||
| 85 | 79 | ||
| 86 | static void NCR5380_print(struct Scsi_Host *instance); | 80 | extern int sun3_map_test(unsigned long, char *); |
| 87 | |||
| 88 | /* #define OLDDMA */ | ||
| 89 | 81 | ||
| 90 | #define USE_WRAPPER | 82 | #define USE_WRAPPER |
| 91 | /*#define RESET_BOOT */ | 83 | /*#define RESET_BOOT */ |
| @@ -101,7 +93,11 @@ static void NCR5380_print(struct Scsi_Host *instance); | |||
| 101 | 93 | ||
| 102 | /* #define SUPPORT_TAGS */ | 94 | /* #define SUPPORT_TAGS */ |
| 103 | 95 | ||
| 96 | #ifdef SUN3_SCSI_VME | ||
| 97 | #define ENABLE_IRQ() | ||
| 98 | #else | ||
| 104 | #define ENABLE_IRQ() enable_irq( IRQ_SUN3_SCSI ); | 99 | #define ENABLE_IRQ() enable_irq( IRQ_SUN3_SCSI ); |
| 100 | #endif | ||
| 105 | 101 | ||
| 106 | 102 | ||
| 107 | static irqreturn_t scsi_sun3_intr(int irq, void *dummy); | 103 | static irqreturn_t scsi_sun3_intr(int irq, void *dummy); |
| @@ -123,6 +119,8 @@ module_param(setup_hostid, int, 0); | |||
| 123 | 119 | ||
| 124 | static struct scsi_cmnd *sun3_dma_setup_done = NULL; | 120 | static struct scsi_cmnd *sun3_dma_setup_done = NULL; |
| 125 | 121 | ||
| 122 | #define RESET_RUN_DONE | ||
| 123 | |||
| 126 | #define AFTER_RESET_DELAY (HZ/2) | 124 | #define AFTER_RESET_DELAY (HZ/2) |
| 127 | 125 | ||
| 128 | /* ms to wait after hitting dma regs */ | 126 | /* ms to wait after hitting dma regs */ |
| @@ -136,10 +134,9 @@ static struct scsi_cmnd *sun3_dma_setup_done = NULL; | |||
| 136 | 134 | ||
| 137 | static volatile unsigned char *sun3_scsi_regp; | 135 | static volatile unsigned char *sun3_scsi_regp; |
| 138 | static volatile struct sun3_dma_regs *dregs; | 136 | static volatile struct sun3_dma_regs *dregs; |
| 139 | #ifdef OLDDMA | 137 | #ifndef SUN3_SCSI_VME |
| 140 | static unsigned char *dmabuf = NULL; /* dma memory buffer */ | ||
| 141 | #endif | ||
| 142 | static struct sun3_udc_regs *udc_regs = NULL; | 138 | static struct sun3_udc_regs *udc_regs = NULL; |
| 139 | #endif | ||
| 143 | static unsigned char *sun3_dma_orig_addr = NULL; | 140 | static unsigned char *sun3_dma_orig_addr = NULL; |
| 144 | static unsigned long sun3_dma_orig_count = 0; | 141 | static unsigned long sun3_dma_orig_count = 0; |
| 145 | static int sun3_dma_active = 0; | 142 | static int sun3_dma_active = 0; |
| @@ -159,6 +156,7 @@ static inline void sun3scsi_write(int reg, int value) | |||
| 159 | sun3_scsi_regp[reg] = value; | 156 | sun3_scsi_regp[reg] = value; |
| 160 | } | 157 | } |
| 161 | 158 | ||
| 159 | #ifndef SUN3_SCSI_VME | ||
| 162 | /* dma controller register access functions */ | 160 | /* dma controller register access functions */ |
| 163 | 161 | ||
| 164 | static inline unsigned short sun3_udc_read(unsigned char reg) | 162 | static inline unsigned short sun3_udc_read(unsigned char reg) |
| @@ -180,6 +178,7 @@ static inline void sun3_udc_write(unsigned short val, unsigned char reg) | |||
| 180 | dregs->udc_data = val; | 178 | dregs->udc_data = val; |
| 181 | udelay(SUN3_DMA_DELAY); | 179 | udelay(SUN3_DMA_DELAY); |
| 182 | } | 180 | } |
| 181 | #endif | ||
| 183 | 182 | ||
| 184 | /* | 183 | /* |
| 185 | * XXX: status debug | 184 | * XXX: status debug |
| @@ -198,17 +197,32 @@ static struct Scsi_Host *default_instance; | |||
| 198 | * | 197 | * |
| 199 | */ | 198 | */ |
| 200 | 199 | ||
| 201 | int __init sun3scsi_detect(struct scsi_host_template * tpnt) | 200 | static int __init sun3scsi_detect(struct scsi_host_template *tpnt) |
| 202 | { | 201 | { |
| 203 | unsigned long ioaddr; | 202 | unsigned long ioaddr, irq; |
| 204 | static int called = 0; | 203 | static int called = 0; |
| 205 | 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 | ||
| 206 | 214 | ||
| 207 | /* check that this machine has an onboard 5380 */ | 215 | /* check that this machine has an onboard 5380 */ |
| 208 | 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 | ||
| 209 | case SM_SUN3|SM_3_50: | 222 | case SM_SUN3|SM_3_50: |
| 210 | case SM_SUN3|SM_3_60: | 223 | case SM_SUN3|SM_3_60: |
| 211 | break; | 224 | break; |
| 225 | #endif | ||
| 212 | 226 | ||
| 213 | default: | 227 | default: |
| 214 | return 0; | 228 | return 0; |
| @@ -217,7 +231,11 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
| 217 | if(called) | 231 | if(called) |
| 218 | return 0; | 232 | return 0; |
| 219 | 233 | ||
| 234 | #ifdef SUN3_SCSI_VME | ||
| 235 | tpnt->proc_name = "Sun3 5380 VME SCSI"; | ||
| 236 | #else | ||
| 220 | tpnt->proc_name = "Sun3 5380 SCSI"; | 237 | tpnt->proc_name = "Sun3 5380 SCSI"; |
| 238 | #endif | ||
| 221 | 239 | ||
| 222 | /* setup variables */ | 240 | /* setup variables */ |
| 223 | tpnt->can_queue = | 241 | tpnt->can_queue = |
| @@ -234,6 +252,38 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
| 234 | tpnt->this_id = 7; | 252 | tpnt->this_id = 7; |
| 235 | } | 253 | } |
| 236 | 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; | ||
| 237 | ioaddr = (unsigned long)ioremap(IOBASE_SUN3_SCSI, PAGE_SIZE); | 287 | ioaddr = (unsigned long)ioremap(IOBASE_SUN3_SCSI, PAGE_SIZE); |
| 238 | sun3_scsi_regp = (unsigned char *)ioaddr; | 288 | sun3_scsi_regp = (unsigned char *)ioaddr; |
| 239 | 289 | ||
| @@ -244,11 +294,6 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
| 244 | printk("SUN3 Scsi couldn't allocate DVMA memory!\n"); | 294 | printk("SUN3 Scsi couldn't allocate DVMA memory!\n"); |
| 245 | return 0; | 295 | return 0; |
| 246 | } | 296 | } |
| 247 | #ifdef OLDDMA | ||
| 248 | if((dmabuf = dvma_malloc_align(SUN3_DVMA_BUFSIZE, 0x10000)) == NULL) { | ||
| 249 | printk("SUN3 Scsi couldn't allocate DVMA memory!\n"); | ||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | #endif | 297 | #endif |
| 253 | #ifdef SUPPORT_TAGS | 298 | #ifdef SUPPORT_TAGS |
| 254 | if (setup_use_tagged_queuing < 0) | 299 | if (setup_use_tagged_queuing < 0) |
| @@ -262,7 +307,7 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
| 262 | default_instance = instance; | 307 | default_instance = instance; |
| 263 | 308 | ||
| 264 | instance->io_port = (unsigned long) ioaddr; | 309 | instance->io_port = (unsigned long) ioaddr; |
| 265 | instance->irq = IRQ_SUN3_SCSI; | 310 | instance->irq = irq; |
| 266 | 311 | ||
| 267 | NCR5380_init(instance, 0); | 312 | NCR5380_init(instance, 0); |
| 268 | 313 | ||
| @@ -283,7 +328,8 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
| 283 | #endif | 328 | #endif |
| 284 | } | 329 | } |
| 285 | 330 | ||
| 286 | 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); | ||
| 287 | if (instance->irq == SCSI_IRQ_NONE) | 333 | if (instance->irq == SCSI_IRQ_NONE) |
| 288 | printk ("s disabled"); | 334 | printk ("s disabled"); |
| 289 | else | 335 | else |
| @@ -300,6 +346,15 @@ int __init sun3scsi_detect(struct scsi_host_template * tpnt) | |||
| 300 | dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR; | 346 | dregs->csr = CSR_SCSI | CSR_FIFO | CSR_INTR; |
| 301 | udelay(SUN3_DMA_DELAY); | 347 | udelay(SUN3_DMA_DELAY); |
| 302 | 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 | ||
| 303 | 358 | ||
| 304 | called = 1; | 359 | called = 1; |
| 305 | 360 | ||
| @@ -367,7 +422,8 @@ static void sun3_scsi_reset_boot(struct Scsi_Host *instance) | |||
| 367 | } | 422 | } |
| 368 | #endif | 423 | #endif |
| 369 | 424 | ||
| 370 | const char * sun3scsi_info (struct Scsi_Host *spnt) { | 425 | static const char *sun3scsi_info(struct Scsi_Host *spnt) |
| 426 | { | ||
| 371 | return ""; | 427 | return ""; |
| 372 | } | 428 | } |
| 373 | 429 | ||
| @@ -379,6 +435,10 @@ static irqreturn_t scsi_sun3_intr(int irq, void *dummy) | |||
| 379 | unsigned short csr = dregs->csr; | 435 | unsigned short csr = dregs->csr; |
| 380 | int handled = 0; | 436 | int handled = 0; |
| 381 | 437 | ||
| 438 | #ifdef SUN3_SCSI_VME | ||
| 439 | dregs->csr &= ~CSR_DMA_ENABLE; | ||
| 440 | #endif | ||
| 441 | |||
| 382 | if(csr & ~CSR_GOOD) { | 442 | if(csr & ~CSR_GOOD) { |
| 383 | if(csr & CSR_DMA_BUSERR) { | 443 | if(csr & CSR_DMA_BUSERR) { |
| 384 | 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); |
| @@ -422,31 +482,28 @@ void sun3_sun3_debug (void) | |||
| 422 | /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ | 482 | /* sun3scsi_dma_setup() -- initialize the dma controller for a read/write */ |
| 423 | 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) |
| 424 | { | 484 | { |
| 425 | #ifdef OLDDMA | ||
| 426 | if(write_flag) | ||
| 427 | memcpy(dmabuf, data, count); | ||
| 428 | else { | ||
| 429 | sun3_dma_orig_addr = data; | ||
| 430 | sun3_dma_orig_count = count; | ||
| 431 | } | ||
| 432 | #else | ||
| 433 | void *addr; | 485 | void *addr; |
| 434 | 486 | ||
| 435 | if(sun3_dma_orig_addr != NULL) | 487 | if(sun3_dma_orig_addr != NULL) |
| 436 | dvma_unmap(sun3_dma_orig_addr); | 488 | dvma_unmap(sun3_dma_orig_addr); |
| 437 | 489 | ||
| 438 | // 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 | ||
| 439 | addr = (void *)dvma_map((unsigned long) data, count); | 493 | addr = (void *)dvma_map((unsigned long) data, count); |
| 494 | #endif | ||
| 440 | 495 | ||
| 441 | sun3_dma_orig_addr = addr; | 496 | sun3_dma_orig_addr = addr; |
| 442 | sun3_dma_orig_count = count; | 497 | sun3_dma_orig_count = count; |
| 443 | #endif | 498 | |
| 499 | #ifndef SUN3_SCSI_VME | ||
| 444 | dregs->fifo_count = 0; | 500 | dregs->fifo_count = 0; |
| 445 | sun3_udc_write(UDC_RESET, UDC_CSR); | 501 | sun3_udc_write(UDC_RESET, UDC_CSR); |
| 446 | 502 | ||
| 447 | /* reset fifo */ | 503 | /* reset fifo */ |
| 448 | dregs->csr &= ~CSR_FIFO; | 504 | dregs->csr &= ~CSR_FIFO; |
| 449 | dregs->csr |= CSR_FIFO; | 505 | dregs->csr |= CSR_FIFO; |
| 506 | #endif | ||
| 450 | 507 | ||
| 451 | /* set direction */ | 508 | /* set direction */ |
| 452 | if(write_flag) | 509 | if(write_flag) |
| @@ -454,6 +511,17 @@ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int wri | |||
| 454 | else | 511 | else |
| 455 | dregs->csr &= ~CSR_SEND; | 512 | dregs->csr &= ~CSR_SEND; |
| 456 | 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 | ||
| 457 | /* byte count for fifo */ | 525 | /* byte count for fifo */ |
| 458 | dregs->fifo_count = count; | 526 | dregs->fifo_count = count; |
| 459 | 527 | ||
| @@ -467,17 +535,12 @@ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int wri | |||
| 467 | printk("scsi%d: fifo_mismatch %04x not %04x\n", | 535 | printk("scsi%d: fifo_mismatch %04x not %04x\n", |
| 468 | default_instance->host_no, dregs->fifo_count, | 536 | default_instance->host_no, dregs->fifo_count, |
| 469 | (unsigned int) count); | 537 | (unsigned int) count); |
| 470 | NCR5380_print(default_instance); | 538 | NCR5380_dprint(NDEBUG_DMA, default_instance); |
| 471 | } | 539 | } |
| 472 | 540 | ||
| 473 | /* setup udc */ | 541 | /* setup udc */ |
| 474 | #ifdef OLDDMA | ||
| 475 | udc_regs->addr_hi = ((dvma_vtob(dmabuf) & 0xff0000) >> 8); | ||
| 476 | udc_regs->addr_lo = (dvma_vtob(dmabuf) & 0xffff); | ||
| 477 | #else | ||
| 478 | udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8); | 542 | udc_regs->addr_hi = (((unsigned long)(addr) & 0xff0000) >> 8); |
| 479 | udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff); | 543 | udc_regs->addr_lo = ((unsigned long)(addr) & 0xffff); |
| 480 | #endif | ||
| 481 | udc_regs->count = count/2; /* count in words */ | 544 | udc_regs->count = count/2; /* count in words */ |
| 482 | udc_regs->mode_hi = UDC_MODE_HIWORD; | 545 | udc_regs->mode_hi = UDC_MODE_HIWORD; |
| 483 | if(write_flag) { | 546 | if(write_flag) { |
| @@ -501,11 +564,13 @@ static unsigned long sun3scsi_dma_setup(void *data, unsigned long count, int wri | |||
| 501 | 564 | ||
| 502 | /* interrupt enable */ | 565 | /* interrupt enable */ |
| 503 | sun3_udc_write(UDC_INT_ENABLE, UDC_CSR); | 566 | sun3_udc_write(UDC_INT_ENABLE, UDC_CSR); |
| 567 | #endif | ||
| 504 | 568 | ||
| 505 | return count; | 569 | return count; |
| 506 | 570 | ||
| 507 | } | 571 | } |
| 508 | 572 | ||
| 573 | #ifndef SUN3_SCSI_VME | ||
| 509 | static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance) | 574 | static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance) |
| 510 | { | 575 | { |
| 511 | unsigned short resid; | 576 | unsigned short resid; |
| @@ -518,6 +583,7 @@ static inline unsigned long sun3scsi_dma_count(struct Scsi_Host *instance) | |||
| 518 | 583 | ||
| 519 | return (unsigned long) resid; | 584 | return (unsigned long) resid; |
| 520 | } | 585 | } |
| 586 | #endif | ||
| 521 | 587 | ||
| 522 | static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) | 588 | static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) |
| 523 | { | 589 | { |
| @@ -536,8 +602,23 @@ static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, | |||
| 536 | 602 | ||
| 537 | 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) |
| 538 | { | 604 | { |
| 605 | #ifdef SUN3_SCSI_VME | ||
| 606 | unsigned short csr; | ||
| 607 | |||
| 608 | csr = dregs->csr; | ||
| 539 | 609 | ||
| 610 | dregs->dma_count_hi = (sun3_dma_orig_count >> 16); | ||
| 611 | dregs->dma_count_lo = (sun3_dma_orig_count & 0xffff); | ||
| 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 | ||
| 540 | sun3_udc_write(UDC_CHN_START, UDC_CSR); | 620 | sun3_udc_write(UDC_CHN_START, UDC_CSR); |
| 621 | #endif | ||
| 541 | 622 | ||
| 542 | return 0; | 623 | return 0; |
| 543 | } | 624 | } |
| @@ -545,12 +626,46 @@ static inline int sun3scsi_dma_start(unsigned long count, unsigned char *data) | |||
| 545 | /* clean up after our dma is done */ | 626 | /* clean up after our dma is done */ |
| 546 | static int sun3scsi_dma_finish(int write_flag) | 627 | static int sun3scsi_dma_finish(int write_flag) |
| 547 | { | 628 | { |
| 548 | unsigned short count; | 629 | unsigned short __maybe_unused count; |
| 549 | unsigned short fifo; | 630 | unsigned short fifo; |
| 550 | int ret = 0; | 631 | int ret = 0; |
| 551 | 632 | ||
| 552 | sun3_dma_active = 0; | 633 | sun3_dma_active = 0; |
| 553 | #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 | ||
| 554 | // check to empty the fifo on a read | 669 | // check to empty the fifo on a read |
| 555 | if(!write_flag) { | 670 | if(!write_flag) { |
| 556 | int tmo = 20000; /* .2 sec */ | 671 | int tmo = 20000; /* .2 sec */ |
| @@ -566,28 +681,8 @@ static int sun3scsi_dma_finish(int write_flag) | |||
| 566 | udelay(10); | 681 | udelay(10); |
| 567 | } | 682 | } |
| 568 | } | 683 | } |
| 569 | |||
| 570 | #endif | ||
| 571 | 684 | ||
| 572 | count = sun3scsi_dma_count(default_instance); | 685 | count = sun3scsi_dma_count(default_instance); |
| 573 | #ifdef OLDDMA | ||
| 574 | |||
| 575 | /* if we've finished a read, copy out the data we read */ | ||
| 576 | if(sun3_dma_orig_addr) { | ||
| 577 | /* check for residual bytes after dma end */ | ||
| 578 | if(count && (NCR5380_read(BUS_AND_STATUS_REG) & | ||
| 579 | (BASR_PHASE_MATCH | BASR_ACK))) { | ||
| 580 | printk("scsi%d: sun3_scsi_finish: read overrun baby... ", default_instance->host_no); | ||
| 581 | printk("basr now %02x\n", NCR5380_read(BUS_AND_STATUS_REG)); | ||
| 582 | ret = count; | ||
| 583 | } | ||
| 584 | |||
| 585 | /* copy in what we dma'd no matter what */ | ||
| 586 | memcpy(sun3_dma_orig_addr, dmabuf, sun3_dma_orig_count); | ||
| 587 | sun3_dma_orig_addr = NULL; | ||
| 588 | |||
| 589 | } | ||
| 590 | #else | ||
| 591 | 686 | ||
| 592 | fifo = dregs->fifo_count; | 687 | fifo = dregs->fifo_count; |
| 593 | last_residual = fifo; | 688 | last_residual = fifo; |
| @@ -605,10 +700,23 @@ static int sun3scsi_dma_finish(int write_flag) | |||
| 605 | vaddr[-2] = (data & 0xff00) >> 8; | 700 | vaddr[-2] = (data & 0xff00) >> 8; |
| 606 | vaddr[-1] = (data & 0xff); | 701 | vaddr[-1] = (data & 0xff); |
| 607 | } | 702 | } |
| 703 | #endif | ||
| 608 | 704 | ||
| 609 | dvma_unmap(sun3_dma_orig_addr); | 705 | dvma_unmap(sun3_dma_orig_addr); |
| 610 | sun3_dma_orig_addr = NULL; | 706 | sun3_dma_orig_addr = NULL; |
| 611 | #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 | ||
| 612 | sun3_udc_write(UDC_RESET, UDC_CSR); | 720 | sun3_udc_write(UDC_RESET, UDC_CSR); |
| 613 | dregs->fifo_count = 0; | 721 | dregs->fifo_count = 0; |
| 614 | dregs->csr &= ~CSR_SEND; | 722 | dregs->csr &= ~CSR_SEND; |
| @@ -616,6 +724,7 @@ static int sun3scsi_dma_finish(int write_flag) | |||
| 616 | /* reset fifo */ | 724 | /* reset fifo */ |
| 617 | dregs->csr &= ~CSR_FIFO; | 725 | dregs->csr &= ~CSR_FIFO; |
| 618 | dregs->csr |= CSR_FIFO; | 726 | dregs->csr |= CSR_FIFO; |
| 727 | #endif | ||
| 619 | 728 | ||
| 620 | sun3_dma_setup_done = NULL; | 729 | sun3_dma_setup_done = NULL; |
| 621 | 730 | ||
