ata pio mode

This commit is contained in:
Able 2024-12-07 10:44:29 -06:00
parent bcc7c827ab
commit df7982d9e5
4 changed files with 143 additions and 79 deletions

View file

@ -455,7 +455,8 @@ fn run(release: bool, target: Target, do_accel: bool) -> Result<(), Error> {
#[rustfmt::skip] #[rustfmt::skip]
com.args([ com.args([
"-bios", &ovmf_path.change_context(Error::OvmfFetch)?, "-bios", &ovmf_path.change_context(Error::OvmfFetch)?,
"-drive", "file=target/disk.img,format=raw", //"-hda", "target/disk.img",
"-drive", "file=target/disk.img,index=0,if=ide,format=raw",
"-device", "vmware-svga", "-device", "vmware-svga",
// "-serial", "stdio", // "-serial", "stdio",
"-m", "2G", "-m", "2G",

View file

@ -2,73 +2,121 @@
.{inb, outb} := memory .{inb, outb} := memory
regs := @use("regs.hb"); regs := @use("regs.hb");
.{ATA_PRIMARY_COMM_REGSTAT, ATA_PRIMARY_DRIVE_HEAD, ATA_PRIMARY_SECCOUNT, ATA_PRIMARY_LBA_LO, ATA_PRIMARY_LBA_MID, ATA_PRIMARY_LBA_HI, STAT_BSY} := regs .{ATA_PRIMARY_IO, ATA_PRIMARY_DEVCTL, ATA_SECONDARY_DEVCTL, ATA_REG_STAT, ATA_SR_ERR, ATA_SR_BSY, ATA_SR_DF, ATA_SR_DRQ} := regs
sloop := fn(i: u8): void {
// idx := 0xFFFFFFF
// loop {
// if idx == 0 {
// break
// } else {
// idx -= 1
// }
// }
sloop := fn(): void {
idx := 0xFFFFFFF
loop { loop {
if idx == 0 { if i == 0 {
break break
} else { } else {
idx -= 1 a := inb(ATA_SECONDARY_DEVCTL)
i -= 1
} }
} }
} }
identify := fn(): u8 { // identify := fn(): u8 {
a := inb(ATA_PRIMARY_COMM_REGSTAT) // a := inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_DRIVE_HEAD, 0xA0) // outb(ATA_PRIMARY_DRIVE_HEAD, 0xA0)
log.info("Primary drive head set.\0") // log.info("Primary drive head set.\0")
a = inb(ATA_PRIMARY_COMM_REGSTAT) // a = inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_SECCOUNT, 0) // outb(ATA_PRIMARY_SECCOUNT, 0)
a = inb(ATA_PRIMARY_COMM_REGSTAT) // a = inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_LBA_LO, 0) // outb(ATA_PRIMARY_LBA_LO, 0)
a = inb(ATA_PRIMARY_COMM_REGSTAT) // a = inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_LBA_MID, 0) // outb(ATA_PRIMARY_LBA_MID, 0)
a = inb(ATA_PRIMARY_COMM_REGSTAT) // a = inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_LBA_HI, 0) // outb(ATA_PRIMARY_LBA_HI, 0)
a = inb(ATA_PRIMARY_COMM_REGSTAT) // a = inb(ATA_PRIMARY_COMM_REGSTAT)
outb(ATA_PRIMARY_COMM_REGSTAT, 0xEC) // outb(ATA_PRIMARY_COMM_REGSTAT, 0xEC)
outb(ATA_PRIMARY_COMM_REGSTAT, 0xE7) // outb(ATA_PRIMARY_COMM_REGSTAT, 0xE7)
status := inb(ATA_PRIMARY_COMM_REGSTAT) // status := inb(ATA_PRIMARY_COMM_REGSTAT)
log.info("Waiting for status.\0") // log.info("Waiting for status.\0")
// loop {
// if (status & STAT_BSY) == 0 {
// log.info("Status got.\0")
// break
// } else {
// sloop()
// }
// status = inb(ATA_PRIMARY_COMM_REGSTAT)
// }
// if status == 0 {
// log.error("No drive detected.\0")
// return 0
// }
// log.info("Status indicates presence of a drive. Polling while STAT_BSY... \0")
// loop {
// if (status & STAT_BSY) == 0 {
// log.info("Status got.\0")
// break
// } else {
// sloop()
// }
// status = inb(ATA_PRIMARY_COMM_REGSTAT)
// }
// mid := inb(ATA_PRIMARY_LBA_MID)
// hi := inb(ATA_PRIMARY_LBA_HI)
// if (mid | hi) == 0 {
// log.error("The drive is not ATA. (Who knows what it is.)\0")
// return 0
// }
// return 0
// }
drive_reset := fn(): void {
log.warn("Drive resetting.\0")
outb(ATA_PRIMARY_DEVCTL, 0x4)
sloop(4)
outb(ATA_PRIMARY_DEVCTL, 0x0)
}
poll := fn(): u8 {
sloop(4)
status := 0
// busy loop waiting for status
loop { loop {
if (status & STAT_BSY) == 0 { status = inb(ATA_PRIMARY_IO + ATA_REG_STAT)
log.info("Status got.\0") if (status & ATA_SR_BSY) == 0 {
break break
} else {
sloop()
} }
status = inb(ATA_PRIMARY_COMM_REGSTAT)
}
if status == 0 {
log.error("No drive detected.\0")
return 0
}
log.info("Status indicates presence of a drive. Polling while STAT_BSY... \0")
loop {
if (status & STAT_BSY) == 0 {
log.info("Status got.\0")
break
} else {
sloop()
}
status = inb(ATA_PRIMARY_COMM_REGSTAT)
} }
mid := inb(ATA_PRIMARY_LBA_MID) status = inb(ATA_PRIMARY_IO + ATA_REG_STAT)
hi := inb(ATA_PRIMARY_LBA_HI) if (status & ATA_SR_DF) == 0 {
log.error("ATA PRIMARY DRIVE FAULT\0")
return 1
}
if (mid | hi) == 0 { if (status & ATA_SR_ERR) == 0 {
log.error("The drive is not ATA. (Who knows what it is.)\0") log.error("ATA PRIMARY ERR\0")
return 0 return 2
}
if (status & ATA_SR_DRQ) == 0 {
log.error("ATA PRIMARY DRQ\0")
return 3
} }
return 0 return 0
} }
main := fn(): int { main := fn(): int {
// shuts down ableOS // shuts down ableOS
// outb(0xF400, 0) // outb(0xF400, 0)
@ -77,7 +125,10 @@ main := fn(): int {
b := inb(0x4700) b := inb(0x4700)
// c := buffer.search("XNumber\0") // c := buffer.search("XNumber\0")
c := identify() // c := identify()
d := drive_reset()
e := poll()
return 0 return 0
} }

View file

@ -1,23 +1,35 @@
$ATA_PRIMARY_DATA := @intcast(0x1F0) // $ATA_PRIMARY_DATA := @intcast(0x1F0)
$ATA_PRIMARY_ERR := @intcast(0x1F1) // $ATA_PRIMARY_ERR := @intcast(0x1F1)
$ATA_PRIMARY_SECCOUNT := @intcast(0x1F2) // $ATA_PRIMARY_SECCOUNT := @intcast(0x1F2)
$ATA_PRIMARY_LBA_LO := @intcast(0x1F3) // $ATA_PRIMARY_LBA_LO := @intcast(0x1F3)
$ATA_PRIMARY_LBA_MID := @intcast(0x1F4) // $ATA_PRIMARY_LBA_MID := @intcast(0x1F4)
$ATA_PRIMARY_LBA_HI := @intcast(0x1F5) // $ATA_PRIMARY_LBA_HI := @intcast(0x1F5)
$ATA_PRIMARY_DRIVE_HEAD := @intcast(0x1F6) // $ATA_PRIMARY_DRIVE_HEAD := @intcast(0x1F6)
$ATA_PRIMARY_COMM_REGSTAT := @intcast(0x1F7) // $ATA_PRIMARY_COMM_REGSTAT := @intcast(0x1F7)
$ATA_PRIMARY_ALTSTAT_DCR := @intcast(0x3F6) // $ATA_PRIMARY_ALTSTAT_DCR := @intcast(0x3F6)
// Indicates an error occurred. Send a new command to clear it $ATA_PRIMARY_IO := @intcast(0x1F0)
STAT_ERR := 1 << 0
// Set when the drive has PIO data to transfer, or is ready to accept PIO data. $ATA_PRIMARY_DEVCTL := @intcast(0x3F6)
STAT_DRQ := 1 << 3 $ATA_SECONDARY_DEVCTL := @intcast(0x3F6)
// Overlapped Mode Service Request.
STAT_SRV := 1 << 4 $ATA_REG_STAT := @intcast(0x7)
// Drive Fault Error (does not set ERR).
STAT_DF := 1 << 5 // // Indicates an error occurred. Send a new command to clear it
// Bit is clear when drive is spun down, or after an error. Set otherwise. // STAT_ERR := 1 << 0
STAT_RDY := 1 << 6 // // Set when the drive has PIO data to transfer, or is ready to accept PIO data.
// Indicates the drive is preparing to send/receive data (wait for it to clear). // STAT_DRQ := 1 << 3
// In case of 'hang' (it never clears), do a software reset. // // Overlapped Mode Service Request.
STAT_BSY := 1 << 7 // STAT_SRV := 1 << 4
// // Drive Fault Error (does not set ERR).
// STAT_DF := 1 << 5
// // Bit is clear when drive is spun down, or after an error. Set otherwise.
// STAT_RDY := 1 << 6
// // Indicates the drive is preparing to send/receive data (wait for it to clear).
// // In case of 'hang' (it never clears), do a software reset.
// STAT_BSY := 1 << 7
$ATA_SR_BSY := 0x80
$ATA_SR_DF := 0x20
$ATA_SR_DRQ := 0x8
$ATA_SR_ERR := 0x1

View file

@ -28,8 +28,8 @@ resolution = "1024x768x24"
[boot.limine.ableos.modules.diskio_driver] [boot.limine.ableos.modules.diskio_driver]
path = "boot:///diskio_driver.hbf" path = "boot:///diskio_driver.hbf"
[boot.limine.ableos.modules.ps2_mouse_driver] # [boot.limine.ableos.modules.ps2_mouse_driver]
path = "boot:///ps2_mouse_driver.hbf" # path = "boot:///ps2_mouse_driver.hbf"
# [boot.limine.ableos.modules.ps2_keyboard_driver] # [boot.limine.ableos.modules.ps2_keyboard_driver]
# path = "boot:///ps2_keyboard_driver.hbf" # path = "boot:///ps2_keyboard_driver.hbf"
@ -37,11 +37,11 @@ path = "boot:///ps2_mouse_driver.hbf"
# [boot.limine.ableos.modules.ps2_driver] # [boot.limine.ableos.modules.ps2_driver]
# path = "boot:///ps2_driver.hbf" # path = "boot:///ps2_driver.hbf"
[boot.limine.ableos.modules.sunset_client] # [boot.limine.ableos.modules.sunset_client]
path = "boot:///sunset_client.hbf" # path = "boot:///sunset_client.hbf"
[boot.limine.ableos.modules.sunset_server] # [boot.limine.ableos.modules.sunset_server]
path = "boot:///sunset_server.hbf" # path = "boot:///sunset_server.hbf"
[boot.limine.ableos.modules.ablefetch] # [boot.limine.ableos.modules.ablefetch]
path = "boot:///ablefetch.hbf" # path = "boot:///ablefetch.hbf"