static unsigned8 read_iagr (struct hw *me, struct mn103int *controller, unsigned_word offset) { unsigned8 val; switch (offset) { case 0: { if (!(controller->group[controller->interrupt_accepted_group].request & controller->group[controller->interrupt_accepted_group].enable)) { /* oops, lost the request */ val = 0; HW_TRACE ((me, "read-iagr:0 lost-0")); } else { val = (controller->interrupt_accepted_group << 2); HW_TRACE ((me, "read-iagr:0 %d", (int) val)); } break; } case 1: val = 0; HW_TRACE ((me, "read-iagr:1 %d", (int) val)); break; default: val = 0; HW_TRACE ((me, "read-iagr 0x%08lx bad offset", (long) offset)); break; } return val; }
/* All reads to the flash address space come here. Using the state machine, we figure out what to return -- actual data stored in the flash, the CFI query structure, some status info, or something else ? Any requests that we can't handle are passed to the command set- specific read function. */ static unsigned cfi_io_read_buffer (struct hw *me, void *dest, int space, address_word addr, unsigned nr_bytes) { struct cfi *cfi = hw_data (me); unsigned char *sdest = dest; unsigned offset, shifted_offset; offset = addr & (cfi->dev_size - 1); shifted_offset = cfi_unshift_addr (cfi, offset); /* XXX: Is this OK to enforce ? */ #if 0 if (cfi->state != CFI_STATE_READ && cfi->width != nr_bytes) { HW_TRACE ((me, "read 0x%08lx length %u does not match flash width %u", (unsigned long) addr, nr_bytes, cfi->width)); return nr_bytes; } #endif HW_TRACE ((me, "%s read 0x%08lx length %u", state_names[cfi->state], (unsigned long) addr, nr_bytes)); switch (cfi->state) { case CFI_STATE_READ: memcpy (dest, cfi->data + offset, nr_bytes); break; case CFI_STATE_CFI_QUERY: if (shifted_offset >= CFI_ADDR_CFI_QUERY_RESULT && shifted_offset < CFI_ADDR_CFI_QUERY_RESULT + sizeof (cfi->query) + (cfi->query.num_erase_regions * 4)) { unsigned char *qry; shifted_offset -= CFI_ADDR_CFI_QUERY_RESULT; if (shifted_offset >= sizeof (cfi->query)) { qry = cfi->erase_region_info; shifted_offset -= sizeof (cfi->query); } else qry = (void *) &cfi->query; sdest[0] = qry[shifted_offset]; memset (sdest + 1, 0, nr_bytes - 1); break; } default: if (!cfi->cmdset->read (me, cfi, dest, offset, shifted_offset, nr_bytes)) HW_TRACE ((me, "unhandled state %s", state_names[cfi->state])); break; } return nr_bytes; }
static void bfin_gpio_port_event (struct hw *me, int my_port, struct hw *source, int source_port, int level) { struct bfin_gpio *port = hw_data (me); bu32 bit = (1 << my_port); /* Normalize the level value. A simulated device can send any value it likes to us, but in reality we only care about 0 and 1. This lets us assume only those two values below. */ level = !!level; HW_TRACE ((me, "pin %i set to %i", my_port, level)); /* Only screw with state if this pin is set as an input, and the input is actually enabled, and it isn't in peripheral mode. */ if ((port->dir & bit) || !(port->inen & bit) || !(port->fer & bit)) { HW_TRACE ((me, "ignoring level due to DIR=%i INEN=%i FER=%i", !!(port->dir & bit), !!(port->inen & bit), !!(port->fer & bit))); return; } hw_port_event (me, my_port, level); }
static unsigned hw_pal_io_write_buffer (struct hw *me, const void *source, int space, unsigned_word addr, unsigned nr_bytes) { hw_pal_device *hw_pal = (hw_pal_device*) hw_data (me); unsigned_1 *byte = (unsigned_1 *) source; switch (addr & hw_pal_address_mask) { case hw_pal_reset_register: hw_halt (me, sim_exited, byte[0]); break; case hw_pal_int_register: hw_port_event (me, INT_PORT + byte[0], /*port*/ (nr_bytes > 1 ? byte[1] : 0)); /* val */ break; case hw_pal_read_fifo: hw_pal->input.buffer = byte[0]; HW_TRACE ((me, "write - input-fifo %d\n", byte[0])); break; case hw_pal_read_status: hw_pal->input.status = byte[0]; HW_TRACE ((me, "write - input-status %d\n", byte[0])); break; case hw_pal_write_fifo: write_hw_pal (me, byte[0]); HW_TRACE ((me, "write - output-fifo %d\n", byte[0])); break; case hw_pal_write_status: hw_pal->output.status = byte[0]; HW_TRACE ((me, "write - output-status %d\n", byte[0])); break; case hw_pal_countdown: do_counter_write (me, hw_pal, "countdown", &hw_pal->countdown, source, nr_bytes); break; case hw_pal_timer: do_counter_write (me, hw_pal, "timer", &hw_pal->timer, source, nr_bytes); break; } return nr_bytes; }
static unsigned8 read_icr (struct hw *me, struct mn103int *controller, unsigned_word base) { unsigned_word offset; struct mn103int_group *group = decode_group (me, controller, base, &offset); unsigned8 val = 0; switch (group->type) { case NMI_GROUP: switch (offset) { case 0: val = INSERT_ID (group->request); HW_TRACE ((me, "read-icr group=%d:0 nmi 0x%02x", group->gid, val)); break; default: break; } break; case LEVEL_GROUP: switch (offset) { case 0: val = (INSERT_IR (group->request) | INSERT_ID (group->request & group->enable)); HW_TRACE ((me, "read-icr group=%d:0 level 0x%02x", group->gid, val)); break; case 1: val = (INSERT_LV (group->level) | INSERT_IE (group->enable)); HW_TRACE ((me, "read-icr level-%d:1 level 0x%02x", group->gid, val)); break; } break; default: break; } return val; }
static void tx3904sio_port_event (struct hw *me, int my_port, struct hw *source, int source_port, int level) { struct tx3904sio *controller = hw_data (me); switch (my_port) { case RESET_PORT: { HW_TRACE ((me, "reset")); tx3904sio_fifo_reset(me, & controller->rx_fifo); tx3904sio_fifo_reset(me, & controller->tx_fifo); controller->slsr = controller->sdicr = controller->sdisr = controller->sfcr = controller->sbgr = 0; controller->slcr = 0x40000000; /* set TWUB */ controller->sbgr = 0x03ff0000; /* set BCLK=3, BRD=FF */ /* Don't interfere with I/O poller. */ break; } default: hw_abort (me, "Event on unknown port %d", my_port); break; } }
static void bfin_mmr_invalid (struct hw *me, SIM_CPU *cpu, address_word addr, unsigned nr_bytes, bool write) { if (!cpu) cpu = hw_system_cpu (me); /* Only throw a fit if the cpu is doing the access. DMA/GDB simply go unnoticed. Not exactly hardware behavior, but close enough. */ if (!cpu) { sim_io_eprintf (hw_system (me), "%s: invalid MMR access @ %#x\n", hw_path (me), addr); return; } HW_TRACE ((me, "invalid MMR %s to 0x%08lx length %u", write ? "write" : "read", (unsigned long) addr, nr_bytes)); /* XXX: is this what hardware does ? */ if (addr >= BFIN_CORE_MMR_BASE) /* XXX: This should be setting up CPLB fault addrs ? */ mmu_process_fault (cpu, addr, write, false, false, true); else /* XXX: Newer parts set up an interrupt from EBIU and program EBIU_ERRADDR with the address. */ cec_hwerr (cpu, HWERR_SYSTEM_MMR); }
static void bfin_mmr_invalid (struct hw *me, address_word addr, unsigned nr_bytes, bool write, bool missing) { SIM_CPU *cpu = hw_system_cpu (me); const char *rw = write ? "write" : "read"; const char *reason = missing ? "no such register" : (addr & 3) ? "must be 32-bit aligned" : "invalid length"; /* Only throw a fit if the cpu is doing the access. DMA/GDB simply go unnoticed. Not exactly hardware behavior, but close enough. */ if (!cpu) { sim_io_eprintf (hw_system (me), "%s: invalid MMR %s at %#x length %u: %s\n", hw_path (me), rw, addr, nr_bytes, reason); return; } HW_TRACE ((me, "invalid MMR %s at %#x length %u: %s", rw, addr, nr_bytes, reason)); /* XXX: is this what hardware does ? What about priority of unaligned vs wrong length vs missing register ? What about system-vs-core ? */ /* XXX: We should move this addr check to a model property so we get the same behavior regardless of where we map the model. */ if (addr >= BFIN_CORE_MMR_BASE) /* XXX: This should be setting up CPLB fault addrs ? */ mmu_process_fault (cpu, addr, write, false, false, true); else /* XXX: Newer parts set up an interrupt from EBIU and program EBIU_ERRADDR with the address. */ cec_hwerr (cpu, HWERR_SYSTEM_MMR); }
static void push_interrupt_level (struct hw *me, struct mn103int *controller) { int selected = find_highest_interrupt_group (me, controller); int level = controller->group[selected].level; HW_TRACE ((me, "port-out - selected=%d level=%d", selected, level)); hw_port_event (me, LEVEL_PORT, level); }
static unsigned mn103iop_io_write_buffer (struct hw *me, const void *source, int space, unsigned_word base, unsigned nr_bytes) { struct mn103iop *io_port = hw_data (me); enum io_port_register_types io_port_reg; HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); io_port_reg = decode_addr (me, io_port, base); switch (io_port_reg) { /* Port output registers */ case P0OUT: case P1OUT: case P2OUT: case P3OUT: write_output_reg(me, io_port, io_port_reg-P0OUT, source, nr_bytes); break; /* Port output mode registers */ case P0MD: case P1MD: case P2MD: case P3MD: write_output_mode_reg(me, io_port, io_port_reg-P0MD, source, nr_bytes); break; /* Port control registers */ case P0DIR: case P1DIR: case P2DIR: case P3DIR: write_control_reg(me, io_port, io_port_reg-P0DIR, source, nr_bytes); break; /* Port pin registers */ case P0IN: case P1IN: case P2IN: hw_abort(me, "Cannot write to pin register."); break; case P2SS: case P4SS: write_dedicated_control_reg(me, io_port, io_port_reg, source, nr_bytes); break; default: hw_abort(me, "invalid address"); } return nr_bytes; }
static void do_counter_event (struct hw *me, void *data) { hw_pal_counter *counter = (hw_pal_counter *) data; if (counter->periodic_p) { HW_TRACE ((me, "timer expired")); counter->start = hw_event_queue_time (me); hw_port_event (me, TIMER_PORT, 1); hw_event_queue_schedule (me, counter->delta, do_counter_event, counter); } else { HW_TRACE ((me, "countdown expired")); counter->delta = 0; hw_port_event (me, COUNTDOWN_PORT, 1); } }
static unsigned m68hc11eepr_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word base, unsigned nr_bytes) { SIM_DESC sd; struct m68hc11eepr *controller; sim_cpu *cpu; HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); sd = hw_system (me); controller = hw_data (me); cpu = STATE_CPU (sd, 0); if (space == io_map) { unsigned cnt = 0; while (nr_bytes != 0) { switch (base) { case M6811_PPROG: case M6811_CONFIG: *((uint8*) dest) = cpu->ios[base]; break; default: hw_abort (me, "reading wrong register 0x%04x", base); } dest = (uint8*) (dest) + 1; base++; nr_bytes--; cnt++; } return cnt; } /* In theory, we can't read the EEPROM when it's being programmed. */ if ((cpu->ios[M6811_PPROG] & M6811_EELAT) != 0 && cpu_is_running (cpu)) { sim_memory_error (cpu, SIM_SIGBUS, base, "EEprom not configured for reading"); } base = base - controller->base_address; memcpy (dest, &controller->eeprom[base], nr_bytes); return nr_bytes; }
static void mn103cpu_port_event (struct hw *me, int my_port, struct hw *source, int source_port, int level) { struct mn103cpu *controller = hw_data (me); /* Schedule our event handler *now* */ if (controller->pending_handler == NULL) controller->pending_handler = hw_event_queue_schedule (me, 0, deliver_mn103cpu_interrupt, NULL); switch (my_port) { case RESET_PORT: controller->pending_reset = 1; HW_TRACE ((me, "port-in reset")); break; case NMI_PORT: controller->pending_nmi = 1; HW_TRACE ((me, "port-in nmi")); break; case LEVEL_PORT: controller->pending_level = level; HW_TRACE ((me, "port-in level=%d", level)); break; default: hw_abort (me, "bad switch"); break; } }
static unsigned tx3904sio_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word base, unsigned nr_bytes) { struct tx3904sio *controller = hw_data (me); unsigned byte; HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); /* tickle fifos */ tx3904sio_tickle(me); for (byte = 0; byte < nr_bytes; byte++) { address_word address = base + byte; int reg_number = (address - controller->base_address) / 4; int reg_offset = (address - controller->base_address) % 4; unsigned_4 register_value; /* in target byte order */ /* fill in entire register_value word */ switch (reg_number) { case SLCR_REG: register_value = controller->slcr; break; case SLSR_REG: register_value = controller->slsr; break; case SDICR_REG: register_value = controller->sdicr; break; case SDISR_REG: register_value = controller->sdisr; break; case SFCR_REG: register_value = controller->sfcr; break; case SBGR_REG: register_value = controller->sbgr; break; case TFIFO_REG: register_value = 0; break; case SFIFO_REG: /* consume rx fifo for MS byte */ if(reg_offset == 0 && tx3904sio_fifo_nonempty(me, & controller->rx_fifo)) register_value = (tx3904sio_fifo_pop(me, & controller->rx_fifo) << 24); else register_value = 0; break; default: register_value = 0; } /* write requested byte out */ register_value = H2T_4(register_value); /* HW_TRACE ((me, "byte %d %02x", reg_offset, ((char*)& register_value)[reg_offset])); */ memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1); } return nr_bytes; }
static void do_counter_read (struct hw *me, hw_pal_device *pal, const char *reg, hw_pal_counter *counter, unsigned32 *word, unsigned nr_bytes) { unsigned32 val; if (nr_bytes != 4) hw_abort (me, "%s - bad read size must be 4 bytes", reg); val = counter->delta; HW_TRACE ((me, "read - %s %ld", reg, (long) val)); *word = H2BE_4 (val); }
static unsigned mn103tim_io_write_buffer (struct hw *me, const void *source, int space, unsigned_word base, unsigned nr_bytes) { struct mn103tim *timers = hw_data (me); enum timer_register_types timer_reg; HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base, (int) nr_bytes, *(unsigned32 *)source)); timer_reg = decode_addr (me, timers, base); /* It can be either a mode register, a base register, a binary counter, */ /* or a special timer 6 register. Check in that order. */ if ( timer_reg <= LAST_MODE_REG ) { if ( timer_reg == 6 ) { write_tm6md(me, timers, base, source, nr_bytes); } else { write_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, source, nr_bytes); } } else if ( timer_reg <= LAST_BASE_REG ) { write_base_reg(me, timers, timer_reg-FIRST_BASE_REG, source, nr_bytes); } else if ( timer_reg <= LAST_COUNTER ) { hw_abort(me, "cannot write to counter"); } else if ( timer_reg <= LAST_TIMER_REG ) { write_special_timer6_reg(me, timers, timer_reg, source, nr_bytes); } else { hw_abort(me, "invalid reg type"); } return nr_bytes; }
static unsigned m68hc11tim_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word base, unsigned nr_bytes) { SIM_DESC sd; struct m68hc11tim *controller; sim_cpu *cpu; unsigned8 val; unsigned cnt = 0; HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); sd = hw_system (me); cpu = STATE_CPU (sd, 0); controller = hw_data (me); while (nr_bytes) { switch (base) { /* The cpu_absolute_cycle is updated after each instruction. Reading in a 16-bit register will be split in two accesses but this will be atomic within the simulator. */ case M6811_TCTN_H: val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust) / (controller->clock_prescaler * 256)); break; case M6811_TCTN_L: val = (uint8) ((cpu->cpu_absolute_cycle - controller->tcnt_adjust) / controller->clock_prescaler); break; default: val = cpu->ios[base]; break; } *((unsigned8*) dest) = val; dest = (char*) dest + 1; base++; nr_bytes--; cnt++; } return cnt; }
static unsigned8 read_extmd (struct hw *me, struct mn103int *controller, unsigned_word offset) { int gid; unsigned8 val = 0; struct mn103int_group *group = external_group (controller, offset); if (group != NULL) { for (gid = 0; gid < 4; gid++) { val |= (group[gid].trigger << (gid * 2)); } } HW_TRACE ((me, "read-extmd 0x%02lx", (long) val)); return val; }
static void write_extmd (struct hw *me, struct mn103int *controller, unsigned_word offset, unsigned8 val) { int gid; struct mn103int_group *group = external_group (controller, offset); if (group != NULL) { for (gid = 0; gid < 4; gid++) { group[gid].trigger = (val >> (gid * 2)) & 0x3; /* MAYBE: interrupts already pending? */ } } HW_TRACE ((me, "write-extmd 0x%02lx", (long) val)); }
static unsigned m68hc11sio_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word base, unsigned nr_bytes) { SIM_DESC sd; struct m68hc11sio *controller; sim_cpu *cpu; unsigned8 val; HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); sd = hw_system (me); cpu = STATE_CPU (sd, 0); controller = hw_data (me); switch (base) { case M6811_SCSR: controller->rx_clear_scsr = cpu->ios[M6811_SCSR] & (M6811_RDRF | M6811_IDLE | M6811_OR | M6811_NF | M6811_FE); case M6811_BAUD: case M6811_SCCR1: case M6811_SCCR2: val = cpu->ios[base]; break; case M6811_SCDR: if (controller->rx_clear_scsr) { cpu->ios[M6811_SCSR] &= ~controller->rx_clear_scsr; } val = controller->rx_char; break; default: return 0; } *((unsigned8*) dest) = val; return 1; }
static unsigned m68hc11spi_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word base, unsigned nr_bytes) { SIM_DESC sd; struct m68hc11spi *controller; sim_cpu *cpu; unsigned8 val; HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); sd = hw_system (me); cpu = STATE_CPU (sd, 0); controller = hw_data (me); switch (base) { case M6811_SPSR: controller->rx_clear_scsr = cpu->ios[M6811_SCSR] & (M6811_SPIF | M6811_WCOL | M6811_MODF); case M6811_SPCR: val = cpu->ios[base]; break; case M6811_SPDR: if (controller->rx_clear_scsr) { cpu->ios[M6811_SPSR] &= ~controller->rx_clear_scsr; controller->rx_clear_scsr = 0; interrupts_update_pending (&cpu->cpu_interrupts); } val = controller->rx_char; break; default: return 0; } *((unsigned8*) dest) = val; return 1; }
static void do_counter_value (struct hw *me, hw_pal_device *pal, const char *reg, hw_pal_counter *counter, unsigned32 *word, unsigned nr_bytes) { unsigned32 val; if (nr_bytes != 4) hw_abort (me, "%s - bad read size must be 4 bytes", reg); if (counter->delta != 0) val = (counter->start + counter->delta - hw_event_queue_time (me)); else val = 0; HW_TRACE ((me, "read - %s %ld", reg, (long) val)); *word = H2BE_4 (val); }
static unsigned tx3904irc_io_write_buffer (struct hw *me, const void *source, int space, unsigned_word base, unsigned nr_bytes) { struct tx3904irc *controller = hw_data (me); unsigned byte; HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); for (byte = 0; byte < nr_bytes; byte++) { address_word address = base + byte; int reg_number = (address - controller->base_address) / 4; int reg_offset = (address - controller->base_address) % 4; unsigned_4* register_ptr; unsigned_4 register_value; /* fill in entire register_value word */ switch (reg_number) { case ISR_REG: register_ptr = & controller->isr; break; case IMR_REG: register_ptr = & controller->imr; break; case ILR0_REG: register_ptr = & controller->ilr[0]; break; case ILR1_REG: register_ptr = & controller->ilr[1]; break; case ILR2_REG: register_ptr = & controller->ilr[2]; break; case ILR3_REG: register_ptr = & controller->ilr[3]; break; default: register_ptr = & register_value; /* used as a dummy */ } /* HW_TRACE ((me, "reg %d pre: %08lx", reg_number, (long) *register_ptr)); */ /* overwrite requested byte */ register_value = H2T_4(* register_ptr); memcpy (((char*)®ister_value)+reg_offset, (const char*)source + byte, 1); * register_ptr = T2H_4(register_value); /* HW_TRACE ((me, "post: %08lx", (long) *register_ptr)); */ } return nr_bytes; }
static unsigned nvram_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word base, unsigned nr_bytes) { struct nvram *controller = hw_data (me); HW_TRACE ((me, "read 0x%08lx %d [%ld]", (long) base, (int) nr_bytes, (long) (base - controller->base_address))); base -= controller->base_address; if (base + nr_bytes > controller->size) nr_bytes = controller->size - base; memcpy (dest, &controller->data[base], nr_bytes); return nr_bytes; }
static void do_counter_write (struct hw *me, hw_pal_device *pal, const char *reg, hw_pal_counter *counter, const unsigned32 *word, unsigned nr_bytes) { if (nr_bytes != 4) hw_abort (me, "%s - bad write size must be 4 bytes", reg); if (counter->handler != NULL) { hw_event_queue_deschedule (me, counter->handler); counter->handler = NULL; } counter->delta = BE2H_4 (*word); counter->start = hw_event_queue_time (me); HW_TRACE ((me, "write - %s %ld", reg, (long) counter->delta)); if (counter->delta > 0) hw_event_queue_schedule (me, counter->delta, do_counter_event, counter); }
static void m68hc11spi_port_event (struct hw *me, int my_port, struct hw *source, int source_port, int level) { SIM_DESC sd; struct m68hc11spi *controller; sim_cpu* cpu; unsigned8 val; controller = hw_data (me); sd = hw_system (me); cpu = STATE_CPU (sd, 0); switch (my_port) { case RESET_PORT: { HW_TRACE ((me, "SPI reset")); /* Reset the state of SPI registers. */ controller->rx_clear_scsr = 0; if (controller->spi_event) { hw_event_queue_deschedule (me, controller->spi_event); controller->spi_event = 0; } val = 0; m68hc11spi_io_write_buffer (me, &val, io_map, (unsigned_word) M6811_SPCR, 1); break; } default: hw_abort (me, "Event on unknown port %d", my_port); break; } }
static unsigned mn103tim_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word base, unsigned nr_bytes) { struct mn103tim *timers = hw_data (me); enum timer_register_types timer_reg; HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); timer_reg = decode_addr (me, timers, base); /* It can be either a mode register, a base register, a binary counter, */ /* or a special timer 6 register. Check in that order. */ if ( timer_reg >= FIRST_MODE_REG && timer_reg <= LAST_MODE_REG ) { read_mode_reg(me, timers, timer_reg-FIRST_MODE_REG, dest, nr_bytes); } else if ( timer_reg <= LAST_BASE_REG ) { read_base_reg(me, timers, timer_reg-FIRST_BASE_REG, dest, nr_bytes); } else if ( timer_reg <= LAST_COUNTER ) { read_counter(me, timers, timer_reg-FIRST_COUNTER, dest, nr_bytes); } else if ( timer_reg <= LAST_TIMER_REG ) { read_special_timer6_reg(me, timers, timer_reg, dest, nr_bytes); } else { hw_abort(me, "invalid timer register address."); } return nr_bytes; }
static unsigned tx3904tmr_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word base, unsigned nr_bytes) { struct tx3904tmr *controller = hw_data (me); unsigned byte; HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); for (byte = 0; byte < nr_bytes; byte++) { address_word address = base + byte; int reg_number = (address - controller->base_address) / 4; int reg_offset = 3 - (address - controller->base_address) % 4; unsigned_4 register_value; /* in target byte order */ /* fill in entire register_value word */ switch (reg_number) { case TCR_REG: register_value = controller->tcr; break; case TISR_REG: register_value = controller->tisr; break; case CPRA_REG: register_value = controller->cpra; break; case CPRB_REG: register_value = controller->cprb; break; case ITMR_REG: register_value = controller->itmr; break; case CCDR_REG: register_value = controller->ccdr; break; case PMGR_REG: register_value = controller->pmgr; break; case WTMR_REG: register_value = controller->wtmr; break; case TRR_REG: register_value = controller->trr; break; default: register_value = 0; } /* write requested byte out */ memcpy ((char*) dest + byte, ((char*)& register_value)+reg_offset, 1); } return nr_bytes; }
static void tx3904tmr_port_event (struct hw *me, int my_port, struct hw *source, int source_port, int level) { struct tx3904tmr *controller = hw_data (me); switch (my_port) { case RESET_PORT: { HW_TRACE ((me, "reset")); /* preset flip-flop to FFI value */ controller->ff = GET_PMGR_FFI(controller); controller->tcr = controller->itmr = controller->ccdr = controller->pmgr = controller->wtmr = controller->tisr = controller->trr = 0; controller->cpra = controller->cprb = 0x00FFFFFF; controller->last_ticks = controller->roundoff_ticks = 0; if(controller->event != NULL) hw_event_queue_deschedule(me, controller->event); controller->event = NULL; break; } default: hw_abort (me, "Event on unknown port %d", my_port); break; } }
static void dv_core_attach_address_callback (struct hw *me, int level, int space, address_word addr, address_word nr_bytes, struct hw *client) { HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, nr_bytes=%ld, client=%s", level, space, (unsigned long) addr, (unsigned long) nr_bytes, hw_path (client))); /* NOTE: At preset the space is assumed to be zero. Perhaphs the space should be mapped onto something for instance: space0 - unified memory; space1 - IO memory; ... */ sim_core_attach (hw_system (me), NULL, /*cpu*/ level, access_read_write_exec, space, addr, nr_bytes, 0, /* modulo */ client, NULL); }