📄 dev_pa_a1.c
字号:
/* * Cisco C7200 (Predator) Simulation Platform. * Copyright (C) 2005,2006 Christophe Fillot. All rights reserved. * * PA-A1 ATM interface based on TI1570 and PLX 9060-ES. * * EEPROM types: * - 0x17: PA-A1-OC3MM * - 0x2C: PA-A1-OC3SM * - 0x2D: PA-A1-OC3UTP * * IOS command: "sh controller atm2/0" * * Manuals: * * Texas Instruments TNETA1570 ATM segmentation and reassembly device * with integrated 64-bit PCI-host interface * http://focus.ti.com/docs/prod/folders/print/tneta1570.html * * PLX 9060-ES * http://www.plxtech.com/products/io_accelerators/PCI9060/default.htm * * TODO: * - RX error handling and RX AAL5-related stuff * - HEC and AAL5 CRC fields. * * Cell trains for faster NETIO communications ? */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <errno.h>#include "crc.h"#include "atm.h"#include "mips64.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "ptask.h"#include "dev_c7200.h"/* Debugging flags */#define DEBUG_ACCESS 0#define DEBUG_UNKNOWN 0#define DEBUG_TRANSMIT 0#define DEBUG_RECEIVE 0#define DEBUG_TX_DMA 0/* PCI vendor/product codes */#define TI1570_PCI_VENDOR_ID 0x104c#define TI1570_PCI_PRODUCT_ID 0xa001#define PLX_9060ES_PCI_VENDOR_ID 0x10b5#define PLX_9060ES_PCI_PRODUCT_ID 0x906e/* Number of buffers transmitted at each TX DMA ring scan pass */#define TI1570_TXDMA_PASS_COUNT 16/* TI1570 Internal Registers (p.58 of doc) */#define TI1570_REG_CONFIG 0x0000 /* Configuration registers */#define TI1570_REG_STATUS 0x0001 /* Status register */#define TI1570_REG_IMASK 0x0002 /* Interrupt-mask register */#define TI1570_REG_RGT_RAT 0x0003 /* RGT + RAT cycle-counter */#define TI1570_REG_RX_UNKNOWN 0x0004 /* RX Unknown Register */#define TI1570_REG_TX_CRING_SIZE 0x0005 /* TX Completion ring sizes */#define TI1570_REG_RX_CRING_SIZE 0x0006 /* RX Completion ring sizes */#define TI1570_REG_TX_PSR_SIZE 0x0007 /* TX Pkt-seg ring size + FIFO */#define TI1570_REG_HEC_AAL5_DISC 0x0008 /* HEC err + AAL5 CPCS discard */#define TI1570_REG_UNK_PROTO_CNT 0x0009 /* Unknown-protocols counter */#define TI1570_REG_RX_ATM_COUNT 0x000A /* ATM-cells-received counter */#define TI1570_REG_TX_ATM_COUNT 0x000B /* ATM-cells-tranmitted counter */#define TI1570_REG_TX_RX_FIFO 0x000C /* TX/RX FIFO occupancy, VCI mask */#define TI1570_REG_SCHED_SIZE 0x000D /* Scheduler Table size */#define TI1570_REG_SOFT_RESET 0x000E /* Software Reset */#define TI1570_REG_TCR_WOI_ADDR 0x0080 /* TX Compl. Ring w/o IRQ addr. */#define TI1570_REG_TCR_WI_ADDR 0x0081 /* TX Compl. Ring w/ IRQ addr. */#define TI1570_REG_RCR_WOI_ADDR 0x0082 /* RX Compl. Ring w/o IRQ addr. */#define TI1570_REG_RCR_WI_ADDR 0x0083 /* RX Compl. Ring w/ IRQ addr. *//* TI1570 configuration register (p.59) */#define TI1570_CFG_EN_RAT 0x00000001 /* Reassembly Aging */#define TI1570_CFG_BP_SEL 0x00000002 /* IRQ on packet or buffer */#define TI1570_CFG_EN_RX 0x00000010 /* RX enable */#define TI1570_CFG_EN_TX 0x00000020 /* TX enable */#define TI1570_CFG_SMALL_MAP 0x00000040 /* Small map *//* TI1570 status register (p.61) */#define TI1570_STAT_CP_TX 0x00000001 /* Transmit completion ring */#define TI1570_STAT_RX_IRR 0x00000040 /* Receive unknown reg set */#define TI1570_STAT_CP_RX 0x00000080 /* Receive completion ring */#define TI1570_STAT_TX_FRZ 0x00000100 /* TX Freeze */#define TI1570_STAT_RX_FRZ 0x00000200 /* RX Freeze *//* Mask for RX/TX completion-ring sizes */#define TI1570_TCR_SIZE_MASK 0x00001FFF /* TX compl. ring size mask */#define TI1570_RCR_SIZE_MASK 0x000003FF /* RX compl. ring size mask *//* TI1750 TX packet segmentation ring register */#define TI1570_PSR_SIZE_MASK 0x000000FF /* pkt-seg ring size *//* Total size of the TI1570 Control Memory */#define TI1570_CTRL_MEM_SIZE 0x100000/* Offsets of the TI1570 structures (p.66) */#define TI1570_TX_SCHED_OFFSET 0x0000 /* TX scheduler table */#define TI1570_INTERNAL_REGS_OFFSET 0x3200 /* Internal Registers */#define TI1570_FREE_BUFFERS_OFFSET 0x3800 /* Free-Buffer Pointers */#define TI1570_RX_DMA_PTR_TABLE_OFFSET 0x4000 /* RX VPI/VCI pointer table */#define TI1570_TX_DMA_TABLE_OFFSET 0x8000 /* TX DMA state table */#define TI1570_RX_DMA_TABLE_OFFSET 0x10000 /* RX DMA state table *//* TX scheduler table */#define TI1570_TX_SCHED_ENTRY_COUNT 6200#define TI1570_TX_SCHED_ENTRY_MASK 0x3FF /* Entry mask */#define TI1570_TX_SCHED_E0_SHIFT 0 /* Shift for entry 0 */#define TI1570_TX_SCHED_E1_SHIFT 16 /* Shift for entry 0 *//* TX DMA state table */#define TI1570_TX_DMA_ACT 0x80000000 /* ACTive (word 0) */#define TI1570_TX_DMA_SOP 0x40000000 /* Start of Packet (SOP) */#define TI1570_TX_DMA_EOP 0x20000000 /* End of Packet (EOP) */#define TI1570_TX_DMA_ABORT 0x10000000 /* Abort */#define TI1570_TX_DMA_TCR_SELECT 0x02000000 /* TX comp. ring selection */#define TI1570_TX_DMA_AAL_TYPE_MASK 0x0C000000 /* AAL-type mask */#define TI1570_TX_DMA_AAL_TRWPTI 0x00000000 /* Transp. AAL w/ PTI set */#define TI1570_TX_DMA_AAL_AAL5 0x04000000 /* AAL5 */#define TI1570_TX_DMA_AAL_TRWOPTI 0x08000000 /* Transp. AAL w/o PTI set */#define TI1570_TX_DMA_OFFSET_MASK 0x00FF0000#define TI1570_TX_DMA_OFFSET_SHIFT 16#define TI1570_TX_DMA_DCOUNT_MASK 0x0000FFFF#define TI1570_TX_DMA_ON 0x80000000 /* DMA state (word 3) */#define TI1570_TX_DMA_RING_OFFSET_MASK 0x3FFFFF00#define TI1570_TX_DMA_RING_OFFSET_SHIFT 8#define TI1570_TX_DMA_RING_INDEX_MASK 0x000000FF#define TI1570_TX_DMA_RING_AAL5_LEN_MASK 0x0000FFFFtypedef struct ti1570_tx_dma_entry ti1570_tx_dma_entry_t;struct ti1570_tx_dma_entry { m_uint32_t ctrl_buf; /* Ctrl, Buffer Offset, Buffer data-byte count */ m_uint32_t cb_addr; /* Current Buffer Address */ m_uint32_t atm_hdr; /* 4-byte ATM header */ m_uint32_t dma_state; /* DMA state + Packet segmentation ring address */ m_uint32_t nb_addr; /* Next Buffer address */ m_uint32_t sb_addr; /* Start of Buffer address */ m_uint32_t aal5_crc; /* Partial AAL5-transmit CRC */ m_uint32_t aal5_ctrl; /* AAL5-control field and length field */};/* TX Packet-Segmentation Rings */#define TI1570_TX_RING_OWN 0x80000000 /* If set, packet is ready */#define TI1570_TX_RING_PTR_MASK 0x3FFFFFFF /* Buffer pointer *//* TX Data Buffers */#define TI1570_TX_BUFFER_RDY 0x80000000 /* If set, buffer is ready */#define TI1570_TX_BUFFER_SOP 0x40000000 /* First buffer of packet */#define TI1570_TX_BUFFER_EOP 0x20000000 /* Last buffer of packet */#define TI1570_TX_BUFFER_ABORT 0x10000000 /* Abort */#define TI1570_TX_BUFFER_OFFSET_MASK 0x00FF0000#define TI1570_TX_BUFFER_OFFSET_SHIFT 16#define TI1570_TX_BUFFER_DCOUNT_MASK 0x0000FFFFtypedef struct ti1570_tx_buffer ti1570_tx_buffer_t;struct ti1570_tx_buffer { m_uint32_t ctrl_buf; /* Ctrl, Buffer offset, Buffer data-byte count */ m_uint32_t nb_addr; /* Start-of-next buffer pointer */ m_uint32_t atm_hdr; /* 4-byte ATM header */ m_uint32_t aal5_ctrl; /* PCS-UU/CPI field (AAL5 control field) */};/* TX completion-ring */#define TI1570_TCR_OWN 0x80000000 /* OWNner bit */#define TI1570_TCR_ABORT 0x40000000 /* Abort *//* RX VPI/VCI DMA pointer table */#define TI1570_RX_VPI_ENABLE 0x80000000 /* VPI enabled ? */#define TI1570_RX_BASE_PTR_MASK 0x7FFF0000 /* Base pointer mask */#define TI1570_RX_BASE_PTR_SHIFT 16 /* Base pointer shift */#define TI1570_RX_VCI_RANGE_MASK 0x0000FFFF /* Valid VCI range *//* RX DMA state table (p.36) */#define TI1570_RX_DMA_ACT 0x80000000 /* ACTive (word 0) */#define TI1570_RX_DMA_RCR_SELECT 0x20000000 /* RX comp. ring selection */#define TI1570_RX_DMA_WAIT_EOP 0x10000000 /* Wait for EOP */#define TI1570_RX_DMA_AAL_TYPE_MASK 0x0C000000 /* AAL-type mask */#define TI1570_RX_DMA_AAL_PTI 0x00000000 /* PTI based tr. AAL pkt */#define TI1570_RX_DMA_AAL_AAL5 0x04000000 /* AAL5 */#define TI1570_RX_DMA_AAL_CNT 0x08000000 /* Cnt based tr. AAL pkt */#define TI1570_RX_DMA_FIFO 0x02000000 /* FIFO used for free bufs */#define TI1570_RX_DMA_TR_CNT_MASK 0xFFFF0000 /* Cnt-based Tr-AAL */#define TI1570_RX_DMA_TR_CNT_SHIFT 16#define TI1570_RX_DMA_CB_LEN_MASK 0x0000FFFF /* Current buffer length */#define TI1570_RX_DMA_ON 0x80000000 /* DMA state (word 6) */#define TI1570_RX_DMA_FILTER 0x40000000 /* Filter */#define TI1570_RX_DMA_FB_PTR_MASK 0x3FFFFFFF /* Free-buffer ptr mask */#define TI1570_RX_DMA_FB_INDEX_MASK 0x000000FF /* Index with Free-buf ring */typedef struct ti1570_rx_dma_entry ti1570_rx_dma_entry_t;struct ti1570_rx_dma_entry { m_uint32_t ctrl; /* Control field, EFCN cell cnt, pkt length */ m_uint32_t cb_addr; /* Current Buffer Address */ m_uint32_t sb_addr; /* Start of Buffer address */ m_uint32_t cb_len; /* Transp-AAL pkt counter, current buf length */ m_uint32_t sp_ptr; /* Start-of-packet pointer */ m_uint32_t aal5_crc; /* Partial AAL5-receive CRC */ m_uint32_t fbr_entry; /* Free-buffer ring-pointer table entry */ m_uint32_t timeout; /* Timeout value, current timeout count */};/* RX free-buffer ring pointer table entry (p.39) */#define TI1570_RX_FBR_PTR_MASK 0xFFFFFFFC#define TI1570_RX_FBR_BS_MASK 0xFFFF0000 /* Buffer size mask */#define TI1570_RX_FBR_BS_SHIFT 16#define TI1570_RX_FBR_RS_MASK 0x0000FC00 /* Ring size mask */#define TI1570_RX_FBR_RS_SHIFT 10#define TI1570_RX_FBR_IDX_MASK 0x000003FF /* Current index mask */typedef struct ti1570_rx_fbr_entry ti1570_rx_fbr_entry_t;struct ti1570_rx_fbr_entry { m_uint32_t fbr_ptr; /* RX free-buffer ring pointer */ m_uint32_t ring_size; /* Ring size and buffer size */};/* RX buffer pointer (p.41) */#define TI1570_RX_BUFPTR_OWN 0x80000000 /* If set, buffer is ready */#define TI1570_RX_BUFPTR_MASK 0x3FFFFFFF /* Buffer address mask *//* RX data buffer (p.42) */#define TI1570_RX_BUFFER_SOP 0x80000000 /* Start-of-Packet buffer */#define TI1570_RX_BUFFER_EOP 0x40000000 /* End-of-Packet buffer */typedef struct ti1570_rx_buffer ti1570_rx_buffer_t;struct ti1570_rx_buffer { m_uint32_t reserved; /* Reserved, not used by the TI1570 */ m_uint32_t ctrl; /* Control field, Start of next buffer pointer */ m_uint32_t atm_hdr; /* ATM header */ m_uint32_t user; /* User-defined value */};/* Internal structure to hold free buffer info */typedef struct ti1570_rx_buf_holder ti1570_rx_buf_holder_t;struct ti1570_rx_buf_holder { m_uint32_t buf_addr; m_uint32_t buf_size; ti1570_rx_buffer_t rx_buf;};/* RX completion ring entry */#define TI1570_RCR_PKT_OVFLW 0x80000000 /* Packet overflow (word 0) */#define TI1570_RCR_CRC_ERROR 0x40000000 /* CRC error */#define TI1570_RCR_BUF_STARV 0x20000000 /* Buffer starvation */#define TI1570_RCR_TIMEOUT 0x10000000 /* Reassembly timeout */#define TI1570_RCR_ABORT 0x08000000 /* Abort condition */#define TI1570_RCR_AAL5 0x04000000 /* AAL5 indicator */#define TI1570_RCR_VALID 0x80000000 /* Start-ptr valid (word 2) */#define TI1570_RCR_OWN 0x80000000 /* Buffer ready (word 4) */#define TI1570_RCR_ERROR 0x40000000 /* Error entry */typedef struct ti1570_rcr_entry ti1570_rcr_entry_t;struct ti1570_rcr_entry { m_uint32_t atm_hdr; /* ATM header */ m_uint32_t error; /* Error Indicator + Congestion cell count */ m_uint32_t sp_addr; /* Start of packet */ m_uint32_t aal5_trailer; /* AAL5 trailer */ m_uint32_t fbr_entry; /* Free-buffer ring-pointer table entry */ m_uint32_t res[3]; /* Reserved, not used by the TI1570 */};/* TI1570 Data */struct pa_a1_data { char *name; /* Control Memory pointer */ m_uint32_t *ctrl_mem_ptr; /* TI1570 internal registers */ m_uint32_t *iregs; /* TX FIFO cell */ m_uint8_t txfifo_cell[ATM_CELL_SIZE]; m_uint32_t txfifo_avail,txfifo_pos; /* TX Scheduler table */ m_uint32_t *tx_sched_table; /* TX DMA state table */ ti1570_tx_dma_entry_t *tx_dma_table; /* TX/RX completion ring current position */ m_uint32_t tcr_wi_pos,tcr_woi_pos; m_uint32_t rcr_wi_pos,rcr_woi_pos; /* RX VPI/VCI DMA pointer table */ m_uint32_t *rx_vpi_vci_dma_table; /* RX DMA state table */ ti1570_rx_dma_entry_t *rx_dma_table; /* RX Free-buffer ring pointer table */ ti1570_rx_fbr_entry_t *rx_fbr_table; /* Virtual device */ struct vdevice *dev; /* PCI device information */ struct pci_device *pci_dev_ti,*pci_dev_plx; /* Virtual machine */ vm_instance_t *vm; /* NetIO descriptor */ netio_desc_t *nio; /* TX ring scanner task id */ ptask_id_t tx_tid;};/* Log a TI1570 message */#define TI1570_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)/* Reset the TI1570 (forward declaration) */static void ti1570_reset(struct pa_a1_data *d,int clear_ctrl_mem);/* * dev_pa_a1_access() */void *dev_pa_a1_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 pa_a1_data *d = dev->priv_data; if (op_type == MTS_READ) *data = 0;#if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,"TI1570","read access to offset = 0x%x, pc = 0x%llx\n", offset,cpu->pc); } else { cpu_log(cpu,"TI1570","write access to vaddr = 0x%x, pc = 0x%llx, " "val = 0x%llx\n",offset,cpu->pc,*data); }#endif /* Specific cases */ switch(offset) { case 0x3238: TI1570_LOG(d,"reset issued.\n"); ti1570_reset(d,FALSE); break; case 0x18000c: if (op_type == MTS_READ) { *data = 0xa6; return NULL; } break; } /* Control Memory access */ if (offset < TI1570_CTRL_MEM_SIZE) { if (op_type == MTS_READ) *data = d->ctrl_mem_ptr[offset >> 2]; else d->ctrl_mem_ptr[offset >> 2] = *data; return NULL; } /* Unknown offset */#if DEBUG_UNKNOWN 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;}/* Fetch a TX data buffer from host memory */static void ti1570_read_tx_buffer(struct pa_a1_data *d,m_uint32_t addr, ti1570_tx_buffer_t *tx_buf){ physmem_copy_from_vm(d->vm,tx_buf,addr,sizeof(ti1570_tx_buffer_t)); /* byte-swapping */ tx_buf->ctrl_buf = vmtoh32(tx_buf->ctrl_buf); tx_buf->nb_addr = vmtoh32(tx_buf->nb_addr); tx_buf->atm_hdr = vmtoh32(tx_buf->atm_hdr); tx_buf->aal5_ctrl = vmtoh32(tx_buf->aal5_ctrl);}/* Acquire a TX buffer */static int ti1570_acquire_tx_buffer(struct pa_a1_data *d, ti1570_tx_dma_entry_t *tde, m_uint32_t buf_addr){ ti1570_tx_buffer_t tx_buf; m_uint32_t buf_offset;#if DEBUG_TRANSMIT TI1570_LOG(d,"ti1570_acquire_tx_buffer: acquiring buffer at address 0x%x\n", buf_addr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -