drivers/ata/pdc_adma.c

Source file repositories/reference/linux-study-clean/drivers/ata/pdc_adma.c

File Facts

System
Linux kernel
Corpus path
drivers/ata/pdc_adma.c
Extension
.c
Size
15230 bytes
Lines
608
Domain
Driver Families
Bucket
drivers/ata
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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.

Dependency Surface

Detected Declarations

Annotated Snippet

static struct pci_driver adma_ata_pci_driver = {
	.name			= DRV_NAME,
	.id_table		= adma_ata_pci_tbl,
	.probe			= adma_ata_init_one,
	.remove			= ata_pci_remove_one,
};

static int adma_check_atapi_dma(struct ata_queued_cmd *qc)
{
	return 1;	/* ATAPI DMA not yet supported */
}

static void adma_reset_engine(struct ata_port *ap)
{
	void __iomem *chan = ADMA_PORT_REGS(ap);

	/* reset ADMA to idle state */
	writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
	udelay(2);
	writew(aPIOMD4, chan + ADMA_CONTROL);
	udelay(2);
}

static void adma_reinit_engine(struct ata_port *ap)
{
	struct adma_port_priv *pp = ap->private_data;
	void __iomem *chan = ADMA_PORT_REGS(ap);

	/* mask/clear ATA interrupts */
	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
	ata_sff_check_status(ap);

	/* reset the ADMA engine */
	adma_reset_engine(ap);

	/* set in-FIFO threshold to 0x100 */
	writew(0x100, chan + ADMA_FIFO_IN);

	/* set CPB pointer */
	writel((u32)pp->pkt_dma, chan + ADMA_CPB_NEXT);

	/* set out-FIFO threshold to 0x100 */
	writew(0x100, chan + ADMA_FIFO_OUT);

	/* set CPB count */
	writew(1, chan + ADMA_CPB_COUNT);

	/* read/discard ADMA status */
	readb(chan + ADMA_STATUS);
}

static inline void adma_enter_reg_mode(struct ata_port *ap)
{
	void __iomem *chan = ADMA_PORT_REGS(ap);

	writew(aPIOMD4, chan + ADMA_CONTROL);
	readb(chan + ADMA_STATUS);	/* flush */
}

static void adma_freeze(struct ata_port *ap)
{
	void __iomem *chan = ADMA_PORT_REGS(ap);

	/* mask/clear ATA interrupts */
	writeb(ATA_NIEN, ap->ioaddr.ctl_addr);
	ata_sff_check_status(ap);

	/* reset ADMA to idle state */
	writew(aPIOMD4 | aNIEN | aRSTADM, chan + ADMA_CONTROL);
	udelay(2);
	writew(aPIOMD4 | aNIEN, chan + ADMA_CONTROL);
	udelay(2);
}

static void adma_thaw(struct ata_port *ap)
{
	adma_reinit_engine(ap);
}

static int adma_prereset(struct ata_link *link, unsigned long deadline)
{
	struct ata_port *ap = link->ap;
	struct adma_port_priv *pp = ap->private_data;

	if (pp->state != adma_state_idle) /* healthy paranoia */
		pp->state = adma_state_mmio;
	adma_reinit_engine(ap);

	return ata_sff_prereset(link, deadline);
}

Annotation

Implementation Notes