103 lines
3.4 KiB
C
103 lines
3.4 KiB
C
// ide.h - shared IDE/ATA driver internals.
|
||
#pragma once
|
||
|
||
#include <stdint.h>
|
||
#include <string.h>
|
||
#include <intrin.h>
|
||
#include <ntlite/ddi/io_driver.h>
|
||
#include <ntlite/ddi/hal_api.h>
|
||
#include <kernel/ke_debug.h>
|
||
#include <kernel/ke_sched.h>
|
||
#include <kernel/ke_irp.h>
|
||
#include <kernel/ke_event.h>
|
||
#include <kernel/ke_semaphore.h>
|
||
#include <kernel/ke_thread.h>
|
||
#include <kernel/ke_irq.h>
|
||
#include <kernel/ke_dpc.h>
|
||
#include <kernel/mm_phys.h>
|
||
#include <kernel/mm_virt.h>
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// IDE register map (primary channel, base 0x1F0)
|
||
// ---------------------------------------------------------------------------
|
||
#define IDE_DATA 0x1F0
|
||
#define IDE_ERR 0x1F1
|
||
#define IDE_SECCNT 0x1F2
|
||
#define IDE_LBA0 0x1F3
|
||
#define IDE_LBA1 0x1F4
|
||
#define IDE_LBA2 0x1F5
|
||
#define IDE_DRIVE 0x1F6
|
||
#define IDE_STATUS 0x1F7
|
||
#define IDE_CMD 0x1F7
|
||
#define IDE_ALT 0x3F6
|
||
|
||
#define IDE_BUSY 0x80
|
||
#define IDE_READY 0x40
|
||
#define IDE_ERR_F 0x01
|
||
#define IDE_DRQ 0x08
|
||
|
||
// ATA commands
|
||
#define CMD_READ_EXT 0x24 // PIO 48-bit read
|
||
#define CMD_WRITE_EXT 0x34 // PIO 48-bit write
|
||
#define CMD_READ_DMA_EXT 0x25 // DMA 48-bit read
|
||
#define CMD_WRITE_DMA_EXT 0x35 // DMA 48-bit write
|
||
#define CMD_READ_DMA 0xC8 // DMA 28-bit read
|
||
#define CMD_WRITE_DMA 0xCA // DMA 28-bit write
|
||
#define CMD_IDENT 0xEC
|
||
|
||
// IDE primary IRQ
|
||
#define IDE_IRQ_PRIMARY 14
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Bus Master IDE register offsets (relative to gBmBase, primary channel)
|
||
// ---------------------------------------------------------------------------
|
||
#define BM_CMD_REG 0x00 // command
|
||
#define BM_STATUS_REG 0x02 // status
|
||
#define BM_PRDT_REG 0x04 // PRDT physical address (32-bit)
|
||
|
||
// BM_CMD_REG bits
|
||
#define BM_CMD_START 0x01 // start DMA transfer
|
||
#define BM_CMD_READ 0x08 // 1 = disk→memory (read), 0 = memory→disk (write)
|
||
|
||
// BM_STATUS_REG bits
|
||
#define BM_STATUS_ACTIVE 0x01 // DMA active
|
||
#define BM_STATUS_ERROR 0x02 // DMA error (write 1 to clear)
|
||
#define BM_STATUS_IRQ 0x04 // interrupt pending (write 1 to clear)
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Physical Region Descriptor (PRDT entry, 8 bytes)
|
||
// The PRDT itself must not cross a 64 KB boundary and must be 4-byte aligned.
|
||
// We allocate a full page so both constraints are trivially satisfied.
|
||
// ---------------------------------------------------------------------------
|
||
#pragma pack(push, 1)
|
||
typedef struct {
|
||
uint32_t physAddr; // physical base of this memory region
|
||
uint16_t byteCount; // byte count; 0 means 64 KB
|
||
uint16_t flags; // bit 15: End Of Table
|
||
} PRD;
|
||
#pragma pack(pop)
|
||
|
||
#define PRD_EOT 0x8000u
|
||
// 512 entries × 8 bytes = 4096 bytes = exactly one page; supports 512×64 KB = 32 MB
|
||
#define PRDT_MAX_ENTRIES 512
|
||
|
||
|
||
extern const HAL_API *gHal;
|
||
extern DRIVER_OBJECT gDriver;
|
||
extern DEVICE_OBJECT *gDevice;
|
||
extern bool gDmaEnabled;
|
||
extern uint64_t gSectorCount;
|
||
extern bool gSupportsLba48;
|
||
extern uint16_t gBmBase;
|
||
extern PRD *gPrdtVirt;
|
||
extern uint32_t gPrdtPhys;
|
||
extern IRP_QUEUE gIrpQueue;
|
||
extern SEMAPHORE *gIrpSemaphore;
|
||
extern EVENT *gDmaEvent;
|
||
extern KDPC gDmaDpc;
|
||
|
||
void IdeDmaCompletionDpc(KDPC *dpc, void *context, void *systemArgument1, void *systemArgument2);
|
||
void IdeIsr(void);
|
||
void IdeWorker(uintptr_t arg);
|
||
bool IdeDmaInit(void);
|