📄 hw_opic.c
字号:
if (timer->inhibited) reg = timer->count; /* stalled value */ else reg = timer->count - device_event_queue_time(me); /* time remaining */ DTRACE(opic, ("timer %d current count register - read 0x%x\n", index, reg)); return reg;}static unsigneddo_timer_N_base_count_register_read(device *me, hw_opic_device *opic, int index){ opic_timer *timer = &opic->timer[index]; unsigned reg; ASSERT(index >= 0 && index < opic->nr_timer_interrupts); reg = timer->base_count; DTRACE(opic, ("timer %d base count register - read 0x%x\n", index, reg)); return reg;}static voidtimer_event(void *data){ opic_timer *timer = data; device *me = timer->me; if (timer->inhibited) device_error(timer->me, "internal-error - timer event occured when timer %d inhibited", timer->nr); handle_interrupt(timer->me, timer->opic, timer->interrupt_source, 1); timer->timeout_event = device_event_queue_schedule(me, timer->base_count, timer_event, timer); DTRACE(opic, ("timer %d - interrupt at %ld, next at %d\n", timer->nr, (long)device_event_queue_time(me), timer->base_count));}static voiddo_timer_N_base_count_register_write(device *me, hw_opic_device *opic, int index, unsigned reg){ opic_timer *timer = &opic->timer[index]; int inhibit; ASSERT(index >= 0 && index < opic->nr_timer_interrupts); inhibit = reg & 0x80000000; if (timer->inhibited && !inhibit) { timer->inhibited = 0; if (timer->timeout_event != NULL) device_event_queue_deschedule(me, timer->timeout_event); timer->count = device_event_queue_time(me) + reg; timer->base_count = reg; timer->timeout_event = device_event_queue_schedule(me, timer->base_count, timer_event, (void*)timer); DTRACE(opic, ("timer %d base count register - write 0x%x - timer started\n", index, reg)); } else if (!timer->inhibited && inhibit) { if (timer->timeout_event != NULL) device_event_queue_deschedule(me, timer->timeout_event); timer->count = timer->count - device_event_queue_time(me); timer->inhibited = 1; timer->base_count = reg; DTRACE(opic, ("timer %d base count register - write 0x%x - timer stopped\n", index, reg)); } else { ASSERT((timer->inhibited && inhibit) || (!timer->inhibited && !inhibit)); DTRACE(opic, ("timer %d base count register - write 0x%x\n", index, reg)); timer->base_count = reg; }}static unsigneddo_timer_N_vector_priority_register_read(device *me, hw_opic_device *opic, int index){ unsigned reg; ASSERT(index >= 0 && index < opic->nr_timer_interrupts); reg = read_vector_priority_register(me, opic, &opic->timer_interrupt_source[index], "timer", index); return reg;}static voiddo_timer_N_vector_priority_register_write(device *me, hw_opic_device *opic, int index, unsigned reg){ ASSERT(index >= 0 && index < opic->nr_timer_interrupts); reg &= ~isu_level_triggered_bit; /* force edge trigger */ reg |= isu_positive_polarity_bit; /* force rising (positive) edge */ reg |= isu_multicast_bit; /* force multicast */ write_vector_priority_register(me, opic, &opic->timer_interrupt_source[index], reg, "timer", index);}static unsigneddo_timer_N_destination_register_read(device *me, hw_opic_device *opic, int index){ unsigned reg; ASSERT(index >= 0 && index < opic->nr_timer_interrupts); reg = read_destination_register(me, opic, &opic->timer_interrupt_source[index], "timer", index); return reg;}static voiddo_timer_N_destination_register_write(device *me, hw_opic_device *opic, int index, unsigned reg){ ASSERT(index >= 0 && index < opic->nr_timer_interrupts); write_destination_register(me, opic, &opic->timer_interrupt_source[index], reg, "timer", index);}/* IPI registers */static unsigneddo_ipi_N_vector_priority_register_read(device *me, hw_opic_device *opic, int index){ unsigned reg; ASSERT(index >= 0 && index < opic->nr_interprocessor_interrupts); reg = read_vector_priority_register(me, opic, &opic->interprocessor_interrupt_source[index], "ipi", index); return reg;}static voiddo_ipi_N_vector_priority_register_write(device *me, hw_opic_device *opic, int index, unsigned reg){ ASSERT(index >= 0 && index < opic->nr_interprocessor_interrupts); reg &= ~isu_level_triggered_bit; /* force edge trigger */ reg |= isu_positive_polarity_bit; /* force rising (positive) edge */ reg |= isu_multicast_bit; /* force a multicast source */ write_vector_priority_register(me, opic, &opic->interprocessor_interrupt_source[index], reg, "ipi", index);}static voiddo_ipi_N_dispatch_register_write(device *me, hw_opic_device *opic, int index, unsigned reg){ opic_interrupt_source *source = &opic->interprocessor_interrupt_source[index]; ASSERT(index >= 0 && index < opic->nr_interprocessor_interrupts); DTRACE(opic, ("ipi %d interrupt dispatch register - write 0x%x\n", index, reg)); source->destination = reg; handle_interrupt(me, opic, source, 1);}/* vendor and other global registers */static unsigneddo_vendor_identification_register_read(device *me, hw_opic_device *opic){ unsigned reg; reg = opic->vendor_identification; DTRACE(opic, ("vendor identification register - read 0x%x\n", reg)); return reg;}static unsigneddo_feature_reporting_register_N_read(device *me, hw_opic_device *opic, int index){ unsigned reg = 0; ASSERT(index == 0); switch (index) { case 0: reg |= (opic->nr_external_interrupts << 16); reg |= (opic->nr_interrupt_destinations << 8); reg |= (2/*version 1.2*/); break; } DTRACE(opic, ("feature reporting register %d - read 0x%x\n", index, reg)); return reg;}static unsigneddo_global_configuration_register_N_read(device *me, hw_opic_device *opic, int index){ unsigned reg = 0; ASSERT(index == 0); switch (index) { case 0: reg |= gcr0_8259_bit; /* hardwire 8259 disabled */ break; } DTRACE(opic, ("global configuration register %d - read 0x%x\n", index, reg)); return reg;}static voiddo_global_configuration_register_N_write(device *me, hw_opic_device *opic, int index, unsigned reg){ ASSERT(index == 0); if (reg & gcr0_reset_bit) { DTRACE(opic, ("global configuration register %d - write 0x%x - reseting opic\n", index, reg)); hw_opic_init_data(me); } if (!(reg & gcr0_8259_bit)) { DTRACE(opic, ("global configuration register %d - write 0x%x - ignoring 8259 enable\n", index, reg)); }}/* register read-write */static unsignedhw_opic_io_read_buffer(device *me, void *dest, int space, unsigned_word addr, unsigned nr_bytes, cpu *processor, unsigned_word cia){ hw_opic_device *opic = (hw_opic_device*)device_data(me); opic_register type; int index; decode_opic_address(me, opic, space, addr, nr_bytes, &type, &index); if (type == invalid_opic_register) { device_error(me, "invalid opic read access to %d:0x%lx (%d bytes)", space, (unsigned long)addr, nr_bytes); } else { unsigned reg; switch (type) { case processor_init_register: reg = do_processor_init_register_read(me, opic); break; case interrupt_source_N_vector_priority_register: reg = do_interrupt_source_N_vector_priority_register_read(me, opic, index); break; case interrupt_source_N_destination_register: reg = do_interrupt_source_N_destination_register_read(me, opic, index); break; case interrupt_acknowledge_register_N: reg = do_interrupt_acknowledge_register_N_read(me, opic, index); break; case spurious_vector_register: reg = do_spurious_vector_register_read(me, opic); break; case current_task_priority_register_N: reg = do_current_task_priority_register_N_read(me, opic, index); break; case timer_frequency_reporting_register: reg = do_timer_frequency_reporting_register_read(me, opic); break; case timer_N_current_count_register: reg = do_timer_N_current_count_register_read(me, opic, index); break; case timer_N_base_count_register: reg = do_timer_N_base_count_register_read(me, opic, index); break; case timer_N_vector_priority_register: reg = do_timer_N_vector_priority_register_read(me, opic, index); break; case timer_N_destination_register: reg = do_timer_N_destination_register_read(me, opic, index); break; case ipi_N_vector_priority_register: reg = do_ipi_N_vector_priority_register_read(me, opic, index); break; case feature_reporting_register_N: reg = do_feature_reporting_register_N_read(me, opic, index); break; case global_configuration_register_N: reg = do_global_configuration_register_N_read(me, opic, index); break; case vendor_identification_register: reg = do_vendor_identification_register_read(me, opic); break; default: reg = 0; device_error(me, "unimplemented read of register %s[%d]", opic_register_name(type), index); } *(unsigned_4*)dest = H2LE_4(reg); } return nr_bytes;}static unsignedhw_opic_io_write_buffer(device *me, const void *source, int space, unsigned_word addr, unsigned nr_bytes, cpu *processor, unsigned_word cia){ hw_opic_device *opic = (hw_opic_device*)device_data(me); opic_register type; int index; decode_opic_address(me, opic, space, addr, nr_bytes, &type, &index); if (type == invalid_opic_register) { device_error(me, "invalid opic write access to %d:0x%lx (%d bytes)", space, (unsigned long)addr, nr_bytes); } else { unsigned reg = LE2H_4(*(unsigned_4*)source); switch (type) { case processor_init_register: do_processor_init_register_write(me, opic, reg); break; case interrupt_source_N_vector_priority_register: do_interrupt_source_N_vector_priority_register_write(me, opic, index, reg); break; case interrupt_source_N_destination_register: do_interrupt_source_N_destination_register_write(me, opic, index, reg); break; case end_of_interrupt_register_N: do_end_of_interrupt_register_N_write(me, opic, index, reg); break; case spurious_vector_register: do_spurious_vector_register_write(me, opic, reg); break; case current_task_priority_register_N: do_current_task_priority_register_N_write(me, opic, index, reg); break; case timer_frequency_reporting_register: do_timer_frequency_reporting_register_write(me, opic, reg); break; case timer_N_base_count_register: do_timer_N_base_count_register_write(me, opic, index, reg); break; case timer_N_vector_priority_register: do_timer_N_vector_priority_register_write(me, opic, index, reg); break; case timer_N_destination_register: do_timer_N_destination_register_write(me, opic, index, reg); break; case ipi_N_dispatch_register: do_ipi_N_dispatch_register_write(me, opic, index, reg); break; case ipi_N_vector_priority_register: do_ipi_N_vector_priority_register_write(me, opic, index, reg); break; case global_configuration_register_N: do_global_configuration_register_N_write(me, opic, index, reg); break; default: device_error(me, "unimplemented write to register %s[%d]", opic_register_name(type), index); } } return nr_bytes;} static voidhw_opic_interrupt_event(device *me, int my_port, device *source, int source_port, int level, cpu *processor, unsigned_word cia){ hw_opic_device *opic = (hw_opic_device*)device_data(me); int isb; int src_nr = 0; /* find the corresponding internal input port */ for (isb = 0; isb < opic->nr_isu_blocks; isb++) { if (my_port >= opic->isu_block[isb].int_number && my_port < opic->isu_block[isb].int_number + opic->isu_block[isb].range) { src_nr += my_port - opic->isu_block[isb].int_number; break; } else src_nr += opic->isu_block[isb].range; } if (isb == opic->nr_isu_blocks) device_error(me, "interrupt %d out of range", my_port); DTRACE(opic, ("external-interrupt %d, internal %d, level %d\n", my_port, src_nr, level)); /* pass it on */ ASSERT(src_nr >= 0 && src_nr < opic->nr_external_interrupts); handle_interrupt(me, opic, &opic->external_interrupt_source[src_nr], level);}static const device_interrupt_port_descriptor hw_opic_interrupt_ports[] = { { "irq", 0, max_nr_interrupt_sources, input_port, }, { "intr", 0, max_nr_interrupt_destinations, output_port, }, { "init", max_nr_interrupt_destinations, max_nr_interrupt_destinations, output_port, }, { NULL }};static device_callbacks const hw_opic_callbacks = { { generic_device_init_address, hw_opic_init_data }, { NULL, }, /* address */ { hw_opic_io_read_buffer, hw_opic_io_write_buffer }, /* IO */ { NULL, }, /* DMA */ { hw_opic_interrupt_event, NULL, hw_opic_interrupt_ports }, /* interrupt */ { NULL, }, /* unit */ NULL, /* instance */};static void *hw_opic_create(const char *name, const device_unit *unit_address, const char *args){ hw_opic_device *opic = ZALLOC(hw_opic_device); return opic;}const device_descriptor hw_opic_device_descriptor[] = { { "opic", hw_opic_create, &hw_opic_callbacks }, { NULL },};#endif /* _HW_OPIC_C_ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -