AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
dma.c File Reference

ATA bus master DMA, for IDE controllers that can (such as QEMU's PIIX). More...

#include <core/system.h>
#include <core/string.h>
#include <cpu/io.h>
#include <mm/mm.h>
#include <sys/sched.h>
#include <aquila/errno.h>
#include <ata.h>

Go to the source code of this file.

Data Structures

struct  prd
 A physical region descriptor: one piece of memory to transfer. More...

Macros

#define BM_CMD   0
#define BM_STATUS   2
#define BM_PRDT   4
#define BM_CMD_START   0x01
#define BM_CMD_READ   0x08
#define BM_ST_ACTIVE   0x01
#define BM_ST_ERROR   0x02
#define BM_ST_IRQ   0x04
#define DMA_BUF_SIZE   (64 * 1024)
#define DMA_MAX_SECTORS   (DMA_BUF_SIZE / 512)
#define PRD_EOT   0x8000

Functions

static int channel_index (struct ata_drive *drive)
 Returns which channel a drive is on: 0 (primary) or 1 (secondary).
static void dma_complete (struct ata_channel *ch, uint8_t bm_status)
 Ends a transfer: keeps what the controller and the drive say about it, which also acknowledges the interrupt, and marks it done.
void dma_irq (struct ata_channel *ch)
 Handles a channel's interrupt.
static int dma_transfer (struct ata_drive *drive, uint64_t lba, size_t count, int write)
 Transfers up to DMA_MAX_SECTORS sectors between the drive and the channel's buffer, and waits until it is done.
static ssize_t dma_read (struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
 Reads count sectors from lba on, through the channel's buffer.
static ssize_t dma_write (struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
 Writes count sectors from lba on, through the channel's buffer.
int dma_init (struct ata_drive *drive)
 Sets a drive up for DMA, if both the drive and its channel's controller can do it.

Variables

static struct prd prdt [2]
static char dma_buf [2][DMA_BUF_SIZE]

Detailed Description

ATA bus master DMA, for IDE controllers that can (such as QEMU's PIIX).

With DMA, the controller moves a command's data to or from memory itself, and the request sleeps until the drive's interrupt says it is done. With PIO (pio.c), the CPU moves the data a word at a time through an I/O port and polls, which under a hypervisor means an exit to it every time.

Each channel transfers through a buffer of its own, which is physically contiguous and doesn't cross a 64 KiB boundary, as the controller requires. One physical region descriptor (PRD) describes it.

Definition in file dma.c.

Macro Definition Documentation

◆ BM_CMD

#define BM_CMD   0

Definition at line 25 of file dma.c.

Referenced by dma_transfer().

◆ BM_CMD_READ

#define BM_CMD_READ   0x08

Definition at line 30 of file dma.c.

Referenced by dma_transfer().

◆ BM_CMD_START

#define BM_CMD_START   0x01

Definition at line 29 of file dma.c.

Referenced by dma_transfer().

◆ BM_PRDT

#define BM_PRDT   4

Definition at line 27 of file dma.c.

Referenced by dma_transfer().

◆ BM_ST_ACTIVE

#define BM_ST_ACTIVE   0x01

Definition at line 32 of file dma.c.

◆ BM_ST_ERROR

#define BM_ST_ERROR   0x02

Definition at line 33 of file dma.c.

Referenced by dma_complete(), and dma_transfer().

◆ BM_ST_IRQ

#define BM_ST_IRQ   0x04

Definition at line 34 of file dma.c.

Referenced by dma_complete(), dma_irq(), and dma_transfer().

◆ BM_STATUS

#define BM_STATUS   2

Definition at line 26 of file dma.c.

Referenced by dma_complete(), dma_irq(), and dma_transfer().

◆ DMA_BUF_SIZE

#define DMA_BUF_SIZE   (64 * 1024)

Definition at line 36 of file dma.c.

◆ DMA_MAX_SECTORS

#define DMA_MAX_SECTORS   (DMA_BUF_SIZE / 512)

Definition at line 37 of file dma.c.

Referenced by dma_read(), and dma_write().

◆ PRD_EOT

#define PRD_EOT   0x8000

Definition at line 46 of file dma.c.

Referenced by dma_transfer().

Function Documentation

◆ channel_index()

int channel_index ( struct ata_drive * drive)
static

Returns which channel a drive is on: 0 (primary) or 1 (secondary).

Definition at line 54 of file dma.c.

References channel_index(), and ata_drive::id.

Referenced by channel_index(), dma_read(), dma_transfer(), and dma_write().

◆ dma_complete()

void dma_complete ( struct ata_channel * ch,
uint8_t bm_status )
static

Ends a transfer: keeps what the controller and the drive say about it, which also acknowledges the interrupt, and marks it done.

Definition at line 61 of file dma.c.

References ATA_REG_STATUS, ata_channel::base, ata_channel::bm, BM_ST_ERROR, BM_ST_IRQ, BM_STATUS, ata_channel::bm_status, dma_complete(), ata_channel::done, io_in8(), io_out8(), and ata_channel::status.

Referenced by dma_complete(), dma_irq(), and dma_transfer().

◆ dma_init()

int dma_init ( struct ata_drive * drive)

Sets a drive up for DMA, if both the drive and its channel's controller can do it.

Parameters
drivethe drive
Returns
0 if the drive uses DMA now, or -ENODEV if it can't

Definition at line 195 of file dma.c.

References ioaddr::addr, ATA_CAP_DMA, ata_channel::bm, ata_drive::capabilities, ata_drive::channel, dma_init(), dma_read(), dma_write(), ata_drive::read, and ata_drive::write.

Referenced by ata_probe(), and dma_init().

◆ dma_irq()

void dma_irq ( struct ata_channel * ch)

Handles a channel's interrupt.

If it ends a DMA transfer, the request waiting for it wakes up; otherwise (PIO polls) reading the drive's status acknowledges it.

Parameters
chthe channel

Definition at line 76 of file dma.c.

References ioaddr::addr, ATA_REG_STATUS, ata_channel::base, ata_channel::bm, BM_ST_IRQ, BM_STATUS, dma_complete(), dma_irq(), io_in8(), ata_channel::irq_wait, and waitq_wakeup_nopoll().

Referenced by ata_irq(), and dma_irq().

◆ dma_read()

ssize_t dma_read ( struct ata_drive * drive,
uint64_t lba,
size_t count,
void * buf )
static

Reads count sectors from lba on, through the channel's buffer.

Returns 0 or a negative errno.

Definition at line 144 of file dma.c.

References channel_index(), dma_buf, DMA_MAX_SECTORS, dma_read(), dma_transfer(), memcpy(), and MIN.

Referenced by dma_init(), and dma_read().

◆ dma_transfer()

◆ dma_write()

ssize_t dma_write ( struct ata_drive * drive,
uint64_t lba,
size_t count,
void * buf )
static

Writes count sectors from lba on, through the channel's buffer.

Returns 0 or a negative errno.

Definition at line 167 of file dma.c.

References channel_index(), dma_buf, DMA_MAX_SECTORS, dma_transfer(), dma_write(), memcpy(), and MIN.

Referenced by dma_init(), and dma_write().

Variable Documentation

◆ dma_buf

char dma_buf[2][DMA_BUF_SIZE]
static

Definition at line 51 of file dma.c.

Referenced by dma_read(), dma_transfer(), and dma_write().

◆ prdt

struct prd prdt[2]
static

Definition at line 50 of file dma.c.

Referenced by dma_transfer().