📄 hw_opic.c
字号:
/* check to see if that shouldn't be interrupted */ dest->current_pending = find_interrupt_for_dest(me, opic, dest, pending_interrupt); if (can_deliver(me, dest->current_pending, dest)) { ASSERT(dest->current_pending->pending & dest->bit); assert_interrupt(me, opic, dest); } else { dest->current_pending = NULL; }}static voiddecode_opic_address(device *me, hw_opic_device *opic, int space, unsigned_word address, unsigned nr_bytes, opic_register *type, int *index){ int isb = 0; /* is the size valid? */ if (nr_bytes != 4) { *type = invalid_opic_register; *index = -1; return; } /* try for a per-processor register within the interrupt delivery unit */ if (space == opic->idu.space && address >= (opic->idu.address + idu_per_processor_register_base) && address < (opic->idu.address + idu_per_processor_register_base + (sizeof_idu_per_processor_register_block * opic->nr_interrupt_destinations))) { unsigned_word block_offset = (address - opic->idu.address - idu_per_processor_register_base); unsigned_word offset = block_offset % sizeof_idu_per_processor_register_block; *index = block_offset / sizeof_idu_per_processor_register_block; switch (offset) { case 0x040: *type = ipi_N_dispatch_register; *index = 0; break; case 0x050: *type = ipi_N_dispatch_register; *index = 1; break; case 0x060: *type = ipi_N_dispatch_register; *index = 2; break; case 0x070: *type = ipi_N_dispatch_register; *index = 3; break; case 0x080: *type = current_task_priority_register_N; break; case 0x0a0: *type = interrupt_acknowledge_register_N; break; case 0x0b0: *type = end_of_interrupt_register_N; break; default: *type = invalid_opic_register; break; } DTRACE(opic, ("per-processor register %d:0x%lx - %s[%d]\n", space, (unsigned long)address, opic_register_name(*type), *index)); return; } /* try for an interrupt source unit */ for (isb = 0; isb < opic->nr_isu_blocks; isb++) { if (opic->isu_block[isb].space == space && address >= opic->isu_block[isb].address && address < (opic->isu_block[isb].address + opic->isu_block[isb].size)) { unsigned_word block_offset = address - opic->isu_block[isb].address; unsigned_word offset = block_offset % sizeof_isu_register_block; *index = (opic->isu_block[isb].int_number + (block_offset / sizeof_isu_register_block)); switch (offset) { case 0x00: *type = interrupt_source_N_vector_priority_register; break; case 0x10: *type = interrupt_source_N_destination_register; break; default: *type = invalid_opic_register; break; } DTRACE(opic, ("isu register %d:0x%lx - %s[%d]\n", space, (unsigned long)address, opic_register_name(*type), *index)); return; } } /* try for a timer */ if (space == opic->idu.space && address >= (opic->idu.address + idu_timer_base) && address < (opic->idu.address + idu_timer_base + opic->nr_timer_interrupts * sizeof_timer_register_block)) { unsigned_word offset = address % sizeof_timer_register_block; *index = ((address - opic->idu.address - idu_timer_base) / sizeof_timer_register_block); switch (offset) { case 0x00: *type = timer_N_current_count_register; break; case 0x10: *type = timer_N_base_count_register; break; case 0x20: *type = timer_N_vector_priority_register; break; case 0x30: *type = timer_N_destination_register; break; default: *type = invalid_opic_register; break; } DTRACE(opic, ("timer register %d:0x%lx - %s[%d]\n", space, (unsigned long)address, opic_register_name(*type), *index)); return; } /* finally some other misc global register */ if (space == opic->idu.space && address >= opic->idu.address && address < opic->idu.address + opic->idu.size) { unsigned_word block_offset = address - opic->idu.address; switch (block_offset) { case 0x010f0: *type = timer_frequency_reporting_register; *index = -1; break; case 0x010e0: *type = spurious_vector_register; *index = -1; break; case 0x010d0: case 0x010c0: case 0x010b0: case 0x010a0: *type = ipi_N_vector_priority_register; *index = (block_offset - 0x010a0) / 16; break; case 0x01090: *type = processor_init_register; *index = -1; break; case 0x01080: *type = vendor_identification_register; *index = -1; break; case 0x01020: *type = global_configuration_register_N; *index = 0; break; case 0x01000: *type = feature_reporting_register_N; *index = 0; break; default: *type = invalid_opic_register; *index = -1; break; } DTRACE(opic, ("global register %d:0x%lx - %s[%d]\n", space, (unsigned long)address, opic_register_name(*type), *index)); return; } /* nothing matched */ *type = invalid_opic_register; DTRACE(opic, ("invalid register %d:0x%lx\n", space, (unsigned long)address)); return;}/* Processor init register: The bits in this register (one per processor) are directly wired to output "init" interrupt ports. */static unsigneddo_processor_init_register_read(device *me, hw_opic_device *opic){ unsigned reg = opic->init; DTRACE(opic, ("processor init register - read 0x%lx\n", (long)reg)); return reg;}static voiddo_processor_init_register_write(device *me, hw_opic_device *opic, unsigned reg){ int i; for (i = 0; i < opic->nr_interrupt_destinations; i++) { opic_interrupt_destination *dest = &opic->interrupt_destination[i]; if ((reg & dest->bit) != (opic->init & dest->bit)) { if (reg & dest->bit) { DTRACE(opic, ("processor init register - write 0x%lx - asserting init%d\n", (long)reg, i)); opic->init |= dest->bit; device_interrupt_event(me, dest->init_port, 1, NULL, 0); } else { DTRACE(opic, ("processor init register - write 0x%lx - negating init%d\n", (long)reg, i)); opic->init &= ~dest->bit; device_interrupt_event(me, dest->init_port, 0, NULL, 0); } } }}/* Interrupt Source Vector/Priority Register: */static unsignedread_vector_priority_register(device *me, hw_opic_device *opic, opic_interrupt_source *interrupt, const char *reg_name, int reg_index){ unsigned reg; reg = 0; reg |= interrupt->is_masked; reg |= (interrupt->in_service || interrupt->pending ? isu_active_bit : 0); /* active */ reg |= interrupt->is_multicast; reg |= interrupt->is_positive_polarity; reg |= interrupt->is_level_triggered; /* sense? */ reg |= interrupt->priority << isu_priority_shift; reg |= interrupt->vector; DTRACE(opic, ("%s %d vector/priority register - read 0x%lx\n", reg_name, reg_index, (unsigned long)reg)); return reg;}static unsigneddo_interrupt_source_N_vector_priority_register_read(device *me, hw_opic_device *opic, int index){ unsigned reg; ASSERT(index < opic->nr_external_interrupts); reg = read_vector_priority_register(me, opic, &opic->interrupt_source[index], "interrupt source", index); return reg;}static voidwrite_vector_priority_register(device *me, hw_opic_device *opic, opic_interrupt_source *interrupt, unsigned reg, const char *reg_name, int reg_index){ interrupt->is_masked = (reg & isu_mask_bit); interrupt->is_multicast = (reg & isu_multicast_bit); interrupt->is_positive_polarity = (reg & isu_positive_polarity_bit); interrupt->is_level_triggered = (reg & isu_level_triggered_bit); interrupt->priority = ((reg >> isu_priority_shift) % max_nr_task_priorities); interrupt->vector = (reg & isu_vector_bits); DTRACE(opic, ("%s %d vector/priority register - write 0x%lx - %s%s%s-polarity, %s-triggered, priority %ld vector %ld\n", reg_name, reg_index, (unsigned long)reg, interrupt->is_masked ? "masked, " : "", interrupt->is_multicast ? "multicast, " : "", interrupt->is_positive_polarity ? "positive" : "negative", interrupt->is_level_triggered ? "level" : "edge", (long)interrupt->priority, (long)interrupt->vector));}static voiddo_interrupt_source_N_vector_priority_register_write(device *me, hw_opic_device *opic, int index, unsigned reg){ ASSERT(index < opic->nr_external_interrupts); reg &= ~isu_multicast_bit; /* disable multicast */ write_vector_priority_register(me, opic, &opic->interrupt_source[index], reg, "interrupt source", index);}/* Interrupt Source Destination Register: */static unsignedread_destination_register(device *me, hw_opic_device *opic, opic_interrupt_source *interrupt, const char *reg_name, int reg_index){ unsigned long reg; reg = interrupt->destination; DTRACE(opic, ("%s %d destination register - read 0x%lx\n", reg_name, reg_index, reg)); return reg;} static unsigneddo_interrupt_source_N_destination_register_read(device *me, hw_opic_device *opic, int index){ unsigned reg; ASSERT(index < opic->nr_external_interrupts); reg = read_destination_register(me, opic, &opic->external_interrupt_source[index], "interrupt source", index); return reg;}static voidwrite_destination_register(device *me, hw_opic_device *opic, opic_interrupt_source *interrupt, unsigned reg, const char *reg_name, int reg_index){ reg &= (1 << opic->nr_interrupt_destinations) - 1; /* mask out invalid */ DTRACE(opic, ("%s %d destination register - write 0x%x\n", reg_name, reg_index, reg)); interrupt->destination = reg;}static voiddo_interrupt_source_N_destination_register_write(device *me, hw_opic_device *opic, int index, unsigned reg){ ASSERT(index < opic->nr_external_interrupts); write_destination_register(me, opic, &opic->external_interrupt_source[index], reg, "interrupt source", index);}/* Spurious vector register: */static unsigneddo_spurious_vector_register_read(device *me, hw_opic_device *opic){ unsigned long reg = opic->spurious_vector; DTRACE(opic, ("spurious vector register - read 0x%lx\n", reg)); return reg;}static voiddo_spurious_vector_register_write(device *me, hw_opic_device *opic, unsigned reg){ reg &= 0xff; /* mask off invalid */ DTRACE(opic, ("spurious vector register - write 0x%x\n", reg)); opic->spurious_vector = reg;}/* current task priority register: */static unsigneddo_current_task_priority_register_N_read(device *me, hw_opic_device *opic, int index){ opic_interrupt_destination *interrupt_destination = &opic->interrupt_destination[index]; unsigned reg; ASSERT(index >= 0 && index < opic->nr_interrupt_destinations); reg = interrupt_destination->base_priority; DTRACE(opic, ("current task priority register %d - read 0x%x\n", index, reg)); return reg;}static voiddo_current_task_priority_register_N_write(device *me, hw_opic_device *opic, int index, unsigned reg){ opic_interrupt_destination *interrupt_destination = &opic->interrupt_destination[index]; ASSERT(index >= 0 && index < opic->nr_interrupt_destinations); reg %= max_nr_task_priorities; DTRACE(opic, ("current task priority register %d - write 0x%x\n", index, reg)); interrupt_destination->base_priority = reg;}/* Timer Frequency Reporting Register: */static unsigneddo_timer_frequency_reporting_register_read(device *me, hw_opic_device *opic){ unsigned reg; reg = opic->timer_frequency; DTRACE(opic, ("timer frequency reporting register - read 0x%x\n", reg)); return reg;}static voiddo_timer_frequency_reporting_register_write(device *me, hw_opic_device *opic, unsigned reg){ DTRACE(opic, ("timer frequency reporting register - write 0x%x\n", reg)); opic->timer_frequency = reg;}/* timer registers: */static unsigneddo_timer_N_current_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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -