📄 dev_sb1_io.c
字号:
/* * Cisco 7200 (Predator) simulation platform. * Copyright (c) 2005 Christophe Fillot (cf@utc.fr) * * SB-1 I/O devices. * * XXX: just for tests! */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <termios.h>#include <fcntl.h>#include <pthread.h>#include "utils.h"#include "ptask.h"#include "mips64.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "dev_c7200.h"#define DEBUG_UNKNOWN 1/* DUART Status Register */#define DUART_SR_RX_RDY 0x01 /* Receiver ready */#define DUART_SR_RX_FFUL 0x02 /* Receive FIFO full */#define DUART_SR_TX_RDY 0x04 /* Transmitter ready */#define DUART_SR_TX_EMT 0x08 /* Transmitter empty *//* DUART Interrupt Status Register */#define DUART_ISR_TXA 0x01 /* Channel A Transmitter Ready */#define DUART_ISR_RXA 0x02 /* Channel A Receiver Ready */#define DUART_ISR_TXB 0x10 /* Channel B Transmitter Ready */#define DUART_ISR_RXB 0x20 /* Channel B Receiver Ready *//* DUART Interrupt Mask Register */#define DUART_IMR_TXA 0x01 /* Channel A Transmitter Ready */#define DUART_IMR_RXA 0x02 /* Channel A Receiver Ready */#define DUART_IMR_TXB 0x10 /* Channel B Transmitter Ready */#define DUART_IMR_RXB 0x20 /* Channel B Receiver Ready *//* SB-1 DUART channel */struct sb1_duart_channel { m_uint8_t mode; m_uint8_t cmd;};/* SB-1 I/O private data */struct sb1_io_data { vm_obj_t vm_obj; struct vdevice dev; /* Virtual machine */ vm_instance_t *vm; /* DUART info */ u_int duart_irq,duart_irq_seq; m_uint8_t duart_isr,duart_imr; struct sb1_duart_channel duart_chan[2]; /* Periodic task to trigger dummy DUART IRQ */ ptask_id_t duart_irq_tid;};/* Console port input */static void tty_con_input(vtty_t *vtty){ struct sb1_io_data *d = vtty->priv_data; if (d->duart_imr & DUART_IMR_RXA) { d->duart_isr |= DUART_ISR_RXA; vm_set_irq(d->vm,d->duart_irq); }}/* AUX port input */static void tty_aux_input(vtty_t *vtty){ struct sb1_io_data *d = vtty->priv_data; if (d->duart_imr & DUART_IMR_RXB) { d->duart_isr |= DUART_ISR_RXB; vm_set_irq(d->vm,d->duart_irq); }}/* IRQ trickery for Console and AUX ports */static int tty_trigger_dummy_irq(struct sb1_io_data *d,void *arg){ u_int mask; d->duart_irq_seq++; if (d->duart_irq_seq == 2) { mask = DUART_IMR_TXA|DUART_IMR_TXB; if (d->duart_imr & mask) { d->duart_isr |= DUART_ISR_TXA|DUART_ISR_TXB; vm_set_irq(d->vm,d->duart_irq); } d->duart_irq_seq = 0; } return(0);}/* * dev_sb1_io_access() */void *dev_sb1_io_access(cpu_mips_t *cpu,struct vdevice *dev, m_uint32_t offset,u_int op_size,u_int op_type, m_uint64_t *data){ struct sb1_io_data *d = dev->priv_data; u_char odata; if (op_type == MTS_READ) *data = 0; switch(offset) { case 0x390: /* DUART Interrupt Status Register */ if (op_type == MTS_READ) *data = d->duart_isr; break; case 0x320: /* DUART Channel A Only Interrupt Status Register */ if (op_type == MTS_READ) *data = d->duart_isr & 0x0F; break; case 0x340: /* DUART Channel B Only Interrupt Status Register */ if (op_type == MTS_READ) *data = (d->duart_isr >> 4) & 0x0F; break; case 0x3a0: /* DUART Interrupt Mask Register */ if (op_type == MTS_READ) *data = d->duart_imr; else d->duart_imr = *data; break; case 0x330: /* DUART Channel A Only Interrupt Mask Register */ if (op_type == MTS_READ) { *data = d->duart_imr & 0x0F; } else { d->duart_imr &= ~0x0F; d->duart_imr |= *data & 0x0F; } break; case 0x350: /* DUART Channel B Only Interrupt Mask Register */ if (op_type == MTS_READ) { *data = (d->duart_imr >> 4) & 0x0F; } else { d->duart_imr &= ~0xF0; d->duart_imr |= (*data & 0x0F) << 4; } break; case 0x100: /* DUART Mode (Channel A) */ if (op_type == MTS_READ) d->duart_chan[0].mode = *data; else *data = d->duart_chan[0].mode; break; case 0x200: /* DUART Mode (Channel B) */ if (op_type == MTS_READ) d->duart_chan[1].mode = *data; else *data = d->duart_chan[1].mode; break; case 0x150: /* DUART Command Register (Channel A) */ if (op_type == MTS_READ) d->duart_chan[0].cmd = *data; else *data = d->duart_chan[0].cmd; break; case 0x250: /* DUART Command Register (Channel B) */ if (op_type == MTS_READ) d->duart_chan[1].cmd = *data; else *data = d->duart_chan[1].cmd; break; case 0x120: /* DUART Status Register (Channel A) */ if (op_type == MTS_READ) { odata = 0; if (vtty_is_char_avail(d->vm->vtty_con)) odata |= DUART_SR_RX_RDY; odata |= DUART_SR_TX_RDY; vm_clear_irq(d->vm,d->duart_irq); *data = odata; } break; case 0x220: /* DUART Status Register (Channel B) */ if (op_type == MTS_READ) { odata = 0; if (vtty_is_char_avail(d->vm->vtty_aux)) odata |= DUART_SR_RX_RDY; odata |= DUART_SR_TX_RDY; //vm_clear_irq(d->vm,d->duart_irq); *data = odata; } break; case 0x160: /* DUART Received Data Register (Channel A) */ if (op_type == MTS_READ) { *data = vtty_get_char(d->vm->vtty_con); d->duart_isr &= ~DUART_ISR_RXA; } break; case 0x260: /* DUART Received Data Register (Channel B) */ if (op_type == MTS_READ) { *data = vtty_get_char(d->vm->vtty_aux); d->duart_isr &= ~DUART_ISR_RXB; } break; case 0x170: /* DUART Transmit Data Register (Channel A) */ if (op_type == MTS_WRITE) { vtty_put_char(d->vm->vtty_con,(char)*data); d->duart_isr &= ~DUART_ISR_TXA; } break; case 0x270: /* DUART Transmit Data Register (Channel B) */ if (op_type == MTS_WRITE) { vtty_put_char(d->vm->vtty_aux,(char)*data); d->duart_isr &= ~DUART_ISR_TXB; } break; case 0x1a76: /* pcmcia status */ if (op_type == MTS_READ) *data = 0xFF; break;#if DEBUG_UNKNOWN default: if (op_type == MTS_READ) { cpu_log(cpu,"SB1_IO","read from addr 0x%x, pc=0x%llx\n", offset,cpu->pc); } else { cpu_log(cpu,"SB1_IO","write to addr 0x%x, value=0x%llx, " "pc=0x%llx\n",offset,*data,cpu->pc); }#endif } return NULL;}/* Shutdown the SB-1 I/O devices */void dev_sb1_io_shutdown(vm_instance_t *vm,struct sb1_io_data *d){ if (d != NULL) { /* Remove the device */ dev_remove(vm,&d->dev); /* Free the structure itself */ free(d); }}/* Create SB-1 I/O devices */int dev_sb1_io_init(vm_instance_t *vm,u_int duart_irq){ struct sb1_io_data *d; /* allocate private data structure */ if (!(d = malloc(sizeof(*d)))) { fprintf(stderr,"SB1_IO: out of memory\n"); return(-1); } memset(d,0,sizeof(*d)); d->vm = vm; d->duart_irq = duart_irq; vm_object_init(&d->vm_obj); d->vm_obj.name = "sb1_io"; d->vm_obj.data = d; d->vm_obj.shutdown = (vm_shutdown_t)dev_sb1_io_shutdown; /* Set device properties */ dev_init(&d->dev); d->dev.name = "sb1_io"; d->dev.priv_data = d; d->dev.phys_addr = 0x10060000ULL; d->dev.phys_len = 0x10000; d->dev.handler = dev_sb1_io_access; /* Set console and AUX port notifying functions */ vm->vtty_con->priv_data = d; vm->vtty_aux->priv_data = d; vm->vtty_con->read_notifier = tty_con_input; vm->vtty_aux->read_notifier = tty_aux_input; /* Trigger periodically a dummy IRQ to flush buffers */ d->duart_irq_tid = ptask_add((ptask_callback)tty_trigger_dummy_irq,d,NULL); /* Map this device to the VM */ vm_bind_device(vm,&d->dev); vm_object_add(vm,&d->vm_obj); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -