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

📄 dev_mueslix.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   * Cisco C7200 (Predator) Simulation Platform. * Copyright (C) 2005,2006 Christophe Fillot.  All rights reserved. * * Serial Interfaces (Mueslix). * * Note: "debug serial mueslix" gives more technical info. * * Chip mode: Cisco models 36xx and 72xx don't seem to use the same microcode, * so there are code variants to make things work properly. * *  Chip mode 0 => 3600 *  Chip mode 1 => 7200 * * 2 points noticed until now:  *    - RX/TX ring wrapping checks are done differently, *    - TX packet sizes are not specified in the same way. * * Test methodology: *    - Connect two virtual routers together ; *    - Do pings by sending 10 packets by 10 packets. If this stops working, *      count the number of transmitted packets and check with RX/TX rings *      sizes. This is problably a ring wrapping problem. *    - Do multiple pings with various sizes (padding checks); *    - Check if CDP is working, with various hostname sizes. Since CDP *      contains a checksum, it is a good way to determine if packets are *      sent/received correctly. *    - Do a Telnet from both virtual router to the other one, and do a *      "sh run". */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <assert.h>#include "mips64.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "net.h"#include "net_io.h"#include "ptask.h"#include "dev_mueslix.h"/* Debugging flags */#define DEBUG_ACCESS     0#define DEBUG_UNKNOWN    0#define DEBUG_PCI_REGS   0#define DEBUG_TRANSMIT   0#define DEBUG_RECEIVE    0/* Mueslix PCI vendor/product codes */#define MUESLIX_PCI_VENDOR_ID   0x1137#define MUESLIX_PCI_PRODUCT_ID  0x0001/* Number of channels (4 interfaces) */#define MUESLIX_NR_CHANNELS  4#define MUESLIX_CHANNEL_LEN  0x100/* RX/TX status for a channel */#define MUESLIX_CHANNEL_STATUS_RX  0x01#define MUESLIX_CHANNEL_STATUS_TX  0x02/* RX/TX enable masks (XXX check if bit position is correct) */#define MUESLIX_TX_ENABLE   0x01#define MUESLIX_RX_ENABLE   0x02/* RX/TX IRQ masks */#define MUESLIX_TX_IRQ   0x01#define MUESLIX_RX_IRQ   0x10/* Addresses of ports */#define MUESLIX_CHANNEL0_OFFSET  0x100#define MUESLIX_CHANNEL1_OFFSET  0x200#define MUESLIX_CHANNEL2_OFFSET  0x300#define MUESLIX_CHANNEL3_OFFSET  0x400/* TPU Registers */#define MUESLIX_TPU_CMD_OFFSET     0x2c24#define MUESLIX_TPU_CMD_RSP_OFFSET 0x2c2c/* General and channels registers */#define MUESLIX_GEN_CHAN_LEN  0x500/* TPU microcode */#define MUESLIX_UCODE_OFFSET  0x2000#define MUESLIX_UCODE_LEN     0x800/* TPU Xmem and YMem */#define MUESLIX_XMEM_OFFSET   0x2a00#define MUESLIX_YMEM_OFFSET   0x2b00#define MUESLIX_XYMEM_LEN     0x100/* Maximum packet size */#define MUESLIX_MAX_PKT_SIZE  2048/* Send up to 16 packets in a TX ring scan pass */#define MUESLIX_TXRING_PASS_COUNT  16/* RX descriptors */#define MUESLIX_RXDESC_OWN        0x80000000  /* Ownership */#define MUESLIX_RXDESC_FS         0x40000000  /* First Segment */#define MUESLIX_RXDESC_LS         0x20000000  /* Last Segment */#define MUESLIX_RXDESC_OVERRUN    0x10000000  /* Overrun */#define MUESLIX_RXDESC_IGNORED    0x08000000  /* Ignored */#define MUESLIX_RXDESC_ABORT      0x04000000  /* Abort */#define MUESLIX_RXDESC_CRC        0x02000000  /* CRC error */#define MUESLIX_RXDESC_LEN_MASK   0xfff/* TX descriptors */#define MUESLIX_TXDESC_OWN        0x80000000  /* Ownership */#define MUESLIX_TXDESC_FS         0x40000000  /* First Segment */#define MUESLIX_TXDESC_LS         0x20000000  /* Last Segment */#define MUESLIX_TXDESC_SUB        0x00100000  /* Length substractor ? */#define MUESLIX_TXDESC_SUB_LEN    0x03000000  /* Length substrator ? */#define MUESLIX_TXDESC_SUB_SHIFT  24#define MUESLIX_TXDESC_PAD        0x00c00000  /* Sort of padding info ? */#define MUESLIX_TXDESC_PAD_SHIFT  22#define MUESLIX_TXDESC_LEN_MASK   0xfff/* RX Descriptor */struct rx_desc {   m_uint32_t rdes[2];};/* TX Descriptor */struct tx_desc {   m_uint32_t tdes[2];};/* Forward declaration of Mueslix data */typedef struct mueslix_data mueslix_data_t;/* Mueslix channel */struct mueslix_channel {   /* Channel ID */   u_int id;   /* RX/TX status */   u_int rx_tx_status;   /* Channel status (0=disabled) */   u_int status;   /* NetIO descriptor */   netio_desc_t *nio;   /* TX ring scanners task id */   ptask_id_t tx_tid;   /* physical addresses for start and end of RX/TX rings */   m_uint32_t rx_start,rx_end,tx_start,tx_end;     /* physical addresses of current RX and TX descriptors */   m_uint32_t rx_current,tx_current;   /* Parent mueslix structure */   mueslix_data_t *parent;};/* Mueslix Data */struct mueslix_data {   char *name;      /* TPU options */   m_uint32_t tpu_options;   /* Virtual machine */   vm_instance_t *vm;   /* Virtual device */   struct vdevice *dev;   /* PCI device information */   struct pci_device *pci_dev;   /* Chip mode:     *    * 0=increment ring pointers before check + direct TX size,    * 1=increment ring pointers after check  + "complex" TX size.    */   int chip_mode;   /* Channels */   struct mueslix_channel channel[MUESLIX_NR_CHANNELS];   m_uint32_t channel_enable_mask;   /* TPU microcode */   u_char ucode[MUESLIX_UCODE_LEN];   /* TPU Xmem and Ymem */   u_char xmem[MUESLIX_XYMEM_LEN];   u_char ymem[MUESLIX_XYMEM_LEN];};/* Offsets of the 4 channels */static m_uint32_t channel_offset[MUESLIX_NR_CHANNELS] = {   MUESLIX_CHANNEL0_OFFSET, MUESLIX_CHANNEL1_OFFSET,   MUESLIX_CHANNEL2_OFFSET, MUESLIX_CHANNEL3_OFFSET,};/* Log a Mueslix message */#define MUESLIX_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)/* Returns TRUE if RX/TX is enabled for a channel */static inline int dev_mueslix_is_rx_tx_enabled(struct mueslix_data *d,u_int id){   /* 2 bits for RX/TX, 4 channels max */   return((d->channel_enable_mask >> (id << 1)) & 0x03);}/* * Access to channel registers. */void dev_mueslix_chan_access(cpu_mips_t *cpu,struct mueslix_channel *channel,                             m_uint32_t offset,u_int op_size,u_int op_type,                             m_uint64_t *data){   switch(offset) {      case 0x60: /* signals ? */         if ((op_type == MTS_READ) && (channel->nio != NULL))            *data = 0xFFFFFFFF;         break;      case 0x64: /* port status - cable type and probably other things */         if (op_type == MTS_READ)            *data = 0x7B;         break;      case 0x90: /* has influence on clock rate */         if (op_type == MTS_READ)            *data = 0x11111111;         break;      case 0x80: /* TX start */         if (op_type == MTS_WRITE)            channel->tx_start = channel->tx_current = *data;         else            *data = channel->tx_start;         break;      case 0x84: /* TX end */         if (op_type == MTS_WRITE)            channel->tx_end = *data;         else            *data = channel->tx_end;         break;      case 0x88: /* RX start */         if (op_type == MTS_WRITE)            channel->rx_start = channel->rx_current = *data;         else            *data = channel->rx_start;         break;      case 0x8c: /* RX end */         if (op_type == MTS_WRITE)            channel->rx_end = *data;         else            *data = channel->rx_end;         break;   }}/* Handle TPU commands for chip mode 0 (3600) */static void tpu_cm0_handle_cmd(struct mueslix_data *d,u_int cmd){      struct mueslix_channel *channel;   u_int opcode,channel_id;   opcode = (cmd >> 12) & 0xFF;   channel_id = cmd & 0x03;   channel = &d->channel[channel_id];   switch(opcode) {      case 0x10:         MUESLIX_LOG(d,"channel %u disabled\n",channel_id);         channel->status = 0;         break;      case 0x00:         MUESLIX_LOG(d,"channel %u enabled\n",channel_id);         channel->status = 1;         break;      default:         MUESLIX_LOG(d,"unknown command 0x%5x\n",cmd);   }}/* Handle TPU commands for chip mode 1 (7200) */static void tpu_cm1_handle_cmd(struct mueslix_data *d,u_int cmd){      struct mueslix_channel *channel;   u_int opcode,channel_id;   opcode = (cmd >> 12) & 0xFF;   channel_id = cmd & 0x03;   channel = &d->channel[channel_id];   switch(opcode) {      case 0x50:      case 0x30:          MUESLIX_LOG(d,"channel %u disabled\n",channel_id);         channel->status = 0;         break;      case 0x00:         MUESLIX_LOG(d,"channel %u enabled\n",channel_id);         channel->status = 1;         break;      default:         MUESLIX_LOG(d,"unknown command 0x%5x\n",cmd);   }}/* * dev_mueslix_access() */void *dev_mueslix_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 mueslix_data *d = dev->priv_data;   struct mueslix_channel *channel;   m_uint32_t irq_status;   int i;#if DEBUG_ACCESS >= 2   if (op_type == MTS_READ) {      cpu_log(cpu,d->name,"read  access to offset=0x%x, pc=0x%llx, size=%u\n",              offset,cpu->pc,op_size);   } else {      cpu_log(cpu,d->name,"write access to offset=0x%x, pc=0x%llx, "              "val=0x%llx, size=%u\n",offset,cpu->pc,*data,op_size);   }#endif   /* Returns 0 if we don't know the offset */   if (op_type == MTS_READ)      *data = 0x00000000;   /* Handle microcode access */   if ((offset >= MUESLIX_UCODE_OFFSET) &&        (offset < (MUESLIX_UCODE_OFFSET + MUESLIX_UCODE_LEN)))      return(d->ucode + offset - MUESLIX_UCODE_OFFSET);   /* Handle TPU XMem access */   if ((offset >= MUESLIX_XMEM_OFFSET) &&        (offset < (MUESLIX_XMEM_OFFSET + MUESLIX_XYMEM_LEN)))      return(d->xmem + offset - MUESLIX_XMEM_OFFSET);     /* Handle TPU YMem access */   if ((offset >= MUESLIX_YMEM_OFFSET) &&        (offset < (MUESLIX_YMEM_OFFSET + MUESLIX_XYMEM_LEN)))      return(d->ymem + offset - MUESLIX_YMEM_OFFSET);     /* Handle channel access */   for(i=0;i<MUESLIX_NR_CHANNELS;i++)      if ((offset >= channel_offset[i]) &&           (offset < (channel_offset[i] + MUESLIX_CHANNEL_LEN)))   {      dev_mueslix_chan_access(cpu,&d->channel[i],                              offset - channel_offset[i],                              op_size,op_type,data);      return NULL;   }   /* Generic case */   switch(offset) {      /* this reg is accessed when an interrupt occurs */      case 0x0:         if (op_type == MTS_READ) {            irq_status = 0;            for(i=0;i<MUESLIX_NR_CHANNELS;i++) {               channel = &d->channel[i];               if ((dev_mueslix_is_rx_tx_enabled(d,i) & MUESLIX_TX_ENABLE) &&                   (channel->rx_tx_status & MUESLIX_CHANNEL_STATUS_RX))                  irq_status |= MUESLIX_RX_IRQ << i;               if ((dev_mueslix_is_rx_tx_enabled(d,i) & MUESLIX_TX_ENABLE) &&                   (channel->rx_tx_status & MUESLIX_CHANNEL_STATUS_TX))                  irq_status |= MUESLIX_TX_IRQ << i;            }            /*              * Hack: we re-trigger an interrupt here. This was necessary             * because the Mueslix driver was not working properly with             * a C3620 platform.             */            if (irq_status)               pci_dev_trigger_irq(d->vm,d->pci_dev);               *data = irq_status;         } else {            for(i=0;i<MUESLIX_NR_CHANNELS;i++) {               channel = &d->channel[i];               channel->rx_tx_status = 0;            }         }         break;      /* maybe interrupt mask */      case 0x10:         if (op_type == MTS_READ)            *data = 0x2FF;         break;      case 0x14:         if (op_type == MTS_READ)            *data = d->channel_enable_mask;         else {#if DEBUG_ACCESS            cpu_log(cpu,d->name,                    "channel_enable_mask = 0x%5.5llx at pc=0x%llx\n",                    *data,cpu->pc);#endif            d->channel_enable_mask = *data;         }         break;      case 0x18:         if (op_type == MTS_READ)            *data = 0x7F7F7F7F;         break;      case 0x48:         if (op_type == MTS_READ)            *data = 0x00000000;         break;      case 0x7c:         if (op_type == MTS_READ)            *data = 0x492;         break;      case 0x2c00:         if (op_type == MTS_READ)            *data = d->tpu_options;         else            d->tpu_options = *data;         break;      /* cmd reg */      case MUESLIX_TPU_CMD_OFFSET:#if DEBUG_ACCESS         if (op_type == MTS_WRITE) {            cpu_log(cpu,d->name,"cmd_reg = 0x%5.5llx at pc=0x%llx\n",                    *data,cpu->pc);         }#endif         switch(d->chip_mode) {            case 0:  /* 3600 */               tpu_cm0_handle_cmd(d,*data);               break;            case 1:  /* 7200 */               tpu_cm1_handle_cmd(d,*data);               break;         }         break;      /*        * cmd_rsp reg, it seems that 0xFFFF means OK       * (seen on a "sh contr se1/0" with "debug serial mueslix" enabled).       */      case MUESLIX_TPU_CMD_RSP_OFFSET:         if (op_type == MTS_READ)            *data = 0xFFFF;         break;#if DEBUG_UNKNOWN      default:         if (op_type == MTS_READ) {            cpu_log(cpu,d->name,                    "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",                    offset,cpu->pc,op_size);         } else {            cpu_log(cpu,d->name,                    "write to unknown addr 0x%x, value=0x%llx, "                    "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);         }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -