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

ncr5380: Merge DMA implementation from atari_NCR5380 core driver

Adopt the DMA implementation from atari_NCR5380.c. This means that
atari_scsi and sun3_scsi can make use of the NCR5380.c core driver
and the atari_NCR5380.c driver fork can be made redundant.

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

authored by

Finn Thain and committed by
Martin K. Petersen
8053b0ee 438af51c

+153 -41
+138 -34
drivers/scsi/NCR5380.c
··· 31 31 32 32 /* 33 33 * Further development / testing that should be done : 34 - * 1. Cleanup the NCR5380_transfer_dma function and DMA operation complete 35 - * code so that everything does the same thing that's done at the 36 - * end of a pseudo-DMA read operation. 37 34 * 38 35 * 4. Test SCSI-II tagged queueing (I have no devices which support 39 36 * tagged queueing) ··· 113 116 * override-configure an IRQ. 114 117 * 115 118 * PSEUDO_DMA - if defined, PSEUDO DMA is used during the data transfer phases. 119 + * 120 + * REAL_DMA - if defined, REAL DMA is used during the data transfer phases. 116 121 * 117 122 * These macros MUST be defined : 118 123 * ··· 800 801 } while (!done); 801 802 } 802 803 804 + /* 805 + * NCR5380_dma_complete - finish DMA transfer 806 + * @instance: the scsi host instance 807 + * 808 + * Called by the interrupt handler when DMA finishes or a phase 809 + * mismatch occurs (which would end the DMA transfer). 810 + */ 811 + 812 + static void NCR5380_dma_complete(struct Scsi_Host *instance) 813 + { 814 + struct NCR5380_hostdata *hostdata = shost_priv(instance); 815 + int transferred; 816 + unsigned char **data; 817 + int *count; 818 + int saved_data = 0, overrun = 0; 819 + unsigned char p; 820 + 821 + if (hostdata->read_overruns) { 822 + p = hostdata->connected->SCp.phase; 823 + if (p & SR_IO) { 824 + udelay(10); 825 + if ((NCR5380_read(BUS_AND_STATUS_REG) & 826 + (BASR_PHASE_MATCH | BASR_ACK)) == 827 + (BASR_PHASE_MATCH | BASR_ACK)) { 828 + saved_data = NCR5380_read(INPUT_DATA_REG); 829 + overrun = 1; 830 + dsprintk(NDEBUG_DMA, instance, "read overrun handled\n"); 831 + } 832 + } 833 + } 834 + 835 + NCR5380_write(MODE_REG, MR_BASE); 836 + NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); 837 + NCR5380_read(RESET_PARITY_INTERRUPT_REG); 838 + 839 + transferred = hostdata->dma_len - NCR5380_dma_residual(instance); 840 + hostdata->dma_len = 0; 841 + 842 + data = (unsigned char **)&hostdata->connected->SCp.ptr; 843 + count = &hostdata->connected->SCp.this_residual; 844 + *data += transferred; 845 + *count -= transferred; 846 + 847 + if (hostdata->read_overruns) { 848 + int cnt, toPIO; 849 + 850 + if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) { 851 + cnt = toPIO = hostdata->read_overruns; 852 + if (overrun) { 853 + dsprintk(NDEBUG_DMA, instance, 854 + "Got an input overrun, using saved byte\n"); 855 + *(*data)++ = saved_data; 856 + (*count)--; 857 + cnt--; 858 + toPIO--; 859 + } 860 + if (toPIO > 0) { 861 + dsprintk(NDEBUG_DMA, instance, 862 + "Doing %d byte PIO to 0x%p\n", cnt, *data); 863 + NCR5380_transfer_pio(instance, &p, &cnt, data); 864 + *count -= toPIO - cnt; 865 + } 866 + } 867 + } 868 + } 869 + 803 870 #ifndef DONT_USE_INTR 804 871 805 872 /** ··· 920 855 dsprintk(NDEBUG_INTR, instance, "IRQ %d, BASR 0x%02x, SR 0x%02x, MR 0x%02x\n", 921 856 irq, basr, sr, mr); 922 857 923 - if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && 858 + if ((mr & MR_DMA_MODE) || (mr & MR_MONITOR_BSY)) { 859 + /* Probably End of DMA, Phase Mismatch or Loss of BSY. 860 + * We ack IRQ after clearing Mode Register. Workarounds 861 + * for End of DMA errata need to happen in DMA Mode. 862 + */ 863 + 864 + dsprintk(NDEBUG_INTR, instance, "interrupt in DMA mode\n"); 865 + 866 + if (hostdata->connected) { 867 + NCR5380_dma_complete(instance); 868 + queue_work(hostdata->work_q, &hostdata->main_task); 869 + } else { 870 + NCR5380_write(MODE_REG, MR_BASE); 871 + NCR5380_read(RESET_PARITY_INTERRUPT_REG); 872 + } 873 + } else if ((NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_mask) && 924 874 (sr & (SR_SEL | SR_IO | SR_BSY | SR_RST)) == (SR_SEL | SR_IO)) { 925 875 /* Probably reselected */ 926 876 NCR5380_write(SELECT_ENABLE_REG, 0); ··· 1511 1431 register unsigned char p = *phase; 1512 1432 register unsigned char *d = *data; 1513 1433 unsigned char tmp; 1514 - int result; 1434 + int result = 0; 1515 1435 1516 1436 if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) { 1517 1437 *phase = tmp; 1518 1438 return -1; 1519 1439 } 1520 1440 1441 + hostdata->connected->SCp.phase = p; 1442 + 1443 + if (p & SR_IO) { 1444 + if (hostdata->read_overruns) 1445 + c -= hostdata->read_overruns; 1446 + else if (hostdata->flags & FLAG_DMA_FIXUP) 1447 + --c; 1448 + } 1449 + 1450 + dsprintk(NDEBUG_DMA, instance, "initializing DMA %s: length %d, address %p\n", 1451 + (p & SR_IO) ? "receive" : "send", c, d); 1452 + 1521 1453 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p)); 1454 + NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | 1455 + MR_ENABLE_EOP_INTR); 1522 1456 1523 - /* 1524 - * Note : on my sample board, watch-dog timeouts occurred when interrupts 1525 - * were not disabled for the duration of a single DMA transfer, from 1526 - * before the setting of DMA mode to after transfer of the last byte. 1527 - */ 1528 - 1529 - if (hostdata->flags & FLAG_DMA_FIXUP) 1530 - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY); 1531 - else 1532 - NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_MONITOR_BSY | 1533 - MR_ENABLE_EOP_INTR); 1534 - 1535 - dprintk(NDEBUG_DMA, "scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)); 1457 + if (!(hostdata->flags & FLAG_LATE_DMA_SETUP)) { 1458 + /* On the Medusa, it is a must to initialize the DMA before 1459 + * starting the NCR. This is also the cleaner way for the TT. 1460 + */ 1461 + if (p & SR_IO) 1462 + result = NCR5380_dma_recv_setup(instance, d, c); 1463 + else 1464 + result = NCR5380_dma_send_setup(instance, d, c); 1465 + } 1536 1466 1537 1467 /* 1538 1468 * On the PAS16 at least I/O recovery delays are not needed here. ··· 1559 1469 NCR5380_write(START_DMA_SEND_REG, 0); 1560 1470 NCR5380_io_delay(1); 1561 1471 } 1472 + 1473 + if (hostdata->flags & FLAG_LATE_DMA_SETUP) { 1474 + /* On the Falcon, the DMA setup must be done after the last 1475 + * NCR access, else the DMA setup gets trashed! 1476 + */ 1477 + if (p & SR_IO) 1478 + result = NCR5380_dma_recv_setup(instance, d, c); 1479 + else 1480 + result = NCR5380_dma_send_setup(instance, d, c); 1481 + } 1482 + 1483 + /* On failure, NCR5380_dma_xxxx_setup() returns a negative int. */ 1484 + if (result < 0) 1485 + return result; 1486 + 1487 + /* For real DMA, result is the byte count. DMA interrupt is expected. */ 1488 + if (result > 0) { 1489 + hostdata->dma_len = result; 1490 + return 0; 1491 + } 1492 + 1493 + /* The result is zero iff pseudo DMA send/receive was completed. */ 1494 + hostdata->dma_len = c; 1562 1495 1563 1496 /* 1564 1497 * A note regarding the DMA errata workarounds for early NMOS silicon. ··· 1617 1504 * request. 1618 1505 */ 1619 1506 1620 - if (p & SR_IO) { 1621 - result = NCR5380_dma_recv_setup(instance, d, 1622 - hostdata->flags & FLAG_DMA_FIXUP ? c - 1 : c); 1623 - if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { 1507 + if (hostdata->flags & FLAG_DMA_FIXUP) { 1508 + if (p & SR_IO) { 1624 1509 /* 1625 1510 * The workaround was to transfer fewer bytes than we 1626 1511 * intended to with the pseudo-DMA read function, wait for ··· 1644 1533 result = -1; 1645 1534 shost_printk(KERN_ERR, instance, "PDMA read: !REQ timeout\n"); 1646 1535 } 1647 - d[c - 1] = NCR5380_read(INPUT_DATA_REG); 1648 - } 1649 - } else { 1650 - result = NCR5380_dma_send_setup(instance, d, c); 1651 - if (!result && (hostdata->flags & FLAG_DMA_FIXUP)) { 1536 + d[*count - 1] = NCR5380_read(INPUT_DATA_REG); 1537 + } else { 1652 1538 /* 1653 1539 * Wait for the last byte to be sent. If REQ is being asserted for 1654 1540 * the byte we're interested, we'll ACK it and it will go false. ··· 1658 1550 } 1659 1551 } 1660 1552 } 1661 - NCR5380_write(MODE_REG, MR_BASE); 1662 - NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); 1663 - NCR5380_read(RESET_PARITY_INTERRUPT_REG); 1664 - *data = d + c; 1665 - *count = 0; 1553 + 1554 + NCR5380_dma_complete(instance); 1666 1555 return result; 1667 1556 } 1668 1557 ··· 1772 1667 do_abort(instance); 1773 1668 cmd->result = DID_ERROR << 16; 1774 1669 /* XXX - need to source or sink data here, as appropriate */ 1775 - } else 1776 - cmd->SCp.this_residual -= transfersize - len; 1670 + } 1777 1671 } else { 1778 1672 /* Break up transfer into 3 ms chunks, 1779 1673 * presuming 6 accesses per handshake.
+2 -1
drivers/scsi/arm/cumana_1.c
··· 20 20 #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) 21 21 #define NCR5380_dma_recv_setup cumanascsi_pread 22 22 #define NCR5380_dma_send_setup cumanascsi_pwrite 23 + #define NCR5380_dma_residual(instance) (0) 23 24 24 25 #define NCR5380_intr cumanascsi_intr 25 26 #define NCR5380_queue_command cumanascsi_queue_command ··· 246 245 247 246 host->irq = ec->irq; 248 247 249 - ret = NCR5380_init(host, FLAG_DMA_FIXUP); 248 + ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP); 250 249 if (ret) 251 250 goto out_unmap; 252 251
+2 -1
drivers/scsi/arm/oak.c
··· 26 26 #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) 27 27 #define NCR5380_dma_recv_setup oakscsi_pread 28 28 #define NCR5380_dma_send_setup oakscsi_pwrite 29 + #define NCR5380_dma_residual(instance) (0) 29 30 30 31 #define NCR5380_queue_command oakscsi_queue_command 31 32 #define NCR5380_info oakscsi_info ··· 145 144 host->irq = NO_IRQ; 146 145 host->n_io_port = 255; 147 146 148 - ret = NCR5380_init(host, FLAG_DMA_FIXUP); 147 + ret = NCR5380_init(host, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP); 149 148 if (ret) 150 149 goto out_unmap; 151 150
+1
drivers/scsi/dmx3191d.c
··· 42 42 #define NCR5380_dma_xfer_len(instance, cmd, phase) (0) 43 43 #define NCR5380_dma_recv_setup(instance, dst, len) (0) 44 44 #define NCR5380_dma_send_setup(instance, src, len) (0) 45 + #define NCR5380_dma_residual(instance) (0) 45 46 46 47 #define NCR5380_implementation_fields /* none */ 47 48
+1 -1
drivers/scsi/dtc.c
··· 228 228 instance->base = addr; 229 229 ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; 230 230 231 - if (NCR5380_init(instance, 0)) 231 + if (NCR5380_init(instance, FLAG_LATE_DMA_SETUP)) 232 232 goto out_unregister; 233 233 234 234 NCR5380_maybe_reset_bus(instance);
+1
drivers/scsi/dtc.h
··· 23 23 dtc_dma_xfer_len(cmd) 24 24 #define NCR5380_dma_recv_setup dtc_pread 25 25 #define NCR5380_dma_send_setup dtc_pwrite 26 + #define NCR5380_dma_residual(instance) (0) 26 27 27 28 #define NCR5380_intr dtc_intr 28 29 #define NCR5380_queue_command dtc_queue_command
+1 -1
drivers/scsi/g_NCR5380.c
··· 466 466 } 467 467 #endif 468 468 469 - if (NCR5380_init(instance, flags)) 469 + if (NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP)) 470 470 goto out_unregister; 471 471 472 472 switch (overrides[current_override].board) {
+1
drivers/scsi/g_NCR5380.h
··· 64 64 generic_NCR5380_dma_xfer_len(instance, cmd) 65 65 #define NCR5380_dma_recv_setup generic_NCR5380_pread 66 66 #define NCR5380_dma_send_setup generic_NCR5380_pwrite 67 + #define NCR5380_dma_residual(instance) (0) 67 68 68 69 #define NCR5380_intr generic_NCR5380_intr 69 70 #define NCR5380_queue_command generic_NCR5380_queue_command
+2 -1
drivers/scsi/mac_scsi.c
··· 37 37 macscsi_dma_xfer_len(instance, cmd) 38 38 #define NCR5380_dma_recv_setup macscsi_pread 39 39 #define NCR5380_dma_send_setup macscsi_pwrite 40 + #define NCR5380_dma_residual(instance) (0) 40 41 41 42 #define NCR5380_intr macscsi_intr 42 43 #define NCR5380_queue_command macscsi_queue_command ··· 387 386 #endif 388 387 host_flags |= setup_toshiba_delay > 0 ? FLAG_TOSHIBA_DELAY : 0; 389 388 390 - error = NCR5380_init(instance, host_flags); 389 + error = NCR5380_init(instance, host_flags | FLAG_LATE_DMA_SETUP); 391 390 if (error) 392 391 goto fail_init; 393 392
+1 -1
drivers/scsi/pas16.c
··· 375 375 376 376 instance->io_port = io_port; 377 377 378 - if (NCR5380_init(instance, FLAG_DMA_FIXUP)) 378 + if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP)) 379 379 goto out_unregister; 380 380 381 381 NCR5380_maybe_reset_bus(instance);
+1
drivers/scsi/pas16.h
··· 105 105 #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) 106 106 #define NCR5380_dma_recv_setup pas16_pread 107 107 #define NCR5380_dma_send_setup pas16_pwrite 108 + #define NCR5380_dma_residual(instance) (0) 108 109 109 110 #define NCR5380_intr pas16_intr 110 111 #define NCR5380_queue_command pas16_queue_command
+1 -1
drivers/scsi/t128.c
··· 208 208 instance->base = base; 209 209 ((struct NCR5380_hostdata *)instance->hostdata)->base = p; 210 210 211 - if (NCR5380_init(instance, FLAG_DMA_FIXUP)) 211 + if (NCR5380_init(instance, FLAG_DMA_FIXUP | FLAG_LATE_DMA_SETUP)) 212 212 goto out_unregister; 213 213 214 214 NCR5380_maybe_reset_bus(instance);
+1
drivers/scsi/t128.h
··· 79 79 #define NCR5380_dma_xfer_len(instance, cmd, phase) (cmd->transfersize) 80 80 #define NCR5380_dma_recv_setup t128_pread 81 81 #define NCR5380_dma_send_setup t128_pwrite 82 + #define NCR5380_dma_residual(instance) (0) 82 83 83 84 #define NCR5380_intr t128_intr 84 85 #define NCR5380_queue_command t128_queue_command