📄 dev_c7200_pos.c
字号:
/* * Cisco C7200 (Predator) Simulation Platform. * Copyright (C) 2005-2006 Christophe Fillot. All rights reserved. * * EEPROM types: * - 0x95: PA-POS-OC3SMI * - 0x96: PA-POS-OC3MM * * Just an experimentation (I don't have any PA-POS-OC3). It basically works, * on NPE-400. There is something strange with the buffer addresses in TX ring, * preventing this driver working with platforms using SRAM. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include <pthread.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_c7200.h"#include "dev_plx.h"/* Debugging flags */#define DEBUG_ACCESS 0#define DEBUG_UNKNOWN 1#define DEBUG_TRANSMIT 0#define DEBUG_RECEIVE 0/* PCI vendor/product codes */#define POS_OC3_PCI_VENDOR_ID 0x10b5#define POS_OC3_PCI_PRODUCT_ID 0x9060/* Maximum packet size */#define POS_OC3_MAX_PKT_SIZE 8192/* RX descriptors */#define POS_OC3_RXDESC_OWN 0x80000000 /* Ownership */#define POS_OC3_RXDESC_WRAP 0x40000000 /* Wrap ring */#define POS_OC3_RXDESC_CONT 0x08000000 /* Packet continues */#define POS_OC3_RXDESC_LEN_MASK 0x1fff/* TX descriptors */#define POS_OC3_TXDESC_OWN 0x80000000 /* Ownership */#define POS_OC3_TXDESC_WRAP 0x40000000 /* Wrap ring */#define POS_OC3_TXDESC_CONT 0x08000000 /* Packet continues */#define POS_OC3_TXDESC_LEN_MASK 0x1fff#define POS_OC3_TXDESC_ADDR_MASK 0x3fffffff /* Buffer address (?) *//* RX Descriptor */struct rx_desc { m_uint32_t rdes[2];};/* TX Descriptor */struct tx_desc { m_uint32_t tdes[2];};/* PA-POS-OC3 Data */struct pos_oc3_data { char *name; /* 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; /* Virtual machine */ vm_instance_t *vm; /* Virtual devices */ char *rx_name,*tx_name,*cs_name; vm_obj_t *rx_obj,*tx_obj,*cs_obj; struct vdevice rx_dev,tx_dev,cs_dev; /* PCI device information */ struct vdevice dev; struct pci_device *pci_dev; /* NetIO descriptor */ netio_desc_t *nio; /* TX ring scanner task id */ ptask_id_t tx_tid;};/* Log a PA-POS-OC3 message */#define POS_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)/* * pos_access() */static void *dev_pos_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 pos_oc3_data *d = dev->priv_data; if (op_type == MTS_READ) *data = 0;#if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx\n", offset,cpu->pc); } else { if (offset != 0x404) cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, " "val = 0x%llx\n",offset,cpu->pc,*data); }#endif switch(offset) { case 0x404: if (op_type == MTS_READ) *data = 0xFFFFFFFF; break; case 0x406: if (op_type == MTS_READ) *data = 0xFFFFFFFF; break; case 0x407: if (op_type == MTS_READ) *data = 0xFFFFFFFF; 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); }#endif } return NULL;}/* * pos_rx_access() */static void *dev_pos_rx_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 pos_oc3_data *d = dev->priv_data; if (op_type == MTS_READ) *data = 0;#if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx\n", offset,cpu->pc); } else { cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, " "val = 0x%llx\n",offset,cpu->pc,*data); }#endif switch(offset) { case 0x04: if (op_type == MTS_READ) *data = d->rx_start; else d->rx_start = *data; break; case 0x08: if (op_type == MTS_READ) *data = d->rx_current; else d->rx_current = *data; break;#if DEBUG_UNKNOWN default: if (op_type == MTS_READ) { cpu_log(cpu,d->rx_name, "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", offset,cpu->pc,op_size); } else { cpu_log(cpu,d->rx_name, "write to unknown addr 0x%x, value=0x%llx, " "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); }#endif } return NULL;}/* * pos_tx_access() */static void *dev_pos_tx_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 pos_oc3_data *d = dev->priv_data; if (op_type == MTS_READ) *data = 0;#if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,d->tx_name,"read access to offset = 0x%x, pc = 0x%llx\n", offset,cpu->pc); } else { cpu_log(cpu,d->tx_name,"write access to vaddr = 0x%x, pc = 0x%llx, " "val = 0x%llx\n",offset,cpu->pc,*data); }#endif switch(offset) { case 0x04: if (op_type == MTS_READ) *data = d->tx_start; else d->tx_start = *data; break; case 0x08: if (op_type == MTS_READ) *data = d->tx_current; else d->tx_current = *data; break;#if DEBUG_UNKNOWN default: if (op_type == MTS_READ) { cpu_log(cpu,d->tx_name, "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", offset,cpu->pc,op_size); } else { cpu_log(cpu,d->tx_name, "write to unknown addr 0x%x, value=0x%llx, " "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); }#endif } return NULL;}/* * pos_cs_access() */static void *dev_pos_cs_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 pos_oc3_data *d = dev->priv_data; if (op_type == MTS_READ) *data = 0;#if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,d->cs_name,"read access to offset = 0x%x, pc = 0x%llx\n", offset,cpu->pc); } else { cpu_log(cpu,d->cs_name,"write access to vaddr = 0x%x, pc = 0x%llx, " "val = 0x%llx\n",offset,cpu->pc,*data); }#endif switch(offset) { case 0x300000: case 0x300004: case 0x30001c: if (op_type == MTS_READ) *data = 0x00000FFF; break; case 0x300008: if (op_type == MTS_READ) *data = 0x000007F; break;#if DEBUG_UNKNOWN default: if (op_type == MTS_READ) { cpu_log(cpu,d->cs_name, "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", offset,cpu->pc,op_size); } else { cpu_log(cpu,d->cs_name, "write to unknown addr 0x%x, value=0x%llx, " "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); }#endif } return NULL;}/* * Get the address of the next RX descriptor. */static m_uint32_t rxdesc_get_next(struct pos_oc3_data *d,m_uint32_t rxd_addr, struct rx_desc *rxd){ m_uint32_t nrxd_addr; if (rxd->rdes[0] & POS_OC3_RXDESC_WRAP) nrxd_addr = d->rx_start; else nrxd_addr = rxd_addr + sizeof(struct rx_desc); return(nrxd_addr);}/* Read an RX descriptor */static void rxdesc_read(struct pos_oc3_data *d,m_uint32_t rxd_addr, struct rx_desc *rxd){#if DEBUG_RECEIVE POS_LOG(d,"reading RX descriptor at address 0x%x\n",rxd_addr);#endif /* get the next descriptor from VM physical RAM */ physmem_copy_from_vm(d->vm,rxd,rxd_addr,sizeof(struct rx_desc)); /* byte-swapping */ rxd->rdes[0] = vmtoh32(rxd->rdes[0]); rxd->rdes[1] = vmtoh32(rxd->rdes[1]);}/* * Try to acquire the specified RX descriptor. Returns TRUE if we have it. * It assumes that the byte-swapping is done. */static inline int rxdesc_acquire(m_uint32_t rdes0){ return(rdes0 & POS_OC3_RXDESC_OWN);}/* Put a packet in buffer of a descriptor */static ssize_t rxdesc_put_pkt(struct pos_oc3_data *d,struct rx_desc *rxd, u_char **pkt,ssize_t *pkt_len){ ssize_t len,cp_len; len = rxd->rdes[0] & POS_OC3_RXDESC_LEN_MASK; /* compute the data length to copy */ cp_len = m_min(len,*pkt_len);#if DEBUG_RECEIVE POS_LOG(d,"copying %d bytes at 0x%x\n",cp_len,rxd->rdes[1]);#endif /* copy packet data to the VM physical RAM */ physmem_copy_to_vm(d->vm,*pkt,rxd->rdes[1],cp_len); *pkt += cp_len; *pkt_len -= cp_len; return(cp_len);}/* * Put a packet in the RX ring. */static void dev_pos_oc3_receive_pkt(struct pos_oc3_data *d, u_char *pkt,ssize_t pkt_len){ m_uint32_t rx_start,rxdn_addr,rxdn_rdes0; struct rx_desc rxd0,rxdn,*rxdc; ssize_t cp_len,tot_len = pkt_len; u_char *pkt_ptr = pkt;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -