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

The ATA driver: hard disks on the IDE controller, as block device 3 (/dev/hda and up). More...

#include <core/system.h>
#include <core/module.h>
#include <core/kargs.h>
#include <cpu/io.h>
#include <dev/dev.h>
#include <fs/vfs.h>
#include <fs/devfs.h>
#include <fs/posix.h>
#include <fs/mbr.h>
#include <aquila/errno.h>
#include <dev/pci.h>
#include <dev/blkcache.h>
#include <dev/irq.h>
#include <sys/sched.h>
#include <ata.h>

Go to the source code of this file.

Macros

#define BLOCK_SIZE   512UL

Functions

static void channel_acquire (struct ata_channel *ch)
 Takes a channel for one command, waiting while another runs (a DMA request sleeps).
static void channel_release (struct ata_channel *ch)
 Gives a channel back, and wakes up the requests waiting for it.
static ssize_t drive_read (void *_drive, uint64_t lba, size_t count, void *buf)
 Reads sectors from a drive, for the block cache: the channel is held for the command only, and the buffer is the cache's.
static ssize_t drive_write (void *_drive, uint64_t lba, size_t count, void *buf)
 Writes sectors to a drive, for the block cache.
static void ata_irq (void *channel)
 Handles a channel's interrupt.
void ata_reset (struct ata_drive *drive)
 Resets both drives on a drive's channel, and waits until they are done.
void ata_select_drive (struct ata_drive *drive, uint32_t mode)
 Selects a drive on its channel, for an addressing mode, if it isn't selected so already, and waits for the drive to take it.
void ata_setup (struct ata_drive *drive, uint64_t lba, size_t count)
 Writes the registers of a command on count sectors from lba: the drive, the address and the count.
static int ata_partition (struct ata_drive *drive, size_t part, uint64_t *start, uint64_t *nsectors)
 Finds partition part of a drive (1 to 4; 0 is the whole disk): its first sector and how many sectors it has, from the MBR, which is read once.
static int ata_locate (struct devid *dd, int write, struct ata_drive **ref, uint64_t *start, uint64_t *nsectors)
 Finds the drive of a device number, and where its partition is on it.
static ssize_t ata_read (struct devid *dd, off_t offset, size_t size, void *buf)
 Reads sectors of a partition, from sector offset on, through the block cache.
static ssize_t ata_write (struct devid *dd, off_t offset, size_t size, void *buf)
 Writes sectors of a partition, from sector offset on, through the block cache.
static int ata_drive_present (struct ata_drive *drive)
 Returns whether the selected drive is there.
static uint8_t ata_detect_drive (struct ata_drive *drive)
 Detects what a drive is (ATADEV_*).
static int ata_sync (void)
 Has every drive write what its cache holds to the disk, for sync().
static size_t ata_getbs (struct devid *dd)
 Returns the block size: one sector, 512 bytes.
static int ata_probe ()
 Finds the IDE controller, detects its drives, sets them up, and registers the disks as block device 3.

Variables

static struct ata_drive drives [4]
static struct ata_channel channels [2]
static struct ata_drive * last_selected_drive = NULL
static uint32_t last_selected_mode = -1
struct dev atadev

Detailed Description

The ATA driver: hard disks on the IDE controller, as block device 3 (/dev/hda and up).

The driver finds the IDE controller on the PCI bus, detects the four drives its two channels may have, and moves their sectors by PIO (pio.c) or bus master DMA (dma.c). Minor numbers are 64 per drive: 0 is the whole disk, 1 to 4 its primary partitions, from the MBR. Reads and writes go through the block cache (blkcache.c). One command at a time runs on a channel. Only ATA hard disks are supported: not ATAPI (CD-ROMs), and not SATA's own interface.

Definition in file ata.c.

Macro Definition Documentation

◆ BLOCK_SIZE

#define BLOCK_SIZE   512UL

Definition at line 33 of file ata.c.

Referenced by ata_getbs(), and ata_partition().

Function Documentation

◆ ata_detect_drive()

◆ ata_drive_present()

int ata_drive_present ( struct ata_drive * drive)
static

Returns whether the selected drive is there.

It must be called once the channel's reset is done. A floating bus (no drive on the channel) reads 0xFF, and a missing drive next to a present one reads 0.

Definition at line 308 of file ata.c.

References ata_drive_present(), ATA_REG_LBA1, ATA_REG_LBA2, ATA_REG_STATUS, ATA_STATUS_BSY, ATA_STATUS_DRDY, ata_drive::base, and io_in8().

Referenced by ata_detect_drive(), and ata_drive_present().

◆ ata_getbs()

size_t ata_getbs ( struct devid * dd)
static

Returns the block size: one sector, 512 bytes.

Definition at line 446 of file ata.c.

References ata_getbs(), and BLOCK_SIZE.

Referenced by ata_getbs().

◆ ata_irq()

void ata_irq ( void * channel)
static

Handles a channel's interrupt.

Definition at line 82 of file ata.c.

References ata_irq(), ata_drive::channel, and dma_irq().

Referenced by ata_irq(), and ata_probe().

◆ ata_locate()

int ata_locate ( struct devid * dd,
int write,
struct ata_drive ** ref,
uint64_t * start,
uint64_t * nsectors )
static

Finds the drive of a device number, and where its partition is on it.

Returns 0 or a negative errno (-ENXIO if there is no such drive or partition).

Definition at line 240 of file ata.c.

References ata_locate(), ata_partition(), ata_drive::channel, channel_acquire(), channel_release(), drives, devid::minor, ata_drive::read, and ata_drive::write.

Referenced by ata_locate(), ata_read(), and ata_write().

◆ ata_partition()

int ata_partition ( struct ata_drive * drive,
size_t part,
uint64_t * start,
uint64_t * nsectors )
static

Finds partition part of a drive (1 to 4; 0 is the whole disk): its first sector and how many sectors it has, from the MBR, which is read once.

