static void ata_power_down(void) { if (!ata_powered) return; ata_powered = false; if (ceata) { memset(ceata_taskfile, 0, 16); ceata_taskfile[0xf] = 0xe0; ceata_wait_idle(); ceata_write_multiple_register(0, ceata_taskfile, 16); sleep(HZ); PWRCON(0) |= (1 << 9); } else { ata_wait_for_rdy(1000000); ata_write_cbr(&ATA_PIO_DVR, 0); ata_write_cbr(&ATA_PIO_CSD, 0xe0); ata_wait_for_rdy(1000000); sleep(HZ / 30); ATA_CONTROL = 0; while (!(ATA_CONTROL & BIT(1))) yield(); PWRCON(0) |= (1 << 5); } ide_power_enable(false); }
static int ata_rw_chunk_internal(uint64_t sector, uint32_t cnt, void* buffer, bool write) { if (ceata) { memset(ceata_taskfile, 0, 16); ceata_taskfile[0x2] = cnt >> 5; ceata_taskfile[0x3] = sector >> 21; ceata_taskfile[0x4] = sector >> 29; ceata_taskfile[0x5] = sector >> 37; ceata_taskfile[0xa] = cnt << 3; ceata_taskfile[0xb] = sector << 3; ceata_taskfile[0xc] = sector >> 5; ceata_taskfile[0xd] = sector >> 13; ceata_taskfile[0xf] = write ? 0x35 : 0x25; PASS_RC(ceata_wait_idle(), 2, 0); PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1); PASS_RC(ceata_rw_multiple_block(write, buffer, cnt << 3, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 2, 2); } else {
static int ata_set_feature(uint32_t feature, uint32_t param) { if (ceata) { memset(ceata_taskfile, 0, 16); ceata_taskfile[0x1] = feature; ceata_taskfile[0x2] = param; ceata_taskfile[0xf] = 0xef; PASS_RC(ceata_wait_idle(), 2, 0); PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1); PASS_RC(ceata_wait_idle(), 2, 2); } else { PASS_RC(ata_wait_for_rdy(2000000), 2, 0); ata_write_cbr(&ATA_PIO_DVR, 0); ata_write_cbr(&ATA_PIO_FED, feature); ata_write_cbr(&ATA_PIO_SCR, param); ata_write_cbr(&ATA_PIO_CSD, 0xef); PASS_RC(ata_wait_for_rdy(2000000), 2, 1); } return 0; }
static int ata_identify(uint16_t* buf) { int i; if (ceata) { memset(ceata_taskfile, 0, 16); ceata_taskfile[0xf] = 0xec; PASS_RC(ceata_wait_idle(), 2, 0); PASS_RC(ceata_write_multiple_register(0, ceata_taskfile, 16), 2, 1); PASS_RC(ceata_rw_multiple_block(false, buf, 1, CEATA_COMMAND_TIMEOUT * HZ / 1000000), 2, 2); } else { uint32_t old = ATA_CFG; ATA_CFG |= BIT(6); PASS_RC(ata_wait_for_not_bsy(10000000), 1, 0); ata_write_cbr(&ATA_PIO_DVR, 0); ata_write_cbr(&ATA_PIO_CSD, 0xec); PASS_RC(ata_wait_for_start_of_transfer(10000000), 1, 1); for (i = 0; i < 0x100; i++) buf[i] = ata_read_cbr(&ATA_PIO_DTR); ATA_CFG = old; } return 0; }