示例#1
0
// Writes a word to the PI MMIO register space.
int write_pi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  struct pi_controller *pi = (struct pi_controller *) opaque;
  unsigned offset = address - PI_REGS_BASE_ADDRESS;
  enum pi_register reg = (offset >> 2);

  debug_mmio_write(pi, pi_register_mnemonics[reg], word, dqm);

  if (reg == PI_STATUS_REG) {
    if (word & 0x1)
      pi->regs[reg] = 0;

    if (word & 0x2) {
      clear_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
      pi->regs[reg] &= ~0x8;
    }
  }

  else {
    pi->regs[reg] &= ~dqm;
    pi->regs[reg] |= word;

    if (reg == PI_CART_ADDR_REG)
      dd_pi_write(pi->bus->dd, word);

    else if (reg == PI_WR_LEN_REG) {
      if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
        pi->regs[PI_STATUS_REG] &= ~0x1;
        pi->regs[PI_STATUS_REG] |= 0x8;

        signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
        return 0;
      }

      pi->bytes_to_copy = (pi->regs[PI_WR_LEN_REG] & 0xFFFFFF) + 1;
      pi->counter = pi->bytes_to_copy / 2 + 100; // Assume ~2 bytes/clock?
      pi->regs[PI_STATUS_REG] |= 0x9; // I'm busy!
      pi->is_dma_read = false;
    }

    else if (reg == PI_RD_LEN_REG) {
      if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
        pi->regs[PI_STATUS_REG] &= ~0x1;
        pi->regs[PI_STATUS_REG] |= 0x8;

        signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
        return 0;
      }

      pi->bytes_to_copy = (pi->regs[PI_RD_LEN_REG] & 0xFFFFFF) + 1;
      pi->counter = pi->bytes_to_copy / 2 + 100; // Assume ~2 bytes/clock?
      pi->regs[PI_STATUS_REG] |= 0x9; // I'm busy!
      pi->is_dma_read = true;
    }
  }

  return 0;
}
示例#2
0
// Writes a word to the AI MMIO register space.
int write_ai_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  struct ai_controller *ai = (struct ai_controller *) opaque;
  unsigned offset = address - AI_REGS_BASE_ADDRESS;
  enum ai_register reg = (offset >> 2);

  debug_mmio_write(ai, ai_register_mnemonics[reg], word, dqm);

  if (reg == AI_DRAM_ADDR_REG)
    ai->regs[AI_DRAM_ADDR_REG] = word & 0xFFFFF8;

  else if (reg == AI_LEN_REG) {
    ai->regs[AI_LEN_REG] = word & 0x3FFF8;

    if (ai->fifo_count == 2)
      return 0;

    // Fill the next FIFO entry in the DMA engine.
    ai->fifo[ai->fifo_wi].address = ai->regs[AI_DRAM_ADDR_REG];
    ai->fifo[ai->fifo_wi].length = ai->regs[AI_LEN_REG];
    ai->fifo_wi = (ai->fifo_wi == 1) ? 0 : 1;
    ai->fifo_count++;

    if (ai->fifo_count == 2)
      ai->regs[AI_STATUS_REG] |= 0x80000001U;

    // If we're not DMA-ing already, start DMA engine.
    if (!(ai->regs[AI_STATUS_REG] & 0x40000000U))
      ai_dma(ai);
  }

  else if (reg == AI_STATUS_REG) {
    struct bus_controller *bus;

    memcpy(&bus, ai, sizeof(bus));
    clear_rcp_interrupt(bus->vr4300, MI_INTR_AI);
  }

  else if (reg == AI_DACRATE_REG) {
    ai->regs[AI_DACRATE_REG] = word & 0x3FFF;

    ai->ctx.frequency = (double) NTSC_DAC_FREQ /
      (ai->regs[AI_DACRATE_REG] + 1);
  }

  else if (reg == AI_BITRATE_REG)
    ai->regs[AI_BITRATE_REG] = word & 0xF;

  else
    ai->regs[reg] = word;

  return 0;
}
示例#3
0
// Writes a word to the MI MMIO register space.
int write_mi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  struct vr4300 *vr4300 = (struct vr4300 *) opaque;
  uint32_t offset = address - MI_REGS_BASE_ADDRESS;
  enum mi_register reg = (offset >> 2);
  uint32_t result;

  debug_mmio_write(mi, mi_register_mnemonics[reg], word, dqm);

  // Change mode settings?
  if (reg == MI_INIT_MODE_REG) {
    result = word & 0x3FF;

    if (word & 0x0080)
      result &= ~MI_INIT_MODE;
    else if (word & 0x0100)
      result |= MI_INIT_MODE;

    if (word & 0x0200)
      result &= ~MI_EBUS_TEST_MODE;
    else if (word & 0x0400)
      result |= MI_EBUS_TEST_MODE;

    if (word & 0x0800) {
      vr4300->mi_regs[MI_INTR_REG] &= ~MI_INTR_DP;
      check_for_interrupts(vr4300); // TODO/FIXME: ???
    }

    if (word & 0x1000)
      result &= ~MI_RDRAM_REG_MODE;
    else if (word & 0x2000)
      result |= MI_RDRAM_REG_MODE;

    vr4300->mi_regs[MI_INIT_MODE_REG] = result;
  }

  // Change interrupt mask?
  else if (reg == MI_INTR_MASK_REG) {
    if (word & 0x0001)
      vr4300->mi_regs[MI_INTR_MASK_REG] &= ~MI_INTR_SP;
    else if (word & 0x0002)
      vr4300->mi_regs[MI_INTR_MASK_REG] |= MI_INTR_SP;

    if (word & 0x0004)
      vr4300->mi_regs[MI_INTR_MASK_REG] &= ~MI_INTR_SI;
    else if (word & 0x0008)
      vr4300->mi_regs[MI_INTR_MASK_REG] |= MI_INTR_SI;

    if (word & 0x0010)
      vr4300->mi_regs[MI_INTR_MASK_REG] &= ~MI_INTR_AI;
    else if (word & 0x0020)
      vr4300->mi_regs[MI_INTR_MASK_REG] |= MI_INTR_AI;

    if (word & 0x0040)
      vr4300->mi_regs[MI_INTR_MASK_REG] &= ~MI_INTR_VI;
    else if (word & 0x0080)
      vr4300->mi_regs[MI_INTR_MASK_REG] |= MI_INTR_VI;

    if (word & 0x0100)
      vr4300->mi_regs[MI_INTR_MASK_REG] &= ~MI_INTR_PI;
    else if (word & 0x0200)
      vr4300->mi_regs[MI_INTR_MASK_REG] |= MI_INTR_PI;

    if (word & 0x0400)
      vr4300->mi_regs[MI_INTR_MASK_REG] &= ~MI_INTR_DP;
    else if (word & 0x0800)
      vr4300->mi_regs[MI_INTR_MASK_REG] |= MI_INTR_DP;

    check_for_interrupts(vr4300); // TODO/FIXME: ???
  }

  else {
    vr4300->mi_regs[reg] &= ~dqm;
    vr4300->mi_regs[reg] |= word;
  }

  return 0;
}