📄 dev_mpc860.c
字号:
case 0x02: mpc860_fec_mii_read_access(d,phy,reg); break; default: MPC_LOG(d,"FEC: unknown MII opcode %u\n",op); } /* MII access completed */ d->fec_ievent |= MPC860_IEVENT_MII; mpc860_fec_update_irq_status(d);}/* * FEC register access (0xE00 to 0xF84). */static int dev_mpc860_fec_access(struct mpc860_data *d,m_uint32_t offset, u_int op_size,u_int op_type,m_uint64_t *data){ switch(offset) { /* R_DES_START: Beginning of RxBD ring */ case 0xE10: if (op_type == MTS_READ) *data = d->fec_rdes_start; else d->fec_rdes_start = *data & 0xFFFFFFFC; break; /* X_DES_START: Beginning of TxBD ring */ case 0xE14: if (op_type == MTS_READ) *data = d->fec_xdes_start; else d->fec_xdes_start = *data & 0xFFFFFFFC; break; /* R_BUFF_SIZE: Receive Buffer Size */ case 0xE18: if (op_type == MTS_READ) *data = d->fec_rbuf_size; else d->fec_rbuf_size = *data & 0x7F0; break; /* ECNTRL */ case 0xE40: if (op_type == MTS_READ) { *data = d->fec_ecntrl; } else { if (*data & MPC860_ECNTRL_RESET) d->fec_ecntrl = 0; else { if (!(*data & MPC860_ECNTRL_ETHER_EN)) { d->fec_xdes_current = d->fec_xdes_start; d->fec_rdes_current = d->fec_rdes_start; } d->fec_ecntrl = *data; } } break; /* IEVENT: Interrupt Event Register */ case 0xE44: if (op_type == MTS_READ) { *data = d->fec_ievent; } else { d->fec_ievent &= ~(*data); mpc860_fec_update_irq_status(d); } break; /* IMASK: Interrupt Mask Register */ case 0xE48: if (op_type == MTS_READ) { *data = d->fec_imask; } else { d->fec_imask = *data; mpc860_fec_update_irq_status(d); } break; /* IVEC: Interrupt Vector Register */ case 0xE4C: if (op_type == MTS_READ) *data = d->fec_ivec; else d->fec_ivec = *data; break; /* X_DES_ACTIVE: TxBD Active Register */ case 0xE54: mpc860_fec_handle_tx_ring(d); //printf("x_des_active set\n"); break; /* MII_DATA */ case 0xE80: if (op_type == MTS_READ) { *data = d->fec_mii_data; } else { d->fec_mii_data = *data; mpc860_fec_mii_access(d); } break; } return(0);}/* Set NIO for the Fast Ethernet Controller */int mpc860_fec_set_nio(struct mpc860_data *d,netio_desc_t *nio){ /* check that a NIO is not already bound */ if (!d || (d->fec_nio != NULL)) return(-1); d->fec_nio = nio; netio_rxl_add(nio,(netio_rx_handler_t)mpc860_fec_handle_rx_pkt,d,NULL); return(0);}/* Unset NIO of the Fast Ethernet Controller */int mpc860_fec_unset_nio(struct mpc860_data *d){ if (!d) return(-1); if (d->fec_nio != NULL) { netio_rxl_remove(d->fec_nio); d->fec_nio = NULL; } return(0);}/* ======================================================================== */#define MPC860_CP_FOP(chan,op) (((chan) << 4) + (op))/* Execute a command sent through CP Command Register (CPCR) */static void mpc860_exec_cpcr(struct mpc860_data *d,m_uint32_t cpcr){ u_int channel,opcode,fop; channel = (cpcr >> 4) & 0x0F; opcode = (cpcr >> 8) & 0x0F; fop = MPC860_CP_FOP(channel,opcode); switch(fop) { /* SPI - Init RX and TX params */ case MPC860_CP_FOP(MPC860_CHAN_SPI_IDMA2_RT,0): mpc860_spi_init_rx_tx_params(d); break; /* SPI - Init RX params */ case MPC860_CP_FOP(MPC860_CHAN_SPI_IDMA2_RT,1): mpc860_spi_init_rx_params(d); break; /* SPI - Init TX params */ case MPC860_CP_FOP(MPC860_CHAN_SPI_IDMA2_RT,2): mpc860_spi_init_tx_params(d); break; /* SCC1 - Init RX and TX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC1,0): mpc860_scc_init_rx_tx_params(d,0); break; /* SCC1 - Init RX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC1,1): mpc860_scc_init_rx_params(d,0); break; /* SCC1 - Init TX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC1,2): mpc860_scc_init_tx_params(d,0); break; /* SCC2 - Init RX and TX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC2,0): mpc860_scc_init_rx_tx_params(d,1); break; /* SCC2 - Init RX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC2,1): mpc860_scc_init_rx_params(d,1); break; /* SCC2 - Init TX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC2,2): mpc860_scc_init_tx_params(d,1); break; /* SCC3 - Init RX and TX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC3,0): mpc860_scc_init_rx_tx_params(d,2); break; /* SCC3 - Init RX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC3,1): mpc860_scc_init_rx_params(d,2); break; /* SCC3 - Init TX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC3,2): mpc860_scc_init_tx_params(d,2); break; /* SCC4 - Init RX and TX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC4,0): mpc860_scc_init_rx_tx_params(d,3); break; /* SCC4 - Init RX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC4,1): mpc860_scc_init_rx_params(d,3); break; /* SCC4 - Init TX params */ case MPC860_CP_FOP(MPC860_CHAN_SCC4,2): mpc860_scc_init_tx_params(d,3); break; default: MPC_LOG(d,"CPCR: unknown cmd: channel=0x%4.4x, opcode=0x%4.4x\n", channel,opcode); }}/* * dev_mpc860_access() */void *dev_mpc860_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset, u_int op_size,u_int op_type,m_uint64_t *data){ struct mpc860_data *d = dev->priv_data; if (op_type == MTS_READ) *data = 0x0;#if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,d->name, "read from offset 0x%x, pc=0x%llx (size=%u)\n", offset,cpu_get_pc(cpu),op_size); } else { cpu_log(cpu,d->name, "write to offset 0x%x, value=0x%llx, pc=0x%llx (size=%u)\n", offset,*data,cpu_get_pc(cpu),op_size); }#endif /* Handle dual-port RAM access */ if ((offset >= MPC860_DPRAM_OFFSET) && (offset < MPC860_DPRAM_END)) return(d->dpram + (offset - MPC860_DPRAM_OFFSET)); /* Handle SCC channels */ if ((offset >= MPC860_REG_SCC_BASE) && (offset < (MPC860_REG_SCC_BASE + (4 * 0x20)))) { dev_mpc860_scc_access(d,offset,op_size,op_type,data); return NULL; } /* Handle Fast Ethernet Controller (FEC) registers */ if ((offset >= MPC860_REG_FEC_BASE) && (offset <= MPC860_REG_FEC_END)) { dev_mpc860_fec_access(d,offset,op_size,op_type,data); return NULL; } switch(offset) { /* SWSR - Software Service Register (Watchdog) */ case MPC860_REG_SWSR: break; /* SIU Interrupt Pending Register */ case MPC860_REG_SIPEND: if (op_type == MTS_READ) *data = d->sipend; break; /* SIU Interrupt Mask Register */ case MPC860_REG_SIMASK: if (op_type == MTS_READ) { *data = d->simask; } else { d->simask = *data; mpc860_update_irq_status(d); } break; /* * Cisco 2600: * Bit 30: 0=NM in slot 1 */ case MPC860_REG_PIPR: if (op_type == MTS_READ) *data = 0x3F00F600; break; /* PISCR - Periodic Interrupt Status and Control Register */ case MPC860_REG_PISCR: if (op_type == MTS_WRITE) { if (*data & 0x80) { d->sipend &= ~0x40000000; mpc860_update_irq_status(d); } } break; case MPC860_REG_TBSCR: if (op_type == MTS_READ) *data = 0x45; break; /* IDMA1 Status and Mask Registers */ case MPC860_REG_IDSR1: if (op_type == MTS_READ) { *data = d->idsr[0]; } else { d->idsr[0] &= ~(*data); } break; case MPC860_REG_IDMR1: if (op_type == MTS_READ) *data = d->idmr[0]; else d->idmr[0] = *data; break; /* IDMA2 Status and Mask Registers */ case MPC860_REG_IDSR2: if (op_type == MTS_READ) *data = d->idsr[1]; else d->idsr[1] &= ~(*data); break; case MPC860_REG_IDMR2: if (op_type == MTS_READ) *data = d->idmr[1]; else d->idmr[1] = *data; break; /* CICR - CPM Interrupt Configuration Register */ case MPC860_REG_CICR: if (op_type == MTS_READ) *data = d->cicr; else d->cicr = *data; break; /* CIPR - CPM Interrupt Pending Register */ case MPC860_REG_CIPR: if (op_type == MTS_READ) *data = d->cipr; else { d->cipr &= ~(*data); mpc860_update_cpm_int_status(d); } break; /* CIMR - CPM Interrupt Mask Register */ case MPC860_REG_CIMR: if (op_type == MTS_READ) *data = d->cimr; else { d->cimr = *data; mpc860_update_cpm_int_status(d); } break; /* PCSO - Port C Special Options Register */ case MPC860_REG_PCSO: if (op_type == MTS_WRITE) { if (*data & 0x01) {#if DEBUG_IDMA MPC_LOG(d,"activating IDMA0\n");#endif mpc860_idma_start_channel(d,0); } } break; /* PCDAT - Port C Data Register */ case MPC860_REG_PCDAT: if (op_type == MTS_WRITE) d->pcdat = *data; else *data = d->pcdat; break; /* PBDAT - Port B Data Register */ case MPC860_REG_PBDAT: if (op_type == MTS_WRITE) d->pbdat = *data; else *data = d->pbdat; break; /* CPCR - CP Command Register */ case MPC860_REG_CPCR: if (op_type == MTS_WRITE) mpc860_exec_cpcr(d,(m_uint32_t)(*data)); break; /* SPCOM - SPI Command Register */ case MPC860_REG_SPCOM: if ((op_type == MTS_WRITE) && (*data & MPC860_SPCOM_STR)) mpc860_spi_start_tx(d); 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_get_pc(cpu),op_size); } else { cpu_log(cpu,d->name, "write to addr 0x%x, value=0x%llx, pc=0x%llx (size=%u)\n", offset,*data,cpu_get_pc(cpu),op_size); }#endif } return NULL;}/* Set IRQ pending status */void mpc860_set_pending_irq(struct mpc860_data *d,m_uint32_t val){ d->sipend |= 1 << val; mpc860_update_irq_status(d);}/* Clear a pending IRQ */void mpc860_clear_pending_irq(struct mpc860_data *d,m_uint32_t val){ d->sipend &= ~(1 << val); mpc860_update_irq_status(d);}/* Shutdown the MPC860 device */void dev_mpc860_shutdown(vm_instance_t *vm,struct mpc860_data *d){ if (d != NULL) { /* Remove the device */ dev_remove(vm,&d->dev); /* Free the structure itself */ free(d); }}/* Create the MPC860 device */int dev_mpc860_init(vm_instance_t *vm,char *name, m_uint64_t paddr,m_uint32_t len){ struct mpc860_data *d; if (!(d = malloc(sizeof(*d)))) { fprintf(stderr,"mpc860: unable to create device data.\n"); return(-1); } memset(d,0,sizeof(*d)); d->name = name; d->vm = vm; vm_object_init(&d->vm_obj); d->vm_obj.name = name; d->vm_obj.data = d; d->vm_obj.shutdown = (vm_shutdown_t)dev_mpc860_shutdown; dev_init(&d->dev); d->dev.name = name; d->dev.priv_data = d; d->dev.phys_addr = paddr; d->dev.phys_len = len; d->dev.handler = dev_mpc860_access; /* Set the default SPI base address */ dpram_w16(d,MPC860_SPI_BASE_ADDR,MPC860_SPI_BASE); /* Map this device to the VM */ vm_bind_device(vm,&d->dev); vm_object_add(vm,&d->vm_obj); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -