📄 dev_mv64460.c
字号:
/* * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * Marvell MV64460 system controller. * * Based on GT9100 documentation and Linux kernel sources. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "utils.h"#include "net.h"#include "cpu.h"#include "vm.h"#include "dynamips.h"#include "memory.h"#include "device.h"#include "net_io.h"#include "ptask.h"#include "dev_vtty.h"#include "dev_mv64460.h"/* Debugging flags */#define DEBUG_ACCESS 0#define DEBUG_UNKNOWN 0#define DEBUG_DMA 0#define DEBUG_MII 0/* PCI identification */#define PCI_VENDOR_MARVELL 0x11ab /* Marvell/Galileo */#define PCI_PRODUCT_MARVELL_MV64460 0x6485 /* MV-64460 *//* FIXME */#define MV64460_MAX_PKT_SIZE 2048/* Interrupt Low Main Cause Register */#define MV64460_REG_ILMCR 0x0004#define MV64460_ILMCR_IDMA0_COMP 0x00000010 /* IDMA 0 */ #define MV64460_ILMCR_IDMA1_COMP 0x00000020 /* IDMA 1 */ #define MV64460_ILMCR_IDMA2_COMP 0x00000040 /* IDMA 2 */ #define MV64460_ILMCR_IDMA3_COMP 0x00000080 /* IDMA 3 */ #define MV64460_ILMCR_TIMER0_EXP 0x00000100 /* Timer 0 */#define MV64460_ILMCR_TIMER1_EXP 0x00000200 /* Timer 1 */#define MV64460_ILMCR_TIMER2_EXP 0x00000400 /* Timer 2 */#define MV64460_ILMCR_TIMER3_EXP 0x00000800 /* Timer 3 */#define MV64460_ILMCR_P1_GPP_0_7_SUM 0x01000000 /* GPP 0-7 (CPU1) */#define MV64460_ILMCR_P1_GPP_8_15_SUM 0x02000000 /* GPP 8-15 (CPU1) */#define MV64460_ILMCR_P1_GPP_16_23_SUM 0x04000000 /* GPP 16-23 (CPU1) */#define MV64460_ILMCR_P1_GPP_24_31_SUM 0x08000000 /* GPP 24-31 (CPU1) *//* Interrupt High Main Cause Register */#define MV64460_REG_IHMCR 0x000c#define MV64460_IHMCR_ETH0_SUM 0x00000001 /* Ethernet0 summary */#define MV64460_IHMCR_ETH1_SUM 0x00000002 /* Ethernet1 summary */#define MV64460_IHMCR_ETH2_SUM 0x00000004 /* Ethernet2 summary */#define MV64460_IHMCR_SDMA0_SUM 0x00000010 /* Serial DMA0 */#define MV64460_IHMCR_SDMA1_SUM 0x00000040 /* Serial DMA1 */#define MV64460_IHMCR_MPSC0_SUM 0x00000100 /* MPSC0 */#define MV64460_IHMCR_MPSC1_SUM 0x00000200 /* MPSC1 */#define MV64460_IHMCR_ETH0_RX_SUM 0x00000400 /* Ethernet0 RX */#define MV64460_IHMCR_ETH0_TX_SUM 0x00000800 /* Ethernet0 TX */#define MV64460_IHMCR_ETH0_MISC_SUM 0x00001000 /* Ethernet0 Misc */#define MV64460_IHMCR_ETH1_RX_SUM 0x00002000 /* Ethernet1 RX */#define MV64460_IHMCR_ETH1_TX_SUM 0x00004000 /* Ethernet1 TX */#define MV64460_IHMCR_ETH1_MISC_SUM 0x00008000 /* Ethernet1 Misc */#define MV64460_IHMCR_ETH2_RX_SUM 0x00010000 /* Ethernet1 RX */#define MV64460_IHMCR_ETH2_TX_SUM 0x00020000 /* Ethernet1 TX */#define MV64460_IHMCR_ETH2_MISC_SUM 0x00040000 /* Ethernet1 Misc */#define MV64460_IHMCR_P0_GPP_0_7_SUM 0x01000000 /* GPP 0-7 (CPU0) */#define MV64460_IHMCR_P0_GPP_8_15_SUM 0x02000000 /* GPP 8-15 (CPU0) */#define MV64460_IHMCR_P0_GPP_16_23_SUM 0x04000000 /* GPP 16-23 (CPU0) */#define MV64460_IHMCR_P0_GPP_24_31_SUM 0x08000000 /* GPP 24-31 (CPU0) *//* Interrupt registers: CPU_INTn[0], CPU_INTn[1], INT0n, INT1n */#define MV64460_REG_CPU_INTN0_MASK_LO 0x0014#define MV64460_REG_CPU_INTN0_MASK_HI 0x001c#define MV64460_REG_CPU_INTN0_SEL_CAUSE 0x0024#define MV64460_REG_CPU_INTN1_MASK_LO 0x0034#define MV64460_REG_CPU_INTN1_MASK_HI 0x003c#define MV64460_REG_CPU_INTN1_SEL_CAUSE 0x0044#define MV64460_REG_INT0N_MASK_LO 0x0054#define MV64460_REG_INT0N_MASK_HI 0x005c#define MV64460_REG_INT0N_SEL_CAUSE 0x0064#define MV64460_REG_INT1N_MASK_LO 0x0074#define MV64460_REG_INT1N_MASK_HI 0x007c#define MV64460_REG_INT1N_SEL_CAUSE 0x0084#define MV64460_IC_CAUSE_MASK 0x3FFFFFFF /* Shadow of cause register */#define MV64460_IC_CAUSE_SEL 0x40000000 /* Low or High register */#define MV64460_IC_CAUSE_STAT 0x80000000 /* Interrupt status *//* GPP Interrupt cause and mask registers */#define MV64460_REG_GPP_INTR_CAUSE 0xf108#define MV64460_REG_GPP_INTR_MASK0 0xf10c#define MV64460_REG_GPP_INTR_MASK1 0xf114#define MV64460_REG_GPP_VALUE_SET 0xf118#define MV64460_REG_GPP_VALUE_CLEAR 0xf11c/* TX Descriptor */#define MV64460_TXDESC_OWN 0x80000000 /* Ownership */#define MV64460_TXDESC_AM 0x40000000 /* Auto-mode */#define MV64460_TXDESC_EI 0x00800000 /* Enable Interrupt */#define MV64460_TXDESC_GC 0x00400000 /* Generate CRC */#define MV64460_TXDESC_P 0x00040000 /* Padding */#define MV64460_TXDESC_F 0x00020000 /* First buffer of packet */#define MV64460_TXDESC_L 0x00010000 /* Last buffer of packet */#define MV64460_TXDESC_ES 0x00008000 /* Error Summary */#define MV64460_TXDESC_RC 0x00003c00 /* Retransmit Count */#define MV64460_TXDESC_COL 0x00000200 /* Collision */#define MV64460_TXDESC_RL 0x00000100 /* Retransmit Limit Error */#define MV64460_TXDESC_UR 0x00000040 /* Underrun Error */#define MV64460_TXDESC_LC 0x00000020 /* Late Collision Error */#define MV64460_TXDESC_BC_MASK 0xFFFF0000 /* Number of bytes to transmit */#define MV64460_TXDESC_BC_SHIFT 16/* RX Descriptor */#define MV64460_RXDESC_OWN 0x80000000 /* Ownership */#define MV64460_RXDESC_AM 0x40000000 /* Auto-mode */#define MV64460_RXDESC_EI 0x00800000 /* Enable Interrupt */#define MV64460_RXDESC_F 0x00020000 /* First buffer of packet */#define MV64460_RXDESC_L 0x00010000 /* Last buffer of packet */#define MV64460_RXDESC_ES 0x00008000 /* Error Summary */#define MV64460_RXDESC_IGMP 0x00004000 /* IGMP packet detected */#define MV64460_RXDESC_HE 0x00002000 /* Hash Table Expired */#define MV64460_RXDESC_M 0x00001000 /* Missed Frame */#define MV64460_RXDESC_FT 0x00000800 /* Frame Type (802.3/Ethernet) */#define MV64460_RXDESC_SF 0x00000100 /* Short Frame Error */#define MV64460_RXDESC_MFL 0x00000080 /* Maximum Frame Length Error */#define MV64460_RXDESC_OR 0x00000040 /* Overrun Error */#define MV64460_RXDESC_COL 0x00000010 /* Collision */#define MV64460_RXDESC_CE 0x00000001 /* CRC Error */#define MV64460_RXDESC_BC_MASK 0x0000FFFF /* Byte count */#define MV64460_RXDESC_BS_MASK 0xFFFF0000 /* Buffer size */#define MV64460_RXDESC_BS_SHIFT 16/* === IDMA =============================================================== */#define MV64460_IDMA_CHANNELS 4/* Address decoding registers */#define MV64460_IDMA_BAR_REGS 8 /* 8 BAR registers */#define MV64460_IDMA_HAR_REGS 4 /* High address remap for BAR0-3 */#define MV64460_REG_IDMA_BAR(x) (0xA00 + (x << 3))#define MV64460_REG_IDMA_SR(x) (0xA04 + (x << 3))#define MV64460_REG_IDMA_HAR(x) (0xA60 + (x << 2))/* === Serial DMA (SDMA) ================================================== *//* SDMA - number of channels */#define MV64460_SDMA_CHANNELS 2/* SDMA channel */struct sdma_channel { u_int id; m_uint32_t sdc; m_uint32_t sdcm; m_uint32_t rx_desc; m_uint32_t rx_buf_ptr; m_uint32_t scrdp; m_uint32_t tx_desc; m_uint32_t sctdp; m_uint32_t sftdp;};/* SDMA registers base offsets */#define MV64460_REG_SDMA0 0x4000#define MV64460_REG_SDMA1 0x6000/* SDMA cause and mask registers */#define MV64460_REG_SDMA_CAUSE 0xb800#define MV64460_REG_SDMA_MASK 0xb880#define MV64460_SDMA_CAUSE_SDMA0 0x0000000F#define MV64460_SDMA_CAUSE_SDMA1 0x00000F00#define MV64460_SDMA_CAUSE_RXBUF0 0x00000001 /* RX Buffer returned */#define MV64460_SDMA_CAUSE_RXERR0 0x00000002 /* RX Error */#define MV64460_SDMA_CAUSE_TXBUF0 0x00000004 /* TX Buffer returned */#define MV64460_SDMA_CAUSE_TXEND0 0x00000008 /* TX End */#define MV64460_SDMA_CAUSE_RXBUF1 0x00000100 /* RX Buffer returned */#define MV64460_SDMA_CAUSE_RXERR1 0x00000200 /* RX Error */#define MV64460_SDMA_CAUSE_TXBUF1 0x00000400 /* TX Buffer returned */#define MV64460_SDMA_CAUSE_TXEND1 0x00000800 /* TX End *//* SDMA register offsets (per channel) */#define MV64460_SDMA_SDC 0x0000 /* Configuration Register */#define MV64460_SDMA_SDCM 0x0008 /* Command Register */#define MV64460_SDMA_RX_DESC 0x0800 /* RX descriptor */#define MV64460_SDMA_SCRDP 0x0810 /* Current RX descriptor */#define MV64460_SDMA_TX_DESC 0x0c00 /* TX descriptor */#define MV64460_SDMA_SCTDP 0x0c10 /* Current TX desc. pointer */#define MV64460_SDMA_SFTDP 0x0c14 /* First TX desc. pointer *//* SDCR: SDMA Configuration Register */#define MV64460_SDCR_RFT 0x00000001 /* Receive FIFO Threshold */#define MV64460_SDCR_SFM 0x00000002 /* Single Frame Mode */#define MV64460_SDCR_RC 0x0000003c /* Retransmit count */#define MV64460_SDCR_BLMR 0x00000040 /* Big/Little Endian RX mode */#define MV64460_SDCR_BLMT 0x00000080 /* Big/Litlle Endian TX mode */#define MV64460_SDCR_POVR 0x00000100 /* PCI override */#define MV64460_SDCR_RIFB 0x00000200 /* RX IRQ on frame boundary */#define MV64460_SDCR_BSZ 0x00003000 /* Burst size *//* SDCMR: SDMA Command Register */#define MV64460_SDCMR_ERD 0x00000080 /* Enable RX DMA */#define MV64460_SDCMR_AR 0x00008000 /* Abort Receive */#define MV64460_SDCMR_STD 0x00010000 /* Stop TX */#define MV64460_SDCMR_STDH MV64460_SDCMR_STD /* Stop TX High */#define MV64460_SDCMR_STDL 0x00020000 /* Stop TX Low */#define MV64460_SDCMR_TXD 0x00800000 /* TX Demand */#define MV64460_SDCMR_TXDH MV64460_SDCMR_TXD /* Start TX High */#define MV64460_SDCMR_TXDL 0x01000000 /* Start TX Low */#define MV64460_SDCMR_AT 0x80000000 /* Abort Transmit *//* SDMA RX/TX descriptor */struct sdma_desc { m_uint32_t buf_size; m_uint32_t cmd_stat; m_uint32_t next_ptr; m_uint32_t buf_ptr;};/* SDMA Descriptor Command/Status word */#define MV64460_SDMA_CMD_O 0x80000000 /* Owner bit */#define MV64460_SDMA_CMD_AM 0x40000000 /* Auto-mode */#define MV64460_SDMA_CMD_EI 0x00800000 /* Enable Interrupt */#define MV64460_SDMA_CMD_F 0x00020000 /* First buffer */#define MV64460_SDMA_CMD_L 0x00010000 /* Last buffer *//* === MultiProtocol Serial Controller (MPSC) ============================= *//* 2 MPSC channels */#define MV64460_MPSC_CHANNELS 2/* MPSC channel */struct mpsc_channel { m_uint32_t mmcrl; m_uint32_t mmcrh; m_uint32_t mpcr; m_uint32_t chr[10]; vtty_t *vtty; netio_desc_t *nio;};/* MPSC registers base offsets */#define MV64460_REG_MPSC0 0x8000#define MV64460_REG_MPSC1 0x9000#define MV64460_MPSC_MMCRL 0x0000 /* Main Config Register Low */#define MV64460_MPSC_MMCRH 0x0004 /* Main Config Register High */#define MV64460_MPSC_MPCR 0x0008 /* Protocol Config Register */#define MV64460_MPSC_CHR1 0x000C#define MV64460_MPSC_CHR2 0x0010#define MV64460_MPSC_CHR3 0x0014#define MV64460_MPSC_CHR4 0x0018#define MV64460_MPSC_CHR5 0x001C#define MV64460_MPSC_CHR6 0x0020#define MV64460_MPSC_CHR7 0x0024#define MV64460_MPSC_CHR8 0x0028#define MV64460_MPSC_CHR9 0x002C#define MV64460_MPSC_CHR10 0x0030#define MV64460_MMCRL_MODE_MASK 0x0000007#define MV64460_MPSC_MODE_HDLC 0#define MV64460_MPSC_MODE_UART 4#define MV64460_MPSC_MODE_BISYNC 5/* === Integrated SRAM ==================================================== */#define MV64460_SRAM_WIDTH 18#define MV64460_SRAM_SIZE (1 << MV64460_SRAM_WIDTH)#define MV64460_REG_SRAM_BASE 0x268/* SRAM base register */#define MV64460_SRAM_BASE_MASK 0x000FFFFC#define MV64460_SRAM_BASE_SHIFT 2/* ======================================================================== *//* MV64460 system controller private data */struct mv64460_data { char *name; vm_obj_t vm_obj; struct vdevice dev; struct pci_device *pci_dev; vm_instance_t *vm; pthread_mutex_t lock; /* Interrupt controller registers */ m_uint32_t intr_lo,intr_hi; m_uint32_t cpu_intn0_mask_lo,cpu_intn0_mask_hi; m_uint32_t cpu_intn1_mask_lo,cpu_intn1_mask_hi; m_uint32_t int0n_mask_lo,int0n_mask_hi; m_uint32_t int1n_mask_lo,int1n_mask_hi; /* GPP interrupts */ m_uint32_t gpp_intr,gpp_mask0,gpp_mask1; /* IDMA registers */ m_uint32_t idma_bar[MV64460_IDMA_BAR_REGS]; m_uint32_t idma_sr[MV64460_IDMA_BAR_REGS]; m_uint32_t idma_har[MV64460_IDMA_HAR_REGS]; /* SDMA channels */ m_uint32_t sdma_cause,sdma_mask; struct sdma_channel sdma[MV64460_SDMA_CHANNELS]; /* MPSC - MultiProtocol Serial Controller */ struct mpsc_channel mpsc[MV64460_MPSC_CHANNELS]; /* Integrated SRAM */ struct vdevice sram_dev; /* PCI busses */ struct pci_bus *bus[2];};#define MV64460_LOCK(d) pthread_mutex_lock(&(d)->lock)#define MV64460_UNLOCK(d) pthread_mutex_unlock(&(d)->lock)/* Log a GT message */#define MV64460_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)/* ======================================================================== *//* Forward declarations *//* ======================================================================== */static u_int mv64460_mpsc_get_channel_mode(struct mv64460_data *d,u_int id);/* ======================================================================== *//* General interrupt control *//* ======================================================================== *//* Returns a select cause register */static m_uint32_t mv64460_ic_get_sel_cause(struct mv64460_data *d, m_uint32_t mask_lo, m_uint32_t mask_hi){ int lo_act,hi_act; m_uint32_t res; lo_act = d->intr_lo & mask_lo; hi_act = d->intr_hi & mask_hi; if (!lo_act && hi_act) { res = (d->intr_hi & MV64460_IC_CAUSE_MASK) | MV64460_IC_CAUSE_SEL; } else { res = d->intr_lo & MV64460_IC_CAUSE_MASK; if (lo_act && hi_act) res |= MV64460_IC_CAUSE_STAT; } return(res);}/* Update the interrupt status for CPU 0 */static void mv64460_ic_update_cpu0_status(struct mv64460_data *d){ cpu_ppc_t *cpu0 = CPU_PPC32(d->vm->boot_cpu); m_uint32_t lo_act,hi_act; lo_act = d->intr_lo & d->cpu_intn0_mask_lo; hi_act = d->intr_hi & d->cpu_intn0_mask_hi; cpu0->irq_pending = lo_act || hi_act; cpu0->irq_check = cpu0->irq_pending;}/* Update GPIO interrupt status */static void mv64460_gpio_update_int_status(struct mv64460_data *d){ /* GPIO 0-7 */ if (d->gpp_intr & d->gpp_mask0 & 0x000000FF) d->intr_hi |= MV64460_IHMCR_P0_GPP_0_7_SUM; else d->intr_hi &= ~MV64460_IHMCR_P0_GPP_0_7_SUM; /* GPIO 8-15 */ if (d->gpp_intr & d->gpp_mask0 & 0x0000FF00) d->intr_hi |= MV64460_IHMCR_P0_GPP_8_15_SUM; else d->intr_hi &= ~MV64460_IHMCR_P0_GPP_8_15_SUM; /* GPIO 16-23 */ if (d->gpp_intr & d->gpp_mask0 & 0x00FF0000) d->intr_hi |= MV64460_IHMCR_P0_GPP_16_23_SUM; else d->intr_hi &= ~MV64460_IHMCR_P0_GPP_16_23_SUM; /* GPIO 24-32 */ if (d->gpp_intr & d->gpp_mask0 & 0xFF000000) d->intr_hi |= MV64460_IHMCR_P0_GPP_24_31_SUM; else d->intr_hi &= ~MV64460_IHMCR_P0_GPP_24_31_SUM; mv64460_ic_update_cpu0_status(d);}/* ======================================================================== *//* SDMA (Serial DMA) *//* ======================================================================== *//* Update SDMA interrupt status */static void mv64460_sdma_update_int_status(struct mv64460_data *d){ if (d->sdma_cause & d->sdma_mask & MV64460_SDMA_CAUSE_SDMA0) { d->intr_hi |= MV64460_IHMCR_SDMA0_SUM; } else { d->intr_hi &= ~MV64460_IHMCR_SDMA0_SUM; } if (d->sdma_cause & d->sdma_mask & MV64460_SDMA_CAUSE_SDMA1) { d->intr_hi |= MV64460_IHMCR_SDMA1_SUM; } else { d->intr_hi &= ~MV64460_IHMCR_SDMA1_SUM; } mv64460_ic_update_cpu0_status(d);}/* Set SDMA cause register for a channel */static inline void mv64460_sdma_set_cause(struct mv64460_data *d,u_int chan_id, u_int value){ d->sdma_cause |= value << (chan_id << 3);}/* Read a SDMA descriptor from memory */static void mv64460_sdma_desc_read(struct mv64460_data *d,m_uint32_t addr,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -