📄 dev_gt.c
字号:
/* * Cisco 7200 (Predator) simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * Galileo GT64010/GT64120A/GT96100A system controller. * * The DMA stuff is not complete, only "normal" transfers are working * (source and destination addresses incrementing). * * Also, these transfers are "instantaneous" from a CPU point-of-view: when * a channel is enabled, the transfer is immediately done. So, this is not * very realistic. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "utils.h"#include "net.h"#include "mips64.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "net_io.h"#include "ptask.h"#include "dev_gt.h"/* Debugging flags */#define DEBUG_UNKNOWN 0#define DEBUG_DMA 0#define DEBUG_MII 0#define DEBUG_ETH_TX 0#define DEBUG_ETH_RX 0#define DEBUG_ETH_HASH 0/* PCI identification */#define PCI_VENDOR_GALILEO 0x11ab /* Galileo Technology */#define PCI_PRODUCT_GALILEO_GT64010 0x0146 /* GT-64010 */#define PCI_PRODUCT_GALILEO_GT64011 0x4146 /* GT-64011 */#define PCI_PRODUCT_GALILEO_GT64120 0x4620 /* GT-64120 */#define PCI_PRODUCT_GALILEO_GT96100 0x9653 /* GT-96100 *//* === Global definitions === *//* Interrupt High Cause Register */#define GT_IHCR_ETH0_SUM 0x00000001#define GT_IHCR_ETH1_SUM 0x00000002#define GT_IHCR_SDMA_SUM 0x00000010/* Serial Cause Register */#define GT_SCR_ETH0_SUM 0x00000001#define GT_SCR_ETH1_SUM 0x00000002#define GT_SCR_SDMA_SUM 0x00000010/* === DMA definitions === */#define GT_DMA_CHANNELS 4#define GT_DMA_FLYBY_ENABLE 0x00000001 /* FlyBy Enable */ #define GT_DMA_FLYBY_RDWR 0x00000002 /* SDRAM Read/Write (FlyBy) */#define GT_DMA_SRC_DIR 0x0000000c /* Source Direction */#define GT_DMA_DST_DIR 0x00000030 /* Destination Direction */#define GT_DMA_DATA_LIMIT 0x000001c0 /* Data Transfer Limit */#define GT_DMA_CHAIN_MODE 0x00000200 /* Chained Mode */#define GT_DMA_INT_MODE 0x00000400 /* Interrupt Mode */#define GT_DMA_TRANS_MODE 0x00000800 /* Transfer Mode */#define GT_DMA_CHAN_ENABLE 0x00001000 /* Channel Enable */#define GT_DMA_FETCH_NEXT 0x00002000 /* Fetch Next Record */#define GT_DMA_ACT_STATUS 0x00004000 /* DMA Activity Status */#define GT_DMA_SDA 0x00008000 /* Source/Destination Alignment */#define GT_DMA_MDREQ 0x00010000 /* Mask DMA Requests */#define GT_DMA_CDE 0x00020000 /* Close Descriptor Enable */#define GT_DMA_EOTE 0x00040000 /* End-of-Transfer (EOT) Enable */#define GT_DMA_EOTIE 0x00080000 /* EOT Interrupt Enable */#define GT_DMA_ABORT 0x00100000 /* Abort DMA Transfer */#define GT_DMA_SLP 0x00600000 /* Override Source Address */#define GT_DMA_DLP 0x01800000 /* Override Dest Address */#define GT_DMA_RLP 0x06000000 /* Override Record Address */#define GT_DMA_REQ_SRC 0x10000000 /* DMA Request Source *//* Galileo DMA channel */struct dma_channel { m_uint32_t byte_count; m_uint32_t src_addr; m_uint32_t dst_addr; m_uint32_t cdptr; m_uint32_t nrptr; m_uint32_t ctrl;};/* === Ethernet definitions === */#define GT_ETH_PORTS 2#define GT_MAX_PKT_SIZE 2048/* SMI register */#define GT_SMIR_DATA_MASK 0x0000FFFF#define GT_SMIR_PHYAD_MASK 0x001F0000 /* PHY Device Address */#define GT_SMIR_PHYAD_SHIFT 16#define GT_SMIR_REGAD_MASK 0x03e00000 /* PHY Device Register Address */#define GT_SMIR_REGAD_SHIFT 21#define GT_SMIR_OPCODE_MASK 0x04000000 /* Opcode (0: write, 1: read) */#define GT_SMIR_OPCODE_READ 0x04000000#define GT_SMIR_RVALID_FLAG 0x08000000 /* Read Valid */#define GT_SMIR_BUSY_FLAG 0x10000000 /* Busy: 1=op in progress *//* PCR: Port Configuration Register */#define GT_PCR_PM 0x00000001 /* Promiscuous mode */#define GT_PCR_RBM 0x00000002 /* Reject broadcast mode */#define GT_PCR_PBF 0x00000004 /* Pass bad frames */#define GT_PCR_EN 0x00000080 /* Port Enabled/Disabled */#define GT_PCR_LPBK 0x00000300 /* Loopback mode */#define GT_PCR_FC 0x00000400 /* Force collision */#define GT_PCR_HS 0x00001000 /* Hash size */#define GT_PCR_HM 0x00002000 /* Hash mode */#define GT_PCR_HDM 0x00004000 /* Hash default mode */#define GT_PCR_HD 0x00008000 /* Duplex Mode */#define GT_PCR_ISL 0x70000000 /* ISL enabled (0x06) */#define GT_PCR_ACCS 0x80000000 /* Accelerate Slot Time *//* PCXR: Port Configuration Extend Register */#define GT_PCXR_IGMP 0x00000001 /* IGMP packet capture */#define GT_PCXR_SPAN 0x00000002 /* BPDU packet capture */#define GT_PCXR_PAR 0x00000004 /* Partition Enable */#define GT_PCXR_PRIOTX 0x00000038 /* Priority weight for TX */#define GT_PCXR_PRIORX 0x000000C0 /* Priority weight for RX */#define GT_PCXR_PRIORX_OV 0x00000100 /* Prio RX override */#define GT_PCXR_DPLX_EN 0x00000200 /* Autoneg for Duplex */#define GT_PCXR_FCTL_EN 0x00000400 /* Autoneg for 802.3x */#define GT_PCXR_FLP 0x00000800 /* Force Link Pass */#define GT_PCXR_FCTL 0x00001000 /* Flow Control Mode */#define GT_PCXR_MFL 0x0000C000 /* Maximum Frame Length */#define GT_PCXR_MIB_CLR_MODE 0x00010000 /* MIB counters clear mode */#define GT_PCXR_SPEED 0x00040000 /* Port Speed */#define GT_PCXR_SPEED_EN 0x00080000 /* Autoneg for Speed */#define GT_PCXR_RMII_EN 0x00100000 /* RMII Enable */#define GT_PCXR_DSCP_EN 0x00200000 /* DSCP decoding enable *//* PCMR: Port Command Register */#define GT_PCMR_FJ 0x00008000 /* Force Jam / Flow Control *//* PSR: Port Status Register */#define GT_PSR_SPEED 0x00000001 /* Speed: 10/100 Mb/s (100=>1)*/#define GT_PSR_DUPLEX 0x00000002 /* Duplex (1: full) */#define GT_PSR_FCTL 0x00000004 /* Flow Control Mode */#define GT_PSR_LINK 0x00000008 /* Link Up/Down */#define GT_PSR_PAUSE 0x00000010 /* Flow-control disabled state */#define GT_PSR_TXLOW 0x00000020 /* TX Low priority status */#define GT_PSR_TXHIGH 0x00000040 /* TX High priority status */#define GT_PSR_TXINP 0x00000080 /* TX in Progress *//* SDCR: SDMA Configuration Register */#define GT_SDCR_RC 0x0000003c /* Retransmit count */#define GT_SDCR_BLMR 0x00000040 /* Big/Little Endian RX mode */#define GT_SDCR_BLMT 0x00000080 /* Big/Litlle Endian TX mode */#define GT_SDCR_POVR 0x00000100 /* PCI override */#define GT_SDCR_RIFB 0x00000200 /* RX IRQ on frame boundary */#define GT_SDCR_BSZ 0x00003000 /* Burst size *//* SDCMR: SDMA Command Register */#define GT_SDCMR_ERD 0x00000080 /* Enable RX DMA */#define GT_SDCMR_AR 0x00008000 /* Abort Receive */#define GT_SDCMR_STDH 0x00010000 /* Stop TX High */#define GT_SDCMR_STDL 0x00020000 /* Stop TX Low */#define GT_SDCMR_TXDH 0x00800000 /* Start TX High */#define GT_SDCMR_TXDL 0x01000000 /* Start TX Low */#define GT_SDCMR_AT 0x80000000 /* Abort Transmit *//* ICR: Interrupt Cause Register */#define GT_ICR_RXBUF 0x00000001 /* RX Buffer returned to host */#define GT_ICR_TXBUFH 0x00000004 /* TX Buffer High */#define GT_ICR_TXBUFL 0x00000008 /* TX Buffer Low */#define GT_ICR_TXENDH 0x00000040 /* TX End High */#define GT_ICR_TXENDL 0x00000080 /* TX End Low */#define GT_ICR_RXERR 0x00000100 /* RX Error */#define GT_ICR_TXERRH 0x00000400 /* TX Error High */#define GT_ICR_TXERRL 0x00000800 /* TX Error Low */#define GT_ICR_RXOVR 0x00001000 /* RX Overrun */#define GT_ICR_TXUDR 0x00002000 /* TX Underrun */#define GT_ICR_RXBUFQ0 0x00010000 /* RX Buffer in Prio Queue 0 */#define GT_ICR_RXBUFQ1 0x00020000 /* RX Buffer in Prio Queue 1 */#define GT_ICR_RXBUFQ2 0x00040000 /* RX Buffer in Prio Queue 2 */#define GT_ICR_RXBUFQ3 0x00080000 /* RX Buffer in Prio Queue 3 */#define GT_ICR_RXERRQ0 0x00010000 /* RX Error in Prio Queue 0 */#define GT_ICR_RXERRQ1 0x00020000 /* RX Error in Prio Queue 1 */#define GT_ICR_RXERRQ2 0x00040000 /* RX Error in Prio Queue 2 */#define GT_ICR_RXERRQ3 0x00080000 /* RX Error in Prio Queue 3 */#define GT_ICR_MII_STC 0x10000000 /* MII PHY Status Change */#define GT_ICR_SMI_DONE 0x20000000 /* SMI Command Done */#define GT_ICR_INT_SUM 0x80000000 /* Ethernet Interrupt Summary */#define GT_ICR_MASK 0x7FFFFFFF/* Ethernet hash entry */#define GT_HTE_VALID 0x00000001 /* Valid entry */#define GT_HTE_SKIP 0x00000002 /* Skip entry in a chain */#define GT_HTE_RD 0x00000004 /* 0: Discard, 1: Receive */#define GT_HTE_ADDR_MASK 0x7fffffffffff8ULL#define GT_HTE_HOPNUM 12 /* Hash Table Hop Number */enum { GT_HTLOOKUP_MISS, GT_HTLOOKUP_MATCH, GT_HTLOOKUP_HOP_EXCEEDED,};/* TX Descriptor */#define GT_TXDESC_OWN 0x80000000 /* Ownership */#define GT_TXDESC_AM 0x40000000 /* Auto-mode */#define GT_TXDESC_EI 0x00800000 /* Enable Interrupt */#define GT_TXDESC_GC 0x00400000 /* Generate CRC */#define GT_TXDESC_P 0x00040000 /* Padding */#define GT_TXDESC_F 0x00020000 /* First buffer of packet */#define GT_TXDESC_L 0x00010000 /* Last buffer of packet */#define GT_TXDESC_ES 0x00008000 /* Error Summary */#define GT_TXDESC_RC 0x00003c00 /* Retransmit Count */#define GT_TXDESC_COL 0x00000200 /* Collision */#define GT_TXDESC_RL 0x00000100 /* Retransmit Limit Error */#define GT_TXDESC_UR 0x00000040 /* Underrun Error */#define GT_TXDESC_LC 0x00000020 /* Late Collision Error */#define GT_TXDESC_BC_MASK 0xFFFF0000 /* Number of bytes to transmit */#define GT_TXDESC_BC_SHIFT 16/* RX Descriptor */#define GT_RXDESC_OWN 0x80000000 /* Ownership */#define GT_RXDESC_AM 0x40000000 /* Auto-mode */#define GT_RXDESC_EI 0x00800000 /* Enable Interrupt */#define GT_RXDESC_F 0x00020000 /* First buffer of packet */#define GT_RXDESC_L 0x00010000 /* Last buffer of packet */#define GT_RXDESC_ES 0x00008000 /* Error Summary */#define GT_RXDESC_IGMP 0x00004000 /* IGMP packet detected */#define GT_RXDESC_HE 0x00002000 /* Hash Table Expired */#define GT_RXDESC_M 0x00001000 /* Missed Frame */#define GT_RXDESC_FT 0x00000800 /* Frame Type (802.3/Ethernet) */#define GT_RXDESC_SF 0x00000100 /* Short Frame Error */#define GT_RXDESC_MFL 0x00000080 /* Maximum Frame Length Error */#define GT_RXDESC_OR 0x00000040 /* Overrun Error */#define GT_RXDESC_COL 0x00000010 /* Collision */#define GT_RXDESC_CE 0x00000001 /* CRC Error */#define GT_RXDESC_BC_MASK 0x0000FFFF /* Byte count */#define GT_RXDESC_BS_MASK 0xFFFF0000 /* Buffer size */#define GT_RXDESC_BS_SHIFT 16/* RX/TX descriptor */struct eth_desc { m_uint32_t buf_size; m_uint32_t cmd_stat; m_uint32_t next_ptr; m_uint32_t buf_ptr;};/* Galileo Ethernet port */struct eth_port { netio_desc_t *nio; /* First and Current RX descriptors (4 queues) */ m_uint32_t rx_start[4],rx_current[4]; /* Current TX descriptors (2 queues) */ m_uint32_t tx_current[2]; /* Port registers */ m_uint32_t pcr,pcxr,pcmr,psr; /* SDMA registers */ m_uint32_t sdcr,sdcmr; /* Interrupt register */ m_uint32_t icr,imr; /* Hash Table pointer */ m_uint32_t ht_addr; /* Ethernet MIB counters */ m_uint32_t rx_bytes,tx_bytes,rx_frames,tx_frames;};/* Galileo GT64xxx/GT96xxx system controller */struct gt_data { char *name; vm_obj_t vm_obj; struct vdevice dev; struct pci_device *pci_dev; vm_instance_t *vm; struct pci_bus *bus[2]; struct dma_channel dma[GT_DMA_CHANNELS]; m_uint32_t int_cause_reg; m_uint32_t int_mask_reg; /* Ethernet ports (GT-96100) */ u_int eth_irq; ptask_id_t eth_tx_tid; struct eth_port eth_ports[GT_ETH_PORTS]; m_uint32_t smi_reg; m_uint16_t mii_regs[32][32];};/* Log a GT message */#define GT_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)/* Update the interrupt status */static void gt_update_irq_status(struct gt_data *gt_data){ if (gt_data->pci_dev) { if (gt_data->int_cause_reg & gt_data->int_mask_reg) pci_dev_trigger_irq(gt_data->vm,gt_data->pci_dev); else pci_dev_clear_irq(gt_data->vm,gt_data->pci_dev); }}/* Fetch a DMA record (chained mode) */static void gt_dma_fetch_rec(vm_instance_t *vm,struct dma_channel *channel){ m_uint32_t ptr; #if DEBUG_DMA vm_log(vm,"GT_DMA","fetching record at address 0x%x\n",channel->nrptr);#endif /* fetch the record from RAM */ ptr = channel->nrptr; channel->byte_count = swap32(physmem_copy_u32_from_vm(vm,ptr)); channel->src_addr = swap32(physmem_copy_u32_from_vm(vm,ptr+0x04)); channel->dst_addr = swap32(physmem_copy_u32_from_vm(vm,ptr+0x08)); channel->nrptr = swap32(physmem_copy_u32_from_vm(vm,ptr+0x0c)); /* clear the "fetch next record bit" */ channel->ctrl &= ~GT_DMA_FETCH_NEXT;}/* Handle control register of a DMA channel */static void gt_dma_handle_ctrl(struct gt_data *gt_data,int chan_id){ struct dma_channel *channel = >_data->dma[chan_id]; vm_instance_t *vm = gt_data->vm; int done; if (channel->ctrl & GT_DMA_FETCH_NEXT) { if (channel->nrptr == 0) { vm_log(vm,"GT_DMA","trying to load a NULL DMA record...\n"); return; } gt_dma_fetch_rec(vm,channel); } if (channel->ctrl & GT_DMA_CHAN_ENABLE) { do { done = TRUE;#if DEBUG_DMA vm_log(vm,"GT_DMA", "starting transfer from 0x%x to 0x%x (size=%u bytes)\n", channel->src_addr,channel->dst_addr, channel->byte_count & 0xFFFF);#endif physmem_dma_transfer(vm,channel->src_addr,channel->dst_addr, channel->byte_count & 0xFFFF); /* chained mode */ if (!(channel->ctrl & GT_DMA_CHAIN_MODE)) { if (channel->nrptr) { gt_dma_fetch_rec(vm,channel); done = FALSE; } } }while(!done);#if DEBUG_DMA vm_log(vm,"GT_DMA","finished transfer.\n");#endif /* Trigger DMA interrupt */ gt_data->int_cause_reg |= 1 << (4 + chan_id); gt_update_irq_status(gt_data); }}#define DMA_REG(ch,reg_name) \ if (op_type == MTS_WRITE) \ gt_data->dma[ch].reg_name = swap32(*data); \ else \ *data = swap32(gt_data->dma[ch].reg_name);/* Handle a DMA channel */static int gt_dma_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 gt_data *gt_data = dev->priv_data; switch(offset) { /* DMA Source Address */ case 0x810: DMA_REG(0,src_addr); return(1); case 0x814: DMA_REG(1,src_addr); return(1); case 0x818: DMA_REG(2,src_addr); return(1); case 0x81c: DMA_REG(3,src_addr); return(1); /* DMA Destination Address */ case 0x820: DMA_REG(0,dst_addr); return(1); case 0x824: DMA_REG(1,dst_addr); return(1); case 0x828: DMA_REG(2,dst_addr); return(1); case 0x82c: DMA_REG(3,dst_addr); return(1); /* DMA Next Record Pointer */ case 0x830: gt_data->dma[0].cdptr = *data; DMA_REG(0,nrptr); return(1); case 0x834: gt_data->dma[1].cdptr = *data; DMA_REG(1,nrptr); return(1); case 0x838: gt_data->dma[2].cdptr = *data; DMA_REG(2,nrptr); return(1); case 0x83c: gt_data->dma[3].cdptr = *data; DMA_REG(3,nrptr); return(1); /* DMA Channel Control */ case 0x840: DMA_REG(0,ctrl); if (op_type == MTS_WRITE) gt_dma_handle_ctrl(gt_data,0); return(1); case 0x844: DMA_REG(1,ctrl); if (op_type == MTS_WRITE) gt_dma_handle_ctrl(gt_data,1); return(1); case 0x848: DMA_REG(2,ctrl); if (op_type == MTS_WRITE) gt_dma_handle_ctrl(gt_data,2); return(1); case 0x84c: DMA_REG(3,ctrl); if (op_type == MTS_WRITE) gt_dma_handle_ctrl(gt_data,3); return(1); } return(0);}/* * dev_gt64010_access() */void *dev_gt64010_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 gt_data *gt_data = dev->priv_data; if (op_type == MTS_READ) *data = 0; if (gt_dma_access(cpu,dev,offset,op_size,op_type,data) != 0) return NULL; switch(offset) { /* ===== DRAM Settings (completely faked, 128 Mb) ===== */ case 0x008: /* ras10_low */ if (op_type == MTS_READ) *data = swap32(0x000); break; case 0x010: /* ras10_high */ if (op_type == MTS_READ) *data = swap32(0x7F); break; case 0x018: /* ras32_low */ if (op_type == MTS_READ) *data = swap32(0x080);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -