⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dev_ns16552.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
字号:
/* * Cisco 3600 simulation platform. * Copyright (c) 2006 Christophe Fillot (cf@utc.fr) * * NS16552 DUART. */#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 "ptask.h"#include "cpu.h"#include "vm.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "dev_vtty.h"/* Debugging flags */#define DEBUG_UNKNOWN  1#define DEBUG_ACCESS   0/* Interrupt Enable Register (IER) */#define	IER_ERXRDY    0x1#define	IER_ETXRDY    0x2/* Interrupt Identification Register */#define IIR_NPENDING  0x01   /* 0: irq pending, 1: no irq pending */#define	IIR_TXRDY     0x02#define	IIR_RXRDY     0x04/* Line Status Register (LSR) */#define	LSR_RXRDY     0x01#define	LSR_TXRDY     0x20#define	LSR_TXEMPTY   0x40/* UART channel */struct ns16552_channel {   u_int ier,output;   vtty_t *vtty;};/* NS16552 structure */struct ns16552_data {   vm_obj_t vm_obj;   struct vdevice dev;   vm_instance_t *vm;   u_int irq;      /* Register offset divisor */   u_int reg_div;   /* Periodic task to trigger DUART IRQ */   ptask_id_t tid;   struct ns16552_channel channel[2];   u_int duart_irq_seq;};/* Console port input */static void tty_con_input(vtty_t *vtty){   struct ns16552_data *d = vtty->priv_data;   if (d->channel[0].ier & IER_ERXRDY)      vm_set_irq(d->vm,d->irq);}/* AUX port input */static void tty_aux_input(vtty_t *vtty){   struct ns16552_data *d = vtty->priv_data;   if (d->channel[1].ier & IER_ERXRDY)      vm_set_irq(d->vm,d->irq);}/* IRQ trickery for Console and AUX ports */static int tty_trigger_dummy_irq(struct ns16552_data *d,void *arg){   d->duart_irq_seq++;      if (d->duart_irq_seq == 2) {      if (d->channel[0].ier & IER_ETXRDY) {         d->channel[0].output = TRUE;         vm_set_irq(d->vm,d->irq);      }#if 0      if (d->channel[1].ier & IER_ETXRDY) {         d->channel[1].output = TRUE;         vm_set_irq(d->vm,d->irq);      }#endif      d->duart_irq_seq = 0;   }   return(0);}/* * dev_ns16552_access() */void *dev_ns16552_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset,                         u_int op_size,u_int op_type,m_uint64_t *data){   struct ns16552_data *d = dev->priv_data;   int channel = 0;   u_char odata;   if (op_type == MTS_READ)      *data = 0;#if DEBUG_ACCESS   if (op_type == MTS_READ) {      cpu_log(cpu,"NS16552","read from 0x%x, pc=0x%llx\n",              offset,cpu_get_pc(cpu));   } else {      cpu_log(cpu,"NS16552","write to 0x%x, value=0x%llx, pc=0x%llx\n",              offset,*data,cpu_get_pc(cpu));   }#endif   offset >>= d->reg_div;   if (offset >= 0x08)      channel = 1;   switch(offset) {      /* Receiver Buffer Reg. (RBR) / Transmitting Holding Reg. (THR) */      case 0x00:      case 0x08:         if (op_type == MTS_WRITE) {            vtty_put_char(d->channel[channel].vtty,(char)*data);            if (d->channel[channel].ier & IER_ETXRDY)               vm_set_irq(d->vm,d->irq);            d->channel[channel].output = TRUE;         } else {            *data = vtty_get_char(d->channel[channel].vtty);         }         break;      /* Interrupt Enable Register (IER) */      case 0x01:      case 0x09:         if (op_type == MTS_READ) {            *data = d->channel[channel].ier;         } else {            d->channel[channel].ier = *data & 0xFF;            if ((*data & 0x02) == 0) {   /* transmit holding register */               d->channel[channel].vtty->managed_flush = TRUE;               vtty_flush(d->channel[channel].vtty);                           }         }         break;      /* Interrupt Ident Register (IIR) */      case 0x02:         vm_clear_irq(d->vm,d->irq);      case 0x0A:         if (op_type == MTS_READ) {            odata = IIR_NPENDING;            if (vtty_is_char_avail(d->channel[channel].vtty)) {               odata = IIR_RXRDY;            } else {               if (d->channel[channel].output) {                  odata = IIR_TXRDY;                  d->channel[channel].output = 0;               }            }            *data = odata;         }         break;      /* Line Status Register (LSR) */      case 0x05:      case 0x0D:         if (op_type == MTS_READ) {            odata = 0;            if (vtty_is_char_avail(d->channel[channel].vtty))               odata |= LSR_RXRDY;            odata |= LSR_TXRDY|LSR_TXEMPTY;            *data = odata;         }         break;#if DEBUG_UNKNOWN      default:         if (op_type == MTS_READ) {            cpu_log(cpu,"NS16552","read from addr 0x%x, pc=0x%llx (size=%u)\n",                    offset,cpu_get_pc(cpu),op_size);         } else {            cpu_log(cpu,                    "NS16552","write to addr 0x%x, value=0x%llx, "                    "pc=0x%llx (size=%u)\n",                    offset,*data,cpu_get_pc(cpu),op_size);         }#endif   }   return NULL;}/* Shutdown a NS16552 device */void dev_ns16552_shutdown(vm_instance_t *vm,struct ns16552_data *d){   if (d != NULL) {      d->channel[0].vtty->read_notifier = NULL;      d->channel[1].vtty->read_notifier = NULL;      /* Remove the periodic task */      ptask_remove(d->tid);      /* Remove the device */      dev_remove(vm,&d->dev);      /* Free the structure itself */      free(d);   }}/* Create a NS16552 device */int dev_ns16552_init(vm_instance_t *vm,m_uint64_t paddr,m_uint32_t len,                     u_int reg_div,u_int irq,vtty_t *vtty_A,vtty_t *vtty_B){     struct ns16552_data *d;   /* Allocate private data structure */   if (!(d = malloc(sizeof(*d)))) {      fprintf(stderr,"NS16552: out of memory\n");      return(-1);   }   memset(d,0,sizeof(*d));   d->vm  = vm;   d->irq = irq;   d->reg_div = reg_div;   d->channel[0].vtty = vtty_A;   d->channel[1].vtty = vtty_B;   vm_object_init(&d->vm_obj);   d->vm_obj.name = "ns16552";   d->vm_obj.data = d;   d->vm_obj.shutdown = (vm_shutdown_t)dev_ns16552_shutdown;   /* Set device properties */   dev_init(&d->dev);   d->dev.name      = "ns16552";   d->dev.phys_addr = paddr;   d->dev.phys_len  = len;   d->dev.handler   = dev_ns16552_access;   d->dev.priv_data = d;   vtty_A->priv_data = d;   vtty_B->priv_data = d;   vtty_A->read_notifier = tty_con_input;   vtty_B->read_notifier = tty_aux_input;   /* Trigger periodically a dummy IRQ to flush buffers */   d->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 + -