|
AquilaOS documentation
How it works, and its code
|
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] |
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.
| #define BM_CMD 0 |
Definition at line 25 of file dma.c.
Referenced by dma_transfer().
| #define BM_CMD_READ 0x08 |
Definition at line 30 of file dma.c.
Referenced by dma_transfer().
| #define BM_CMD_START 0x01 |
Definition at line 29 of file dma.c.
Referenced by dma_transfer().
| #define BM_PRDT 4 |
Definition at line 27 of file dma.c.
Referenced by dma_transfer().
| #define BM_ST_ERROR 0x02 |
Definition at line 33 of file dma.c.
Referenced by dma_complete(), and dma_transfer().
| #define BM_ST_IRQ 0x04 |
Definition at line 34 of file dma.c.
Referenced by dma_complete(), dma_irq(), and dma_transfer().
| #define BM_STATUS 2 |
Definition at line 26 of file dma.c.
Referenced by dma_complete(), dma_irq(), and dma_transfer().
| #define DMA_MAX_SECTORS (DMA_BUF_SIZE / 512) |
Definition at line 37 of file dma.c.
Referenced by dma_read(), and dma_write().
| #define PRD_EOT 0x8000 |
Definition at line 46 of file dma.c.
Referenced by dma_transfer().
|
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().
|
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().
| 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.
| drive | the drive |
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().
| 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.
| ch | the 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().
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().
Transfers up to DMA_MAX_SECTORS sectors between the drive and the channel's buffer, and waits until it is done.
Returns 0, or -EIO if the controller or the drive reports an error.
Definition at line 93 of file dma.c.
References prd::addr, ATA_CMD_READ_DMA, ATA_CMD_READ_DMA_EXT, ATA_CMD_WRITE_DMA, ATA_CMD_WRITE_DMA_EXT, ATA_MODE_LBA48, ATA_REG_CMD, ata_setup(), ATA_STATUS_DF, ATA_STATUS_ERR, ata_drive::base, ata_channel::bm, BM_CMD, BM_CMD_READ, BM_CMD_START, BM_PRDT, BM_ST_ERROR, BM_ST_IRQ, BM_STATUS, ata_channel::bm_status, ata_drive::channel, channel_index(), curthread, dma_buf, dma_complete(), dma_transfer(), ata_channel::done, prd::flags, ata_drive::id, io_in8(), io_out32(), io_out8(), ata_channel::irq_wait, LMA, ata_drive::mode, PRD_EOT, prdt, printk(), sched_running, prd::size, ata_channel::status, and waitq_sleep_unint().
Referenced by dma_read(), dma_transfer(), and dma_write().
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().
|
static |
Definition at line 51 of file dma.c.
Referenced by dma_read(), dma_transfer(), and dma_write().
|
static |
Definition at line 50 of file dma.c.
Referenced by dma_transfer().