drivers/scsi/atari_scsi.c
Source file repositories/reference/linux-study-clean/drivers/scsi/atari_scsi.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/scsi/atari_scsi.c- Extension
.c- Size
- 27515 bytes
- Lines
- 899
- Domain
- Driver Families
- Bucket
- drivers/scsi
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/types.hlinux/blkdev.hlinux/interrupt.hlinux/init.hlinux/nvram.hlinux/bitops.hlinux/wait.hlinux/platform_device.hasm/setup.hasm/atarihw.hasm/atariints.hasm/atari_stdma.hasm/atari_stram.hasm/io.hscsi/scsi_host.hNCR5380.hNCR5380.c
Detected Declarations
function SCSI_DMA_SETADRfunction SCSI_DMA_GETADRfunction scsi_dma_is_ignored_buserrfunction scsi_tt_intrfunction scsi_falcon_intrfunction exactlyfunction atari_scsi_fetch_restbytesfunction falcon_release_lockfunction stdma_lockfunction atari_scsi_setupfunction atari_scsi_dma_setupfunction atari_scsi_dma_recv_setupfunction atari_scsi_dma_send_setupfunction atari_scsi_dma_residualfunction falcon_classify_cmdfunction atari_scsi_dma_xfer_lenfunction transferfunction atari_scsi_tt_reg_readfunction atari_scsi_tt_reg_writefunction atari_scsi_falcon_reg_readfunction atari_scsi_falcon_reg_writefunction atari_scsi_host_resetfunction atari_scsi_probefunction Medusafunction atari_scsi_remove
Annotated Snippet
if (!scsi_dma_is_ignored_buserr(dma_stat)) {
printk(KERN_ERR "SCSI DMA caused bus error near 0x%08lx\n",
SCSI_DMA_READ_P(dma_addr));
printk(KERN_CRIT "SCSI DMA bus error -- bad DMA programming!");
}
}
/* If the DMA is active but not finished, we have the case
* that some other 5380 interrupt occurred within the DMA transfer.
* This means we have residual bytes, if the desired end address
* is not yet reached. Maybe we have to fetch some bytes from the
* rest data register, too. The residual must be calculated from
* the address pointer, not the counter register, because only the
* addr reg counts bytes not yet written and pending in the rest
* data reg!
*/
if ((dma_stat & 0x02) && !(dma_stat & 0x40)) {
atari_dma_residual = hostdata->dma_len -
(SCSI_DMA_READ_P(dma_addr) - atari_dma_startaddr);
dprintk(NDEBUG_DMA, "SCSI DMA: There are %ld residual bytes.\n",
atari_dma_residual);
if ((signed int)atari_dma_residual < 0)
atari_dma_residual = 0;
if ((dma_stat & 1) == 0) {
/*
* After read operations, we maybe have to
* transport some rest bytes
*/
atari_scsi_fetch_restbytes();
} else {
/*
* There seems to be a nasty bug in some SCSI-DMA/NCR
* combinations: If a target disconnects while a write
* operation is going on, the address register of the
* DMA may be a few bytes farer than it actually read.
* This is probably due to DMA prefetching and a delay
* between DMA and NCR. Experiments showed that the
* dma_addr is 9 bytes to high, but this could vary.
* The problem is, that the residual is thus calculated
* wrong and the next transfer will start behind where
* it should. So we round up the residual to the next
* multiple of a sector size, if it isn't already a
* multiple and the originally expected transfer size
* was. The latter condition is there to ensure that
* the correction is taken only for "real" data
* transfers and not for, e.g., the parameters of some
* other command. These shouldn't disconnect anyway.
*/
if (atari_dma_residual & 0x1ff) {
dprintk(NDEBUG_DMA, "SCSI DMA: DMA bug corrected, "
"difference %ld bytes\n",
512 - (atari_dma_residual & 0x1ff));
atari_dma_residual = (atari_dma_residual + 511) & ~0x1ff;
}
}
tt_scsi_dma.dma_ctrl = 0;
}
/* If the DMA is finished, fetch the rest bytes and turn it off */
if (dma_stat & 0x40) {
atari_dma_residual = 0;
if ((dma_stat & 1) == 0)
atari_scsi_fetch_restbytes();
tt_scsi_dma.dma_ctrl = 0;
}
NCR5380_intr(irq, dev);
return IRQ_HANDLED;
}
static irqreturn_t scsi_falcon_intr(int irq, void *dev)
{
struct Scsi_Host *instance = dev;
struct NCR5380_hostdata *hostdata = shost_priv(instance);
int dma_stat;
/* Turn off DMA and select sector counter register before
* accessing the status register (Atari recommendation!)
*/
st_dma.dma_mode_status = 0x90;
dma_stat = st_dma.dma_mode_status;
/* Bit 0 indicates some error in the DMA process... don't know
* what happened exactly (no further docu).
*/
if (!(dma_stat & 0x01)) {
Annotation
- Immediate include surface: `linux/module.h`, `linux/types.h`, `linux/blkdev.h`, `linux/interrupt.h`, `linux/init.h`, `linux/nvram.h`, `linux/bitops.h`, `linux/wait.h`.
- Detected declarations: `function SCSI_DMA_SETADR`, `function SCSI_DMA_GETADR`, `function scsi_dma_is_ignored_buserr`, `function scsi_tt_intr`, `function scsi_falcon_intr`, `function exactly`, `function atari_scsi_fetch_restbytes`, `function falcon_release_lock`, `function stdma_lock`, `function atari_scsi_setup`.
- Atlas domain: Driver Families / drivers/scsi.
- Implementation status: source implementation candidate.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.