📄 dev_mpc860.c
字号:
/* * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * MPC860 internal devices. */#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 "dev_mpc860.h"/* Debugging flags */#define DEBUG_ACCESS 0#define DEBUG_UNKNOWN 1#define DEBUG_IDMA 0#define DEBUG_SPI 0#define DEBUG_SCC 0#define DEBUG_FEC 1#define MPC860_TXRING_PASS_COUNT 16/* Dual-Port RAM */#define MPC860_DPRAM_OFFSET 0x2000#define MPC860_DPRAM_SIZE 0x2000#define MPC860_DPRAM_END (MPC860_DPRAM_OFFSET + MPC860_DPRAM_SIZE)/* MPC860 registers */#define MPC860_REG_SWSR 0x000e /* Software Service Register */#define MPC860_REG_SIPEND 0x0010 /* SIU Interrupt Pending Register */#define MPC860_REG_SIMASK 0x0014 /* SIU Interrupt Mask Register */#define MPC860_REG_PIPR 0x00f0 /* PCMCIA Interface Input Pins Reg. */#define MPC860_REG_TBSCR 0x0200 /* Timebase Status and Control Reg. */#define MPC860_REG_PISCR 0x0240 /* Periodic Int. Status and Ctrl Reg. */#define MPC860_REG_IDSR1 0x0910 /* IDMA1 Status Register */#define MPC860_REG_IDMR1 0x0914 /* IDMA1 Mask Register */#define MPC860_REG_IDSR2 0x0918 /* IDMA2 Status Register */#define MPC860_REG_IDMR2 0x091c /* IDMA2 Mask Register */#define MPC860_REG_CICR 0x0940 /* CPM Int Config Register */#define MPC860_REG_CIPR 0x0944 /* CPM Int Pending Register */#define MPC860_REG_CIMR 0x0948 /* CPM Int Mask Register */#define MPC860_REG_PCSO 0x0964 /* Port C Special Options Register */#define MPC860_REG_PCDAT 0x0966 /* Port C Data Register */#define MPC860_REG_CPCR 0x09c0 /* CP Command Register */#define MPC860_REG_SCC_BASE 0x0a00 /* SCC register base */#define MPC860_REG_SPMODE 0x0aa0 /* SPI Mode Register */#define MPC860_REG_SPIE 0x0aa6 /* SPI Event Register */#define MPC860_REG_SPIM 0x0aaa /* SPI Mask Register */#define MPC860_REG_SPCOM 0x0aad /* SPI Command Register */#define MPC860_REG_PBDAT 0x0ac4 /* Port B Data Register */#define MPC860_REG_FEC_BASE 0x0e00 /* FEC register base */#define MPC860_REG_FEC_END 0x0f84 /* FEC register end *//* ======================================================================== *//* CICR (CPM Interrupt Config Register) */#define MPC860_CICR_IRL_MASK 0x0000E000 /* Interrupt Level */#define MPC860_CICR_IRL_SHIFT 13#define MPC860_CICR_IEN 0x00000080 /* Interrupt Enable *//* CIPR (CPM Interrupt Pending Register) */#define MPC860_CIPR_PC15 0x80000000#define MPC860_CIPR_SCC1 0x40000000#define MPC860_CIPR_SCC2 0x20000000#define MPC860_CIPR_SCC3 0x10000000#define MPC860_CIPR_SCC4 0x08000000#define MPC860_CIPR_PC14 0x04000000#define MPC860_CIPR_TIMER1 0x02000000#define MPC860_CIPR_PC13 0x01000000#define MPC860_CIPR_PC12 0x00800000#define MPC860_CIPR_SDMA 0x00400000#define MPC860_CIPR_IDMA1 0x00200000#define MPC860_CIPR_IDMA2 0x00100000#define MPC860_CIPR_TIMER2 0x00040000#define MPC860_CIPR_RTT 0x00020000#define MPC860_CIPR_I2C 0x00010000#define MPC860_CIPR_PC11 0x00008000#define MPC860_CIPR_PC10 0x00004000#define MPC860_CIPR_TIMER3 0x00001000#define MPC860_CIPR_PC9 0x00000800#define MPC860_CIPR_PC8 0x00000400#define MPC860_CIPR_PC7 0x00000200#define MPC860_CIPR_TIMER4 0x00000080#define MPC860_CIPR_PC6 0x00000040#define MPC860_CIPR_SPI 0x00000020#define MPC860_CIPR_SMC1 0x00000010#define MPC860_CIPR_SMC2 0x00000008#define MPC860_CIPR_PC5 0x00000004#define MPC860_CIPR_PC4 0x00000002/* CPCR (CP Command Register) */#define MPC860_CPCR_RST 0x8000 /* CP reset command */#define MPC860_CPCR_FLG 0x0001 /* Command Semaphore Flag */#define MPC860_CPCR_CHNUM_MASK 0x00F0 /* Channel Number */#define MPC860_CPCR_CHNUM_SHIFT 4#define MPC860_CPCR_OPCODE_MASK 0x0F00 /* Opcode */#define MPC860_CPCR_OPCODE_SHIFT 8/* CP channels */#define MPC860_CHAN_SCC1 0x00#define MPC860_CHAN_I2C_IDMA1 0x01#define MPC860_CHAN_SCC2 0x04#define MPC860_CHAN_SPI_IDMA2_RT 0x05#define MPC860_CHAN_SCC3 0x08#define MPC860_CHAN_SMC1 0x09#define MPC860_CHAN_SCC4 0x0c#define MPC860_CHAN_SMC2_PIP 0x0d/* ======================================================================== *//* IDMA Status Register */#define MPC860_IDSR_OB 0x0001 /* Out of Buffers */#define MPC860_IDSR_DONE 0x0002 /* Buffer chain done */#define MPC860_IDSR_AD 0x0004 /* Auxiliary done *//* Offsets of IDMA channels (from DPRAM base) */#define MPC860_IDMA1_BASE 0x1cc0#define MPC860_IDMA2_BASE 0x1dc0/* Size of an IDMA buffer descriptor */#define MPC860_IDMA_BD_SIZE 16/* IDMA Buffer Descriptor Control Word */#define MPC860_IDMA_CTRL_V 0x8000 /* Valid Bit */#define MPC860_IDMA_CTRL_W 0x2000 /* Wrap */#define MPC860_IDMA_CTRL_I 0x1000 /* Interrupt for this BD */#define MPC860_IDMA_CTRL_L 0x0800 /* Last buffer of chain */#define MPC860_IDMA_CTRL_CM 0x0200 /* Continuous mode *//* IDMA buffer descriptor */struct mpc860_idma_bd { m_uint16_t offset; /* Offset in DPRAM memory */ m_uint16_t ctrl; /* Control Word */ m_uint8_t dfcr,sfcr; /* Src/Dst Function code registers */ m_uint32_t buf_len; /* Buffer Length */ m_uint32_t src_bp; /* Source buffer pointer */ m_uint32_t dst_bp; /* Destination buffer pointer */};/* ======================================================================== *//* SPI Mode Register (SPMODE) */#define MPC860_SPMODE_LOOP 0x4000 /* Loop mode */#define MPC860_SPMODE_CI 0x2000 /* Clock Invert */#define MPC860_SPMODE_CP 0x1000 /* Clock Phase */#define MPC860_SPMODE_DIV16 0x0800 /* Divide by 16 (SPI clock generator) */#define MPC860_SPMODE_REV 0x0400 /* Reverse Data */#define MPC860_SPMODE_MS 0x0200 /* Master/Slave mode select */#define MPC860_SPMODE_EN 0x0100 /* Enable SPI */#define MPC860_SPMODE_LEN_MASK 0x00F0 /* Data length (4 - 11 bits) */#define MPC860_SPMODE_LEN_SHIFT 4#define MPC860_SPMODE_PM_MASK 0x000F /* Prescale Modulus Select *//* SPI Event/Mask Registers (SPIE/SPIM) */#define MPC860_SPIE_MME 0x20 /* MultiMaster Error */#define MPC860_SPIE_TXE 0x10 /* TX Error */#define MPC860_SPIE_BSY 0x04 /* Busy (no RX buffer available) */#define MPC860_SPIE_TXB 0x02 /* TX Buffer */#define MPC860_SPIE_RXB 0x01 /* RX Buffer *//* SPI Command Register (SPCOM) */#define MPC860_SPCOM_STR 0x80 /* Start Transmit *//* Offsets of SPI parameters (from DPRAM base) */#define MPC860_SPI_BASE 0x1d80#define MPC860_SPI_BASE_ADDR 0x1dac/* Size of an SPI buffer descriptor */#define MPC860_SPI_BD_SIZE 8/* SPI RX Buffer Descriptor Control Word */#define MPC860_SPI_RXBD_CTRL_E 0x8000 /* Empty */#define MPC860_SPI_RXBD_CTRL_W 0x2000 /* Wrap */#define MPC860_SPI_RXBD_CTRL_I 0x1000 /* Interrupt */#define MPC860_SPI_RXBD_CTRL_L 0x0800 /* Last */#define MPC860_SPI_RXBD_CTRL_CM 0x0200 /* Continuous Mode */#define MPC860_SPI_RXBD_CTRL_OV 0x0002 /* Overrun */#define MPC860_SPI_RXBD_CTRL_ME 0x0001 /* MultiMaster Error *//* SPI TX Buffer Descriptor Control Word */#define MPC860_SPI_TXBD_CTRL_R 0x8000 /* Ready Bit */#define MPC860_SPI_TXBD_CTRL_W 0x2000 /* Wrap */#define MPC860_SPI_TXBD_CTRL_I 0x1000 /* Interrupt */#define MPC860_SPI_TXBD_CTRL_L 0x0800 /* Last */#define MPC860_SPI_TXBD_CTRL_CM 0x0200 /* Continuous Mode */#define MPC860_SPI_TXBD_CTRL_UN 0x0002 /* Underrun */#define MPC860_SPI_TXBD_CTRL_ME 0x0001 /* MultiMaster Error *//* SPI buffer descriptor */struct mpc860_spi_bd { m_uint16_t offset; /* Offset in DPRAM memory */ m_uint16_t ctrl; /* Control Word */ m_uint16_t buf_len; /* Buffer Length */ m_uint32_t bp; /* Buffer Pointer */};/* ======================================================================== *//* Number of SCC channels */#define MPC860_SCC_NR_CHAN 4/* Maximum buffer size for SCC */#define MPC860_SCC_MAX_PKT_SIZE 32768/* Offsets of SCC channels (from DPRAM base) */#define MPC860_SCC1_BASE 0x1c00#define MPC860_SCC2_BASE 0x1d00#define MPC860_SCC3_BASE 0x1e00#define MPC860_SCC4_BASE 0x1f00/* GSMR Low register */#define MPC860_GSMRL_MODE_MASK 0x0000000F/* SCC Modes */#define MPC860_SCC_MODE_HDLC 0x00#define MPC860_SCC_MODE_UART 0x04#define MPC860_SCC_MODE_BISYNC 0x08#define MPC860_SCC_MODE_ETH 0x0c/* SCC Event (SCCE) register */#define MPC860_SCCE_TXB 0x0002 /* TX buffer sent */#define MPC860_SCCE_RXB 0x0001 /* RX buffer ready *//* Size of an SCC buffer descriptor */#define MPC860_SCC_BD_SIZE 8/* SCC RX Buffer Descriptor Control Word */#define MPC860_SCC_RXBD_CTRL_E 0x8000 /* Empty */#define MPC860_SCC_RXBD_CTRL_W 0x2000 /* Wrap */#define MPC860_SCC_RXBD_CTRL_I 0x1000 /* Interrupt */#define MPC860_SCC_RXBD_CTRL_L 0x0800 /* Last */#define MPC860_SCC_RXBD_CTRL_F 0x0400 /* First */#define MPC860_SCC_RXBD_CTRL_CM 0x0200 /* Continuous Mode */#define MPC860_SCC_RXBD_CTRL_OV 0x0002 /* Overrun *//* SCC TX Buffer Descriptor Control Word */#define MPC860_SCC_TXBD_CTRL_R 0x8000 /* Ready Bit */#define MPC860_SCC_TXBD_CTRL_W 0x2000 /* Wrap */#define MPC860_SCC_TXBD_CTRL_I 0x1000 /* Interrupt */#define MPC860_SCC_TXBD_CTRL_L 0x0800 /* Last */#define MPC860_SCC_TXBD_CTRL_TC 0x0400 /* Send TX CRC */#define MPC860_SCC_TXBD_CTRL_CM 0x0200 /* Continuous Mode */#define MPC860_SCC_TXBD_CTRL_UN 0x0002 /* Underrun *//* SCC buffer descriptor */struct mpc860_scc_bd { m_uint16_t offset; /* Offset in DPRAM memory */ m_uint16_t ctrl; /* Control Word */ m_uint16_t buf_len; /* Buffer Length */ m_uint32_t bp; /* Buffer Pointer */};/* ======================================================================== *//* FEC Ethernet Control Register */#define MPC860_ECNTRL_FEC_PIN_MUX 0x00000004 /* FEC enable */#define MPC860_ECNTRL_ETHER_EN 0x00000002 /* Ethernet Enable */#define MPC860_ECNTRL_RESET 0x00000001 /* Reset Ethernet controller *//* FEC Interrupt Vector Register */#define MPC860_IVEC_ILEVEL_MASK 0xE0000000 /* Interrupt Level */#define MPC860_IVEC_ILEVEL_SHIFT 29/* FEC Interrupt Event Register */#define MPC860_IEVENT_HBERR 0x80000000 /* Hearbeat Error */#define MPC860_IEVENT_BABR 0x40000000 /* Babbling Receive Error */#define MPC860_IEVENT_BABT 0x20000000 /* Babbling Transmit Error */#define MPC860_IEVENT_GRA 0x10000000 /* Graceful Stop Complete */#define MPC860_IEVENT_TFINT 0x08000000 /* Transmit Frame Interrupt */#define MPC860_IEVENT_TXB 0x04000000 /* Transmit Buffer Interrupt */#define MPC860_IEVENT_RFINT 0x02000000 /* Receive Frame Interrupt */#define MPC860_IEVENT_RXB 0x01000000 /* Receive Buffer Interrupt */#define MPC860_IEVENT_MII 0x00800000 /* MII Interrupt */#define MPC860_IEVENT_EBERR 0x00400000 /* Ethernet Bus Error *//* MII data register */#define MPC860_MII_OP_MASK 0x30000000 /* Opcode (10:read,11:write) */#define MPC860_MII_OP_SHIFT 28#define MPC860_MII_PHY_MASK 0x0F800000 /* PHY device */#define MPC860_MII_PHY_SHIFT 23#define MPC860_MII_REG_MASK 0x007C0000 /* PHY device */#define MPC860_MII_REG_SHIFT 18/* Size of an FEC buffer descriptor */#define MPC860_FEC_BD_SIZE 8/* Maximum packet size for FEC */#define MPC860_FEC_MAX_PKT_SIZE 2048/* FEC RX Buffer Descriptor Control Word */#define MPC860_FEC_RXBD_CTRL_E 0x8000 /* Empty */#define MPC860_FEC_RXBD_CTRL_RO1 0x4000 /* For software use */#define MPC860_FEC_RXBD_CTRL_W 0x2000 /* Wrap */#define MPC860_FEC_RXBD_CTRL_RO2 0x1000 /* For software use */#define MPC860_FEC_RXBD_CTRL_L 0x0800 /* Last */#define MPC860_FEC_RXBD_CTRL_M 0x0100 /* Miss */#define MPC860_FEC_RXBD_CTRL_BC 0x0080 /* Broadcast DA */#define MPC860_FEC_RXBD_CTRL_MC 0x0040 /* Multicast DA */#define MPC860_FEC_RXBD_CTRL_LG 0x0020 /* RX Frame length violation */#define MPC860_FEC_RXBD_CTRL_NO 0x0010 /* RX non-octet aligned frame */#define MPC860_FEC_RXBD_CTRL_SH 0x0008 /* Short Frame */#define MPC860_FEC_RXBD_CTRL_CR 0x0004 /* RX CRC Error */#define MPC860_FEC_RXBD_CTRL_OV 0x0002 /* Overrun */#define MPC860_FEC_RXBD_CTRL_TR 0x0001 /* Truncated Frame *//* FEC TX Buffer Descriptor Control Word */#define MPC860_FEC_TXBD_CTRL_R 0x8000 /* Ready Bit */#define MPC860_FEC_TXBD_CTRL_TO1 0x4000 /* For software use */#define MPC860_FEC_TXBD_CTRL_W 0x2000 /* Wrap */#define MPC860_FEC_TXBD_CTRL_TO2 0x1000 /* For software use */#define MPC860_FEC_TXBD_CTRL_L 0x0800 /* Last */#define MPC860_FEC_TXBD_CTRL_TC 0x0400 /* Send TX CRC */#define MPC860_FEC_TXBD_CTRL_DEF 0x0200 /* Defer Indication */#define MPC860_FEC_TXBD_CTRL_HB 0x0100 /* Heartbeat Error */#define MPC860_FEC_TXBD_CTRL_LC 0x0080 /* Late Collision */#define MPC860_FEC_TXBD_CTRL_RL 0x0040 /* Retranmission Limit */#define MPC860_FEC_TXBD_CTRL_UN 0x0002 /* Underrun */#define MPC860_FEC_TXBD_CTRL_CSL 0x0001 /* Carrier Sense Lost *//* FEC buffer descriptor */struct mpc860_fec_bd { m_uint32_t bd_addr; /* Address in external memory */ m_uint16_t ctrl; /* Control Word */ m_uint16_t buf_len; /* Buffer Length */ m_uint32_t bp; /* Buffer Pointer */};/* ======================================================================== */struct mpc860_scc_chan { netio_desc_t *nio; /* General SCC mode register (high and low parts) */ m_uint32_t gsmr_hi,gsmr_lo; /* Protocol-Specific mode register */ m_uint32_t psmr; /* SCC Event and Mask registers */ m_uint16_t scce,sccm; /* TX packet */ u_char tx_pkt[MPC860_SCC_MAX_PKT_SIZE];};/* MPC860 private data */struct mpc860_data { char *name; vm_obj_t vm_obj; struct vdevice dev; struct pci_device *pci_dev; vm_instance_t *vm; /* SIU Interrupt Pending Register and Interrupt Mask Register */ m_uint32_t sipend,simask; /* CPM Interrupt Configuration Register */ m_uint32_t cicr; /* CPM Interrupt Pending Register and Interrupt Mask Register */ m_uint32_t cipr,cimr; /* IDMA status and mask registers */ m_uint8_t idsr[2],idmr[2]; /* Port B Data Register */ m_uint32_t pbdat,pcdat; /* SPI callback for TX data */ mpc860_spi_tx_callback_t spi_tx_callback; void *spi_user_arg; /* SCC channels */ struct mpc860_scc_chan scc_chan[MPC860_SCC_NR_CHAN]; /* FEC (Fast Ethernet Controller) */ m_uint32_t fec_rdes_start,fec_xdes_start; m_uint32_t fec_rdes_current,fec_xdes_current; m_uint32_t fec_rbuf_size; /* FEC Interrupt Event/Mask registers */ m_uint32_t fec_ievent,fec_imask,fec_ivec; m_uint32_t fec_ecntrl; /* FEC NetIO */ netio_desc_t *fec_nio; /* FEC MII registers */ m_uint32_t fec_mii_data; m_uint16_t fec_mii_regs[32]; /* Dual-Port RAM */ m_uint8_t dpram[MPC860_DPRAM_SIZE];};/* Log a MPC message */#define MPC_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)/* ======================================================================== *//* DPRAM access routines */static inline m_uint8_t dpram_r8(struct mpc860_data *d,m_uint16_t offset){ return(d->dpram[offset]);}static inline void dpram_w8(struct mpc860_data *d,m_uint16_t offset, m_uint8_t val){ d->dpram[offset] = val;}static inline m_uint16_t dpram_r16(struct mpc860_data *d,m_uint16_t offset){ m_uint16_t val; val = (m_uint16_t)d->dpram[offset] << 8; val |= d->dpram[offset+1]; return(val);}static inline void dpram_w16(struct mpc860_data *d,m_uint16_t offset, m_uint16_t val){ d->dpram[offset] = val >> 8; d->dpram[offset+1] = val & 0xFF;}static inline m_uint32_t dpram_r32(struct mpc860_data *d,m_uint16_t offset){ m_uint32_t val; val = d->dpram[offset] << 24; val |= d->dpram[offset+1] << 16; val |= d->dpram[offset+2] << 8; val |= d->dpram[offset+3]; return(val);}static inline void dpram_w32(struct mpc860_data *d,m_uint16_t offset, m_uint32_t val){ d->dpram[offset] = val >> 24; d->dpram[offset+1] = val >> 16; d->dpram[offset+2] = val >> 8; d->dpram[offset+3] = val;}/* ======================================================================== *//* Update interrupt status */static void mpc860_update_irq_status(struct mpc860_data *d){ cpu_ppc_t *cpu = CPU_PPC32(d->vm->boot_cpu); cpu->irq_pending = d->sipend & d->simask; cpu->irq_check = cpu->irq_pending;}/* Map level to SIU Interrupt Pending Register bit */static inline u_int mpc860_get_siu_lvl(u_int level){ return(16 + ((7 - level) << 1));}/* Update CPM interrupt status */static void mpc860_update_cpm_int_status(struct mpc860_data *d){ u_int level,siu_bit; level = (d->cicr & MPC860_CICR_IRL_MASK) >> MPC860_CICR_IRL_SHIFT; siu_bit = mpc860_get_siu_lvl(level); if ((d->cipr & d->cimr) && (d->cicr & MPC860_CICR_IEN)) mpc860_set_pending_irq(d,siu_bit); else mpc860_clear_pending_irq(d,siu_bit);}/* ======================================================================== *//* IDMA *//* ======================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -