📄 dev_c7200_iofpga.c
字号:
/* * Cisco 7200 (Predator) simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * Cisco C7200 (Predator) I/O FPGA: * - Simulates a NMC93C46 Serial EEPROM as CPU and Midplane EEPROM. * - Simulates a DALLAS DS1620 for Temperature Sensors. * - Simulates voltage sensors. * - Simulates console and AUX ports. */#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 "mips64.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "dev_vtty.h"#include "nmc93c46.h"#include "ds1620.h"#include "dev_c7200.h"/* Debugging flags */#define DEBUG_UNKNOWN 1#define DEBUG_ACCESS 0#define DEBUG_LED 0#define DEBUG_IO_CTL 0#define DEBUG_ENVM 0/* DUART RX/TX status (SRA/SRB) */#define DUART_RX_READY 0x01#define DUART_TX_READY 0x04/* DUART RX/TX Interrupt Status/Mask */#define DUART_TXRDYA 0x01#define DUART_RXRDYA 0x02#define DUART_TXRDYB 0x10#define DUART_RXRDYB 0x20/* Definitions for CPU and Midplane Serial EEPROMs */#define DO2_DATA_OUT_MIDPLANE 7#define DO1_DATA_OUT_CPU 6#define CS2_CHIP_SEL_MIDPLANE 5#define SK2_CLOCK_MIDPLANE 4#define DI2_DATA_IN_MIDPLANE 3#define CS1_CHIP_SEL_CPU 2#define SK1_CLOCK_CPU 1#define DI1_DATA_IN_CPU 0/* Definitions for PEM (NPE-B) Serial EEPROM */#define DO1_DATA_OUT_PEM 3#define DI1_DATA_IN_PEM 2#define CS1_CHIP_SEL_PEM 1#define SK1_CLOCK_PEM 0/* Pack the NVRAM */#define NVRAM_PACKED 0x04/* 4 temperature sensors in a C7200 */#define C7200_TEMP_SENSORS 4#define C7200_DEFAULT_TEMP 22 /* default temperature: 22癈 *//* Voltages */#define C7200_A2D_SAMPLES 9/* * A2D MUX Select definitions. */#define C7200_MUX_PS0 0x00 /* Power Supply 0 */#define C7200_MUX_PS1 0x02 /* Power Supply 1 */#define C7200_MUX_P3V 0x04 /* +3V */#define C7200_MUX_P12V 0x08 /* +12V */#define C7200_MUX_P5V 0x0a /* +5V */#define C7200_MUX_N12V 0x0c /* -12V *//* Analog To Digital Converters samples */#define C7200_A2D_PS0 1150#define C7200_A2D_PS1 1150/* Voltage Samples */#define C7200_A2D_P3V 1150#define C7200_A2D_P12V 1150#define C7200_A2D_P5V 1150#define C7200_A2D_N12V 1150/* IO FPGA structure */struct iofpga_data { vm_obj_t vm_obj; struct vdevice dev; c7200_t *router; /* Lock test */ pthread_mutex_t lock; /* Periodic task to trigger dummy DUART IRQ */ ptask_id_t duart_irq_tid; /* DUART & Console Management */ u_int duart_isr,duart_imr,duart_irq_seq; /* IO control register */ u_int io_ctrl_reg; /* Temperature Control */ u_int temp_cfg_reg[C7200_TEMP_SENSORS]; u_int temp_deg_reg[C7200_TEMP_SENSORS]; u_int temp_clk_low; u_int temp_cmd; u_int temp_cmd_pos; u_int temp_data; u_int temp_data_pos; /* Voltages */ u_int mux;};#define IOFPGA_LOCK(d) pthread_mutex_lock(&(d)->lock)#define IOFPGA_UNLOCK(d) pthread_mutex_unlock(&(d)->lock)/* CPU EEPROM definition */static const struct nmc93c46_eeprom_def eeprom_cpu_def = { SK1_CLOCK_CPU, CS1_CHIP_SEL_CPU, DI1_DATA_IN_CPU, DO1_DATA_OUT_CPU,};/* Midplane EEPROM definition */static const struct nmc93c46_eeprom_def eeprom_midplane_def = { SK2_CLOCK_MIDPLANE, CS2_CHIP_SEL_MIDPLANE, DI2_DATA_IN_MIDPLANE, DO2_DATA_OUT_MIDPLANE,};/* PEM (NPE-B) EEPROM definition */static const struct nmc93c46_eeprom_def eeprom_pem_def = { SK1_CLOCK_PEM, CS1_CHIP_SEL_PEM, DI1_DATA_IN_PEM, DO1_DATA_OUT_PEM,};/* IOFPGA manages simultaneously CPU and Midplane EEPROM */static const struct nmc93c46_group eeprom_cpu_midplane = { 2, 0, "CPU and Midplane EEPROM", 0, { &eeprom_cpu_def, &eeprom_midplane_def }, };/* * IOFPGA manages also PEM EEPROM (for NPE-B) * PEM stands for "Power Entry Module": * http://www.cisco.com/en/US/products/hw/routers/ps341/products_field_notice09186a00801cb26d.shtml */static const struct nmc93c46_group eeprom_pem_npeb = { 1, 0, "PEM (NPE-B) EEPROM", 0, { &eeprom_pem_def },};/* Reset DS1620 */static void temp_reset(struct iofpga_data *d){ d->temp_cmd_pos = 0; d->temp_cmd = 0; d->temp_data_pos = 0; d->temp_data = 0;}/* Write the temperature control data */static void temp_write_ctrl(struct iofpga_data *d,u_char val){ switch(val) { case DS1620_RESET_ON: temp_reset(d); break; case DS1620_CLK_LOW: d->temp_clk_low = 1; break; case DS1620_CLK_HIGH: d->temp_clk_low = 0; break; }}/* Read a temperature control data */static u_int temp_read_data(struct iofpga_data *d){ u_int i,data = 0; switch(d->temp_cmd) { case DS1620_READ_CONFIG: for(i=0;i<C7200_TEMP_SENSORS;i++) data |= ((d->temp_cfg_reg[i] >> d->temp_data_pos) & 1) << i; d->temp_data_pos++; if (d->temp_data_pos == DS1620_CONFIG_READ_SIZE) temp_reset(d); break; case DS1620_READ_TEMP: for(i=0;i<C7200_TEMP_SENSORS;i++) data |= ((d->temp_deg_reg[i] >> d->temp_data_pos) & 1) << i; d->temp_data_pos++; if (d->temp_data_pos == DS1620_DATA_READ_SIZE) temp_reset(d); break; default: vm_log(d->router->vm,"IO_FPGA","temp_sensors: CMD = 0x%x\n", d->temp_cmd); } return(data);}/* Write the temperature data write register */static void temp_write_data(struct iofpga_data *d,u_char val){ if (val == DS1620_ENABLE_READ) { d->temp_data_pos = 0; return; } if (!d->temp_clk_low) return; /* Write a command */ if (d->temp_cmd_pos < DS1620_WRITE_SIZE) { if (val == DS1620_DATA_HIGH) d->temp_cmd |= 1 << d->temp_cmd_pos; d->temp_cmd_pos++; if (d->temp_cmd_pos == DS1620_WRITE_SIZE) { switch(d->temp_cmd) { case DS1620_START_CONVT: //printf("temp_sensors: IOS enabled continuous monitoring.\n"); temp_reset(d); break; case DS1620_READ_CONFIG: case DS1620_READ_TEMP: break; default: vm_log(d->router->vm,"IO_FPGA", "temp_sensors: IOS sent command 0x%x.\n", d->temp_cmd); } } } else { if (val == DS1620_DATA_HIGH) d->temp_data |= 1 << d->temp_data_pos; d->temp_data_pos++; }}/* Console port input */static void tty_con_input(vtty_t *vtty){ struct iofpga_data *d = vtty->priv_data; IOFPGA_LOCK(d); if (d->duart_imr & DUART_RXRDYA) { d->duart_isr |= DUART_RXRDYA; vm_set_irq(d->router->vm,C7200_DUART_IRQ); } IOFPGA_UNLOCK(d);}/* AUX port input */static void tty_aux_input(vtty_t *vtty){ struct iofpga_data *d = vtty->priv_data; IOFPGA_LOCK(d); if (d->duart_imr & DUART_RXRDYB) { d->duart_isr |= DUART_RXRDYB; vm_set_irq(d->router->vm,C7200_DUART_IRQ); } IOFPGA_UNLOCK(d);}/* IRQ trickery for Console and AUX ports */static int tty_trigger_dummy_irq(struct iofpga_data *d,void *arg){ u_int mask; IOFPGA_LOCK(d); d->duart_irq_seq++; if (d->duart_irq_seq == 2) { mask = DUART_TXRDYA|DUART_TXRDYB; if (d->duart_imr & mask) { d->duart_isr |= DUART_TXRDYA|DUART_TXRDYB; vm_set_irq(d->router->vm,C7200_DUART_IRQ); } d->duart_irq_seq = 0; } IOFPGA_UNLOCK(d); return(0);}/* * dev_c7200_iofpga_access() */void *dev_c7200_iofpga_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 iofpga_data *d = dev->priv_data; vm_instance_t *vm = d->router->vm; u_char odata; if (op_type == MTS_READ) *data = 0x0;#if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,"IO_FPGA","reading reg 0x%x at pc=0x%llx\n",offset,cpu->pc); } else { cpu_log(cpu,"IO_FPGA","writing reg 0x%x at pc=0x%llx, data=0x%llx\n", offset,cpu->pc,*data); }#endif IOFPGA_LOCK(d); switch(offset) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -