📄 dv-mn103int.c
字号:
static voidmn103int_port_event (struct hw *me, int my_port, struct hw *source, int source_port, int level){ struct mn103int *controller = hw_data (me); switch (my_port) { case ACK_PORT: { int selected = find_highest_interrupt_group (me, controller); if (controller->group[selected].level != level) hw_abort (me, "botched level synchronisation"); controller->interrupt_accepted_group = selected; HW_TRACE ((me, "port-event port=ack level=%d - selected=%d", level, selected)); break; } default: { int gid; int iid; struct mn103int_group *group; unsigned interrupt; if (my_port > NR_G_PORTS) hw_abort (me, "Event on unknown port %d", my_port); /* map the port onto an interrupt group */ gid = (my_port % NR_G_PORTS) / 4; group = &controller->group[gid]; iid = (my_port % 4); interrupt = 1 << iid; /* update our cached input */ if (level) group->input |= interrupt; else group->input &= ~interrupt; /* update the request bits */ switch (group->trigger) { case ACTIVE_LOW: case ACTIVE_HIGH: if (level) group->request |= interrupt; break; case NEGATIVE_EDGE: case POSITIVE_EDGE: group->request |= interrupt; } /* force a corresponding output */ switch (group->type) { case NMI_GROUP: { /* for NMI's the event is the trigger */ HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - NMI", my_port, gid, iid)); if ((group->request & group->enable) != 0) { HW_TRACE ((me, "port-out NMI")); hw_port_event (me, NMI_PORT, 1); } break; } case LEVEL_GROUP: { /* if an interrupt is now pending */ HW_TRACE ((me, "port-in port=%d group=%d interrupt=%d - INT", my_port, gid, iid)); push_interrupt_level (me, controller); break; } } break; } }}/* Read/write to to an ICR (group control register) */static struct mn103int_group *decode_group (struct hw *me, struct mn103int *controller, unsigned_word base, unsigned_word *offset){ int gid = (base / 4) % NR_GROUPS; *offset = (base % 4); return &controller->group[gid];}static unsigned8read_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 voidwrite_icr (struct hw *me, struct mn103int *controller, unsigned_word base, unsigned8 val){ unsigned_word offset; struct mn103int_group *group = decode_group (me, controller, base, &offset); switch (group->type) { case NMI_GROUP: switch (offset) { case 0: HW_TRACE ((me, "write-icr group=%d:0 nmi 0x%02x", group->gid, val)); group->request &= ~EXTRACT_ID (val); break; /* Special backdoor access to SYSEF flag from CPU. See interp.c:program_interrupt(). */ case 3: HW_TRACE ((me, "write-icr-special group=%d:0 nmi 0x%02x", group->gid, val)); group->request |= EXTRACT_ID (val); default: break; } break; case LEVEL_GROUP: switch (offset) { case 0: /* request/detect */ /* Clear any ID bits and then set them according to IR */ HW_TRACE ((me, "write-icr group=%d:0 level 0x%02x %x:%x:%x", group->gid, val, group->request, EXTRACT_IR (val), EXTRACT_ID (val))); group->request = ((EXTRACT_IR (val) & EXTRACT_ID (val)) | (EXTRACT_IR (val) & group->request) | (~EXTRACT_IR (val) & ~EXTRACT_ID (val) & group->request)); break; case 1: /* level/enable */ HW_TRACE ((me, "write-icr group=%d:1 level 0x%02x", group->gid, val)); group->level = EXTRACT_LV (val); group->enable = EXTRACT_IE (val); break; default: /* ignore */ break; } push_interrupt_level (me, controller); break; default: break; }}/* Read the IAGR (Interrupt accepted group register) */static unsigned8read_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;}/* Reads/writes to the EXTMD (external interrupt trigger configuration register) */static struct mn103int_group *external_group (struct mn103int *controller, unsigned_word offset){ switch (offset) { case 0: return &controller->group[IRQ0_PORT/4]; case 1: return &controller->group[IRQ4_PORT/4]; default: return NULL; }}static unsigned8read_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 voidwrite_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));}/* generic read/write */static intdecode_addr (struct hw *me, struct mn103int *controller, unsigned_word address, unsigned_word *offset){ int i; for (i = 0; i < NR_BLOCKS; i++) { if (address >= controller->block[i].base && address <= controller->block[i].bound) { *offset = address - controller->block[i].base; return i; } } hw_abort (me, "bad address"); return -1;}static unsignedmn103int_io_read_buffer (struct hw *me, void *dest, int space, unsigned_word base, unsigned nr_bytes){ struct mn103int *controller = hw_data (me); unsigned8 *buf = dest; unsigned byte; /* HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); */ for (byte = 0; byte < nr_bytes; byte++) { unsigned_word address = base + byte; unsigned_word offset; switch (decode_addr (me, controller, address, &offset)) { case ICR_BLOCK: buf[byte] = read_icr (me, controller, offset); break; case IAGR_BLOCK: buf[byte] = read_iagr (me, controller, offset); break; case EXTMD_BLOCK: buf[byte] = read_extmd (me, controller, offset); break; default: hw_abort (me, "bad switch"); } } return nr_bytes;} static unsignedmn103int_io_write_buffer (struct hw *me, const void *source, int space, unsigned_word base, unsigned nr_bytes){ struct mn103int *controller = hw_data (me); const unsigned8 *buf = source; unsigned byte; /* HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); */ for (byte = 0; byte < nr_bytes; byte++) { unsigned_word address = base + byte; unsigned_word offset; switch (decode_addr (me, controller, address, &offset)) { case ICR_BLOCK: write_icr (me, controller, offset, buf[byte]); break; case IAGR_BLOCK: /* not allowed */ break; case EXTMD_BLOCK: write_extmd (me, controller, offset, buf[byte]); break; default: hw_abort (me, "bad switch"); } } return nr_bytes;} static intmn103int_ioctl(struct hw *me, hw_ioctl_request request, va_list ap){ struct mn103int *controller = (struct mn103int *)hw_data(me); controller->group[0].request = EXTRACT_ID(4); mn103int_port_event(me, 2 /* nmi_port(syserr) */, NULL, 0, 0); return 0;}const struct hw_descriptor dv_mn103int_descriptor[] = { { "mn103int", mn103int_finish, }, { NULL },};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -