24#include <aquila/errno.h>
33#define BLOCK_SIZE 512UL
173 0xE0 | (drive->
slave << 4) | ((lba >> 24) & 0xF));
202 if (!drive->
psize[part]) {
208 if (drive->
read(drive, 0, 1, buf) < 0) {
232 *start = drive->
poff[part];
233 *nsectors = drive->
psize[part];
244 size_t drive_id = dd->
minor / 64;
245 size_t partition = dd->
minor % 64;
247 if (drive_id >= 4 || partition > 4)
272 if ((err =
ata_locate(dd, 0, &drive, &start, &nsectors)))
278 size =
MIN(size, nsectors - offset);
281 return err < 0 ? err : (
ssize_t) size;
293 if ((err =
ata_locate(dd, 1, &drive, &start, &nsectors)))
297 return size ? -ENOSPC : 0;
299 size =
MIN(size, nsectors - offset);
302 return err < 0 ? err : (
ssize_t) size;
323 return (lba1 == 0x14 && lba2 == 0xEB) || (lba1 == 0x69 && lba2 == 0x96);
380 memset(ide_ident, 0,
sizeof(ide_ident));
390 for (
int i = 0; i < 512; i += 2) {
392 ide_ident[i+0] = x & 0xFFFF;
393 ide_ident[i+1] = (x >> 8) & 0xFFFF;
410 for (
int i = 0; i < 40; i += 2) {
414 drive->
model[40] = 0;
432 for (
int i = 0; i < 4; ++i) {
458 printk(
"ata: scanning PCI bus for IDE controller(s)\n");
463 printk(
"ata: no IDE controller(s) found\n");
468 printk(
"ata: found IDE controller: bus: 0x%x, dev: 0x%x, func: 0x%x\n", ide.
bus, ide.
dev, ide.
func);
477 if (base == 0 || base == 1)
480 if (control == 0 || control == 1)
483 printk(
"ata: IDE controller primary channel: base: 0x%x, control: 0x%x\n", base, control);
511 if (base == 0 || base == 1)
514 if (control == 0 || control == 1)
517 printk(
"ata: IDE controller secondary channel: base: 0x%x, control: 0x%x\n", base, control);
525 if ((bm & 1) && (bm & ~3U)) {
532 printk(
"ata: bus master DMA at 0x%x\n", bm & ~3U);
535 for (
int i = 0; i < 4; ++i)
555 for (
int i = 0; i < 4 * count; ++i) {
562 printk(
"ata%d: initializing ATA device (%s)\n", i,
566 printk(
"ata%d: SATA is not supported\n", i);
569 printk(
"ata%d: PATAPI is not supported\n", i);
572 printk(
"ata%d: SATAPI is not supported\n", i);
static uint16_t io_in16(struct ioaddr *io, uintptr_t off)
static uint8_t io_in8(struct ioaddr *io, uintptr_t off)
Reads an 8-, 16- or 32-bit register.
static void io_out8(struct ioaddr *io, uintptr_t off, uint8_t val)
Writes an 8-, 16- or 32-bit register.
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,...
static void channel_acquire(struct ata_channel *ch)
Takes a channel for one command, waiting while another runs (a DMA request sleeps).
static size_t ata_getbs(struct devid *dd)
Returns the block size: one sector, 512 bytes.
static uint32_t last_selected_mode
static struct ata_drive * last_selected_drive
static struct ata_channel channels[2]
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 void channel_release(struct ata_channel *ch)
Gives a channel back, and wakes up the requests waiting for 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 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 ...
static void ata_irq(void *channel)
Handles a channel's interrupt.
static struct ata_drive drives[4]
static int ata_probe()
Finds the IDE controller, detects its drives, sets them up, and registers the disks as block device 3...
static uint8_t ata_detect_drive(struct ata_drive *drive)
Detects what a drive is (ATADEV_*).
void ata_reset(struct ata_drive *drive)
Resets both drives on a drive's channel, and waits until they are done.
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,...
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 drive_write(void *_drive, uint64_t lba, size_t count, void *buf)
Writes sectors to a drive, for the block cache.
static int ata_sync(void)
Has every drive write what its cache holds to the disk, for sync().
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.
void dma_irq(struct ata_channel *channel)
Handles a channel's interrupt.
#define ATA_PIO_SEC_PORT_BASE
void pio_init(struct ata_drive *drive)
Sets a drive up for PIO, and resets its channel.
#define ATA_IDENT_DEVICETYPE
#define ATA_PIO_PRI_PORT_CONTROL
#define ATA_IDENT_CAPABILITIES
#define ATA_PIO_SEC_PORT_CONTROL
#define ATA_IDENT_COMMANDSETS
#define ATA_IDENT_MAX_LBA_EXT
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.
#define ATA_CMD_IDENTIFY_PACKET
#define ATA_REG_SECCOUNT0
#define ATA_IDENT_MAX_LBA
#define ATA_PIO_PRI_PORT_BASE
ssize_t blkcache_read(void *owner, uint64_t sector, size_t count, void *buf, uint64_t nsectors, blkcache_io read)
Reads sectors of a disk through the cache.
ssize_t blkcache_write(void *owner, uint64_t sector, size_t count, void *buf, blkcache_io write)
Writes sectors of a disk through the cache: they stay dirty in it until it is flushed.
int kargs_get(const char *key, const char **value)
Looks up an argument of the kernel's command line.
void kdev_blkdev_register(devid_t major, struct dev *dev)
Registers a driver as the block device of a major number.
void * kmalloc(size_t size, struct malloc_type *type, int flags)
Allocates memory for one of the kernel's structures.
void kfree(void *)
Frees an object that kmalloc() gave.
void * memset(void *dst, int c, size_t n)
Sets n bytes to c.
#define MODULE_INIT(name, i, f)
int posix_file_open(struct file *file)
Finishes opening a file: with O_TRUNC, a regular file is truncated to 0 bytes.
int pci_irq(struct pci_dev *dev)
Finds the IRQ that a function's interrupt pin comes to.
uint16_t pci_reg16_read(struct pci_dev *dev, uint8_t off)
Reads a 16-bit configuration register.
int pci_scan_device(uint8_t class, uint8_t subclass, struct pci_dev *_dev, size_t nr)
Finds the functions of a class and subclass, on bus 0.
uint32_t pci_read_bar(struct pci_dev *dev, uint8_t id)
Reads a base address register as it is, flag bits included.
void pci_reg16_write(struct pci_dev *dev, uint8_t off, uint16_t val)
Writes a 16-bit configuration register: the 32-bit register it's in is read, changed and written back...
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.
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.
int printk(const char *fmt,...)
Writes a kernel message, to the message buffer and the consoles.
unsigned long long int uint64_t
unsigned short int uint16_t
An IDE channel, with the master and slave drives on it.
int busy
one command at a time: whether one is running, and the requests waiting for the channel
struct ioaddr base
the command block's registers, and the bus master's for DMA (whose address is 0 if the controller has...
ssize_t(*) read(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
struct ata_channel * channel
ssize_t(*) write(struct ata_drive *drive, uint64_t lba, size_t count, void *buf)
A device driver: its operations, any of which may be NULL.
Which device: its kind (S_IFCHR or S_IFBLK) and numbers.
Where a device's registers are.
A PCI function: its bus, device (slot) and function numbers.
static void flush(vaddr_t sva, vaddr_t eva)
Flushes [sva, eva) from the running CPU's TLB.
void waitq_wakeup_nopoll(struct waitq *waitq)
Wakes up every thread sleeping on a wait queue, but not the threads polling it.
void waitq_sleep_unint(struct waitq *waitq)
Puts the current thread to sleep on a wait queue until it is woken up, whatever signals come meanwhil...