Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ncr5380: Enable PDMA for DTC chips

Add I/O register mapping for DTC chips and enable PDMA mode.

These chips have 16-bit wide HOST BUFFER register and it must be read
by 16-bit accesses (we lose data otherwise).

Large PIO transfers crash at least the DTCT-436P chip (all reads result
in 0xFF) so this patch actually makes it work.

The chip also crashes when we bang on the C400 host status register too
heavily after PDMA write - a small udelay is needed.

Tested on DTCT-436P and verified that it does not break 53C400A.

Signed-off-by: Ondrej Zary <linux@rainbow-software.org>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Ondrej Zary and committed by
Martin K. Petersen
aeb51152 cecf3bee

+33 -8
+31 -7
drivers/scsi/g_NCR5380.c
··· 327 327 ports = ncr_53c400a_ports; 328 328 break; 329 329 case BOARD_DTC3181E: 330 - flags = FLAG_NO_PSEUDO_DMA; 330 + flags = FLAG_NO_DMA_FIXUP; 331 331 ports = dtc_3181e_ports; 332 332 break; 333 333 } ··· 400 400 #ifndef SCSI_G_NCR5380_MEM 401 401 instance->io_port = overrides[current_override].NCR5380_map_name; 402 402 instance->n_io_port = region_size; 403 + hostdata->io_width = 1; /* 8-bit PDMA by default */ 403 404 404 405 /* 405 406 * On NCR53C400 boards, NCR5380 registers are mapped 8 past ··· 413 412 hostdata->c400_blk_cnt = 1; 414 413 hostdata->c400_host_buf = 4; 415 414 break; 415 + case BOARD_DTC3181E: 416 + hostdata->io_width = 2; /* 16-bit PDMA */ 417 + /* fall through */ 416 418 case BOARD_NCR53C400A: 417 419 hostdata->c400_ctl_status = 9; 418 420 hostdata->c400_blk_cnt = 10; ··· 431 427 hostdata->c400_blk_cnt = 0x101; 432 428 hostdata->c400_host_buf = 0x104; 433 429 break; 430 + case BOARD_DTC3181E: 434 431 case BOARD_NCR53C400A: 435 432 pr_err(DRV_MODULE_NAME ": unknown register offsets\n"); 436 433 goto out_unregister; ··· 443 438 444 439 switch (overrides[current_override].board) { 445 440 case BOARD_NCR53C400: 441 + case BOARD_DTC3181E: 446 442 case BOARD_NCR53C400A: 447 443 NCR5380_write(hostdata->c400_ctl_status, CSR_BASE); 448 444 } ··· 571 565 ; /* FIXME - no timeout */ 572 566 573 567 #ifndef SCSI_G_NCR5380_MEM 574 - insb(instance->io_port + hostdata->c400_host_buf, 568 + if (hostdata->io_width == 2) 569 + insw(instance->io_port + hostdata->c400_host_buf, 570 + dst + start, 64); 571 + else 572 + insb(instance->io_port + hostdata->c400_host_buf, 575 573 dst + start, 128); 576 574 #else 577 575 /* implies SCSI_G_NCR5380_MEM */ ··· 591 581 ; /* FIXME - no timeout */ 592 582 593 583 #ifndef SCSI_G_NCR5380_MEM 594 - insb(instance->io_port + hostdata->c400_host_buf, 584 + if (hostdata->io_width == 2) 585 + insw(instance->io_port + hostdata->c400_host_buf, 586 + dst + start, 64); 587 + else 588 + insb(instance->io_port + hostdata->c400_host_buf, 595 589 dst + start, 128); 596 590 #else 597 591 /* implies SCSI_G_NCR5380_MEM */ ··· 653 639 while (NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) 654 640 ; // FIXME - timeout 655 641 #ifndef SCSI_G_NCR5380_MEM 656 - outsb(instance->io_port + hostdata->c400_host_buf, 642 + if (hostdata->io_width == 2) 643 + outsw(instance->io_port + hostdata->c400_host_buf, 644 + src + start, 64); 645 + else 646 + outsb(instance->io_port + hostdata->c400_host_buf, 657 647 src + start, 128); 658 648 #else 659 649 /* implies SCSI_G_NCR5380_MEM */ ··· 672 654 ; // FIXME - no timeout 673 655 674 656 #ifndef SCSI_G_NCR5380_MEM 675 - outsb(instance->io_port + hostdata->c400_host_buf, 657 + if (hostdata->io_width == 2) 658 + outsw(instance->io_port + hostdata->c400_host_buf, 659 + src + start, 64); 660 + else 661 + outsb(instance->io_port + hostdata->c400_host_buf, 676 662 src + start, 128); 677 663 #else 678 664 /* implies SCSI_G_NCR5380_MEM */ ··· 697 675 /* All documentation says to check for this. Maybe my hardware is too 698 676 * fast. Waiting for it seems to work fine! KLL 699 677 */ 700 - while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) 701 - ; // FIXME - no timeout 678 + while (!(i = NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ)) { 679 + udelay(4); /* DTC436 chip hangs without this */ 680 + /* FIXME - no timeout */ 681 + } 702 682 703 683 /* 704 684 * I know. i is certainly != 0 here but the loop is new. See previous
+2 -1
drivers/scsi/g_NCR5380.h
··· 44 44 #define NCR5380_implementation_fields \ 45 45 int c400_ctl_status; \ 46 46 int c400_blk_cnt; \ 47 - int c400_host_buf; 47 + int c400_host_buf; \ 48 + int io_width; 48 49 49 50 #else 50 51 /* therefore SCSI_G_NCR5380_MEM */