Returns 0, -ENXIO if the MBR has no partition there (no signature, an empty entry, or one past the disk's end), -EIO if the MBR can't be read, or -ENOMEM.

The MBR is read into a buffer of its own: lookups on the two channels may run at once, each sleeping while its read is done.

Definition at line 192 of file ata.c.

References ata_partition(), BLOCK_SIZE, mbr::boot_signature, kfree(), kmalloc(), ata_drive::max_lba, ata_drive::poff, ata_drive::psize, mbr::ptab, ata_drive::read, mbr_part::sectors_count, mbr_part::start_lba, and mbr_part::type.

Referenced by ata_locate(), and ata_partition().

◆ ata_probe()

◆ ata_read()

ssize_t ata_read ( struct devid * dd,
off_t offset,
size_t size,
void * buf )
static

Reads sectors of a partition, from sector offset on, through the block cache.

Returns how many were read (none past the partition's end), or a negative errno.

Definition at line 266 of file ata.c.

References ata_locate(), ata_read(), blkcache_read(), drive_read(), ata_drive::max_lba, and MIN.

Referenced by ata_read().

◆ ata_reset()

void ata_reset ( struct ata_drive * drive)

Resets both drives on a drive's channel, and waits until they are done.

Parameters
drivea drive on the channel

Definition at line 97 of file ata.c.

References ATA_CMD_RESET, ATA_REG_HDDEVSEL, ata_reset(), ATA_STATUS_BSY, ATA_TIMEOUT, ata_drive::base, ata_drive::ctrl, io_in8(), io_out8(), last_selected_drive, last_selected_mode, and NULL.

Referenced by ata_detect_drive(), ata_reset(), and pio_init().

◆ ata_select_drive()

void ata_select_drive ( struct ata_drive * drive,
uint32_t mode )

Selects a drive on its channel, for an addressing mode, if it isn't selected so already, and waits for the drive to take it.

Parameters
drivethe drive
modethe addressing mode (ATA_MODE_*), or 0 to detect it

Definition at line 126 of file ata.c.

References ATA_MODE_LBA28, ATA_MODE_LBA48, ATA_REG_HDDEVSEL, ata_select_drive(), ata_drive::base, io_out8(), last_selected_drive, last_selected_mode, ata_drive::mode, and ata_drive::slave.

Referenced by ata_detect_drive(), ata_select_drive(), ata_setup(), and pio_flush().

◆ ata_setup()

void ata_setup ( struct ata_drive * drive,
uint64_t lba,
size_t count )

Writes the registers of a command on count sectors from lba: the drive, the address and the count.

The command itself is sent after.

Parameters
drivethe drive
lbathe first sector
counthow many sectors

Definition at line 155 of file ata.c.

References ATA_MODE_LBA48, ATA_REG_ERROR, ATA_REG_HDDEVSEL, ATA_REG_LBA0, ATA_REG_LBA1, ATA_REG_LBA2, ATA_REG_SECCOUNT0, ata_select_drive(), ata_setup(), ata_drive::base, io_out8(), ata_drive::mode, and ata_drive::slave.

Referenced by ata_setup(), dma_transfer(), pio_read_sectors(), and pio_write_sectors().

◆ ata_sync()

int ata_sync ( void )
static

Has every drive write what its cache holds to the disk, for sync().

Returns 0, or -EIO if a drive failed.

Definition at line 428 of file ata.c.

References ata_sync(), ata_drive::channel, channel_acquire(), channel_release(), drives, and flush().

Referenced by ata_sync().

◆ ata_write()

ssize_t ata_write ( struct devid * dd,
off_t offset,
size_t size,
void * buf )
static

Writes sectors of a partition, from sector offset on, through the block cache.

Returns how many were written (none past the partition's end: -ENOSPC), or a negative errno.

Definition at line 287 of file ata.c.

References ata_locate(), ata_write(), blkcache_write(), drive_write(), and MIN.

Referenced by ata_write().

◆ channel_acquire()

void channel_acquire ( struct ata_channel * ch)
static

Takes a channel for one command, waiting while another runs (a DMA request sleeps).

Before there are processes, nothing else runs. A signal doesn't end the wait: a transfer is never left halfway.

Definition at line 41 of file ata.c.

References ata_channel::busy, channel_acquire(), curthread, sched_running, ata_channel::wait, and waitq_sleep_unint().

Referenced by ata_locate(), ata_sync(), channel_acquire(), drive_read(), and drive_write().

◆ channel_release()

void channel_release ( struct ata_channel * ch)
static

Gives a channel back, and wakes up the requests waiting for it.

Definition at line 50 of file ata.c.

References ata_channel::busy, channel_release(), ata_channel::wait, and waitq_wakeup_nopoll().

Referenced by ata_locate(), ata_sync(), channel_release(), drive_read(), and drive_write().

◆ drive_read()

ssize_t drive_read ( void * _drive,
uint64_t lba,
size_t count,
void * buf )
static

Reads sectors from a drive, for the block cache: the channel is held for the command only, and the buffer is the cache's.

Definition at line 58 of file ata.c.

References ata_drive::channel, channel_acquire(), channel_release(), drive_read(), and ata_drive::read.

Referenced by ata_read(), and drive_read().

◆ drive_write()

ssize_t drive_write ( void * _drive,
uint64_t lba,
size_t count,
void * buf )
static

Writes sectors to a drive, for the block cache.

Definition at line 70 of file ata.c.

References ata_drive::channel, channel_acquire(), channel_release(), drive_write(), and ata_drive::write.

Referenced by ata_write(), and drive_write().

Variable Documentation

◆ atadev

struct dev atadev
Initial value:
= {
.name = "ata",
.probe = ata_probe,
.bread = ata_read,
.bwrite = ata_write,
.getbs = ata_getbs,
.sync = ata_sync,
.fops = {
.open = posix_file_open,
.read = posix_file_read,
.write = posix_file_write,
},
}
static size_t ata_getbs(struct devid *dd)
Returns the block size: one sector, 512 bytes.
Definition ata.c:446
static ssize_t ata_read(struct devid *dd, off_t offset, size_t size, void *buf)
Reads sectors of a partition, from sector offset on, through the block cache.
Definition ata.c:266
static int ata_probe()
Finds the IDE controller, detects its drives, sets them up, and registers the disks as block device 3...
Definition ata.c:453
static int ata_sync(void)
Has every drive write what its cache holds to the disk, for sync().
Definition ata.c:428
static ssize_t ata_write(struct devid *dd, off_t offset, size_t size, void *buf)
Writes sectors of a partition, from sector offset on, through the block cache.
Definition ata.c:287
int posix_file_open(struct file *file)
Finishes opening a file: with O_TRUNC, a regular file is truncated to 0 bytes.
Definition open.c:17
ssize_t posix_file_read(struct file *file, struct iobuf *io)
Reads from an open file at its offset, and moves the offset past what was read.
Definition read.c:29
ssize_t posix_file_write(struct file *file, struct iobuf *io)
Writes to an open file at its offset, and moves the offset past what was written.
Definition write.c:25

Definition at line 592 of file ata.c.

Referenced by ata_probe().

◆ channels

struct ata_channel channels[2]
static

Definition at line 36 of file ata.c.

Referenced by ata_probe().

◆ drives

struct ata_drive drives[4]
static

Definition at line 35 of file ata.c.

Referenced by ata_locate(), ata_probe(), and ata_sync().

◆ last_selected_drive

struct ata_drive* last_selected_drive = NULL
static

Definition at line 89 of file ata.c.

Referenced by ata_reset(), and ata_select_drive().

◆ last_selected_mode

uint32_t last_selected_mode = -1
static

Definition at line 90 of file ata.c.

Referenced by ata_reset(), and ata_select_drive().