#define NCR5380_implementation_fields \ int offset; \ int c400_ctl_status; \ int c400_blk_cnt; \ int c400_host_buf; \ int io_width; \ int pdma_residual; \ int board
/* * An interrupt is triggered whenever BSY = false, SEL = true * and a bit set in the SELECT_ENABLE_REG is asserted on the * SCSI bus. * * Note that the bus is only driven when the phase control signals * (I/O, C/D, and MSG) match those in the TCR.
*/
NCR5380_write(TARGET_COMMAND_REG,
PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));
NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
NCR5380_write(INITIATOR_COMMAND_REG,
ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_SEL);
/** * g_NCR5380_probe_irq - find the IRQ of a NCR5380 or equivalent * @instance: SCSI host instance * * Autoprobe for the IRQ line used by the card by triggering an IRQ * and then looking to see what interrupt actually turned up.
*/
if (is_pmio) {
hostdata->io_port = base;
hostdata->io_width = 1; /* 8-bit PDMA by default */
hostdata->offset = 0;
/* * On NCR53C400 boards, NCR5380 registers are mapped 8 past * the base address.
*/ switch (board) { case BOARD_NCR53C400:
hostdata->io_port += 8;
hostdata->c400_ctl_status = 0;
hostdata->c400_blk_cnt = 1;
hostdata->c400_host_buf = 4; break; case BOARD_DTC3181E:
hostdata->io_width = 2; /* 16-bit PDMA */
fallthrough; case BOARD_NCR53C400A: case BOARD_HP_C2502:
hostdata->c400_ctl_status = 9;
hostdata->c400_blk_cnt = 10;
hostdata->c400_host_buf = 8; break;
}
} else {
hostdata->base = base;
hostdata->offset = NCR53C400_mem_base; switch (board) { case BOARD_NCR53C400:
hostdata->c400_ctl_status = 0x100;
hostdata->c400_blk_cnt = 0x101;
hostdata->c400_host_buf = 0x104; break; case BOARD_DTC3181E: case BOARD_NCR53C400A: case BOARD_HP_C2502:
pr_err(DRV_MODULE_NAME ": unknown register offsets\n");
ret = -EINVAL; goto out_unregister;
}
}
/* Check for vacant slot */
NCR5380_write(MODE_REG, 0); if (NCR5380_read(MODE_REG) != 0) {
ret = -ENODEV; goto out_unregister;
}
ret = NCR5380_init(instance, flags | FLAG_LATE_DMA_SETUP); if (ret) goto out_unregister;
switch (board) { case BOARD_NCR53C400: case BOARD_DTC3181E: case BOARD_NCR53C400A: case BOARD_HP_C2502:
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
}
scsi_remove_host(instance); if (instance->irq != NO_IRQ)
free_irq(instance->irq, instance);
NCR5380_exit(instance);
scsi_host_put(instance);
iounmap(iomem); if (io_port)
release_region(io_port, region_size); else
release_mem_region(base, region_size);
}
/* wait_for_53c80_access - wait for 53C80 registers to become accessible * @hostdata: scsi host private data * * The registers within the 53C80 logic block are inaccessible until * bit 7 in the 53C400 control status register gets asserted.
*/
staticvoid wait_for_53c80_access(struct NCR5380_hostdata *hostdata)
{ int count = 10000;
do { if (hostdata->board == BOARD_DTC3181E)
udelay(4); /* DTC436 chip hangs without this */ if (NCR5380_read(hostdata->c400_ctl_status) & CSR_53C80_REG) return;
} while (--count > 0);
scmd_printk(KERN_ERR, hostdata->connected, "53c80 registers not accessible, device will be reset\n");
NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
}
/** * generic_NCR5380_precv - pseudo DMA receive * @hostdata: scsi host private data * @dst: buffer to write into * @len: transfer size * * Perform a pseudo DMA mode receive from a 53C400 or equivalent device.
*/
staticinlineint generic_NCR5380_precv(struct NCR5380_hostdata *hostdata, unsignedchar *dst, int len)
{ int residual; int start = 0;
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE | CSR_TRANS_DIR);
NCR5380_write(hostdata->c400_blk_cnt, len / 128);
do { if (start == len - 128) { /* Ignore End of DMA interrupt for the final buffer */ if (NCR5380_poll_politely(hostdata, hostdata->c400_ctl_status,
CSR_HOST_BUF_NOT_RDY, 0, 0) < 0) break;
} else { if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
CSR_HOST_BUF_NOT_RDY, 0,
hostdata->c400_ctl_status,
CSR_GATED_53C80_IRQ,
CSR_GATED_53C80_IRQ, 0) < 0 ||
NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) break;
}
if (residual != 0) { /* 53c80 interrupt or transfer timeout. Reset 53c400 logic. */
NCR5380_write(hostdata->c400_ctl_status, CSR_RESET);
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
}
wait_for_53c80_access(hostdata);
if (residual == 0 && NCR5380_poll_politely(hostdata, BUS_AND_STATUS_REG,
BASR_END_DMA_TRANSFER,
BASR_END_DMA_TRANSFER,
0) < 0)
scmd_printk(KERN_ERR, hostdata->connected, "%s: End of DMA timeout\n",
__func__);
hostdata->pdma_residual = residual;
return 0;
}
/** * generic_NCR5380_psend - pseudo DMA send * @hostdata: scsi host private data * @src: buffer to read from * @len: transfer size * * Perform a pseudo DMA mode send to a 53C400 or equivalent device.
*/
staticinlineint generic_NCR5380_psend(struct NCR5380_hostdata *hostdata, unsignedchar *src, int len)
{ int residual; int start = 0;
NCR5380_write(hostdata->c400_ctl_status, CSR_BASE);
NCR5380_write(hostdata->c400_blk_cnt, len / 128);
do { if (NCR5380_poll_politely2(hostdata, hostdata->c400_ctl_status,
CSR_HOST_BUF_NOT_RDY, 0,
hostdata->c400_ctl_status,
CSR_GATED_53C80_IRQ,
CSR_GATED_53C80_IRQ, 0) < 0 ||
NCR5380_read(hostdata->c400_ctl_status) & CSR_HOST_BUF_NOT_RDY) { /* Both 128 B buffers are in use */ if (start >= 128)
start -= 128; if (start >= 128)
start -= 128; break;
}
if (start >= len && NCR5380_read(hostdata->c400_blk_cnt) == 0) break;
if (NCR5380_read(hostdata->c400_ctl_status) & CSR_GATED_53C80_IRQ) { /* Host buffer is empty, other one is in use */ if (start >= 128)
start -= 128; break;
}
if (hostdata->flags & FLAG_NO_PSEUDO_DMA) return 0;
/* 53C400 datasheet: non-modulo-128-byte transfers should use PIO */ if (transfersize % 128) return 0;
/* Limit PDMA send to 512 B to avoid random corruption on DTC3181E */ if (hostdata->board == BOARD_DTC3181E &&
cmd->sc_data_direction == DMA_TO_DEVICE)
transfersize = min(transfersize, 512);
staticint generic_NCR5380_isa_match(struct device *pdev, unsignedint ndev)
{ int ret = generic_NCR5380_init_one(&driver_template, pdev, base[ndev],
irq[ndev], card[ndev]); if (ret) { if (base[ndev])
printk(KERN_WARNING "Card not found at address 0x%03x\n",
base[ndev]); return 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.