📄 dev_c7200_bri.c
字号:
return(TRUE);}/* Scan a channel TX ring */static inline int m32_tx_scan(struct m32_data *d,u_int chan_id){ struct m32_channel *chan = &d->channels[chan_id]; m_uint8_t pkt[M32_MAX_PKT_SIZE]; struct m32_tx_desc txd; m_uint32_t pkt_len; if (!chan->tx_current) return(FALSE); switch(chan->poll_mode) { case 0: m32_set_cfgw(d,M32_OFFSET_CTDA+(chan_id*4),chan->tx_current); /* Try to transmit data */ if (!m32_tx_acquire(d,chan->tx_current,&txd)) return(FALSE); printf("M32: TX scanner for channel %u (tx_current=0x%8.8x)\n", chan_id,chan->tx_current); printf("M32: params=0x%8.8x, next=0x%8.8x.\n",txd.params,txd.ntdp); /* The descriptor has been acquired */ pkt_len = (txd.params & M32_TXDESC_NO_MASK) >> M32_TXDESC_NO_SHIFT; physmem_copy_from_vm(d->vm,pkt,txd.tdp,pkt_len); printf("M32: data_ptr=0x%x, len=%u\n",txd.tdp,pkt_len); mem_dump(stdout,pkt,pkt_len); /* Poll the next descriptor (wait for HOLD bit to be reset */ chan->poll_mode = 1; if (txd.params & M32_TXDESC_FE) { m32_post_interrupt(d,M32_II_FI | chan_id); vm_set_irq(d->vm,2); } break; case 1: if (!m32_tx_acquire_next(d,&chan->tx_current)) return(FALSE); printf("M32: branching on next descriptor 0x%x\n",chan->tx_current); chan->poll_mode = 0; break; } return(TRUE);}/* Scan the all channel TX rings */static void m32_tx_scan_all_channels(struct m32_data *d){ u_int i; for(i=0;i<M32_NR_CHANNELS;i++) m32_tx_scan(d,i);}/* * Handle an action request. * * IN, ICO and RES bits are mutually exclusive. */static int m32_action_req(struct m32_data *d,m_uint32_t action){ u_int chan_id; /* Define a new Interrupt Queue */ if (action & M32_AS_IA) { d->iq_base_addr = d->iq_cur_addr = m32_get_cfgw(d,4); d->iq_size = ((m32_get_cfgw(d,8) & 0xFF) + 1) * 16 * sizeof(m_uint32_t); } /* Initialization Procedure */ if (action & M32_AS_IN) { /* Fetch all timeslots assignments */ m32_fetch_all_ts(d); /* Fetch specification of the specified channel */ chan_id = (action & M32_AS_CHAN_MASK) >> M32_AS_CHAN_SHIFT; m32_fetch_chan_spec(d,chan_id); /* Generate acknowledge */ if (!(action & M32_AS_IM)) m32_post_interrupt(d,M32_II_ARACK); } /* Initialize Channel Only */ if (action & M32_AS_ICO) { /* Fetch specification of the specified channel */ chan_id = (action & M32_AS_CHAN_MASK) >> M32_AS_CHAN_SHIFT; m32_fetch_chan_spec(d,chan_id); /* Generate acknowledge */ if (!(action & M32_AS_IM)) m32_post_interrupt(d,M32_II_ARACK); } /* Reset */ if (action & M32_AS_RES) { /* Fetch all timeslots assignments */ m32_fetch_all_ts(d); /* Fetch all channel specifications */ m32_fetch_all_chan_spec(d); /* Generate acknowledge */ if (!(action & M32_AS_IM)) m32_post_interrupt(d,M32_II_ARACK); } return(0);}/* Munich32 general access function */static void *m32_gen_access(struct m32_data *d,cpu_mips_t *cpu, m_uint32_t offset,u_int op_size,u_int op_type, m_uint64_t *data){ u_int p; switch(offset) { /* Action Specification */ case 0x0: if (op_type == MTS_WRITE) m32_action_req(d,*data); return NULL; /* Configuration memory */ default: switch(op_size) { case 4: if (op_type == MTS_READ) *data = m32_get_cfgw(d,offset); else m32_set_cfgw(d,offset,*data); break; case 1: if (op_type == MTS_READ) { *data = m32_get_cfgw(d,offset & ~0x03); *data >>= (24 - ((offset & 0x03) << 3)); *data &= 0xFF; } else { printf("UNSUPPORTED(1)!!!!\n"); } break; case 2: if (op_type == MTS_READ) { *data = m32_get_cfgw(d,offset & ~0x03); *data >>= (16 - ((offset & 0x03) << 3)); *data &= 0xFFFF; } else { printf("UNSUPPORTED(2)!!!!\n"); } break; case 8: if (op_type == MTS_READ) { *data = (m_uint64_t)m32_get_cfgw(d,offset) << 32; *data |= m32_get_cfgw(d,offset+4); } else { printf("UNSUPPORTED(8)!!!!\n"); } break; default: printf("UNSUPPORTED (size=%u)!!!\n",op_size); } } return NULL;}/* * pa_4b_access() */void *pa_4b_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_4b_data *d = dev->priv_data; static m_uint32_t test1,test2,test3; if (op_type == MTS_READ) *data = 0xFFFFFFFF;#if DEBUG_ACCESS if (offset >= MUNICH32_MEM_SIZE) { if (op_type == MTS_READ) { cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx " "(op_size=%u)\n",offset,cpu->pc,op_size); } else { cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, " "val = 0x%llx (op_size=%u)\n",offset,cpu->pc,*data,op_size); } }#endif /* Specific cases */ switch(offset) { case 0x40008: if (op_type == MTS_READ) *data = 0xFF; break; case 0x40030: if (op_type == MTS_READ) *data = 0xFF; break; case 0x40000: if (op_type == MTS_READ) *data = 0xFFFF; break; case 0x40020: if (op_type == MTS_READ) *data = 0xFFFFFFFF; //test2; else test2 = *data; break; case 0x40021: if (op_type == MTS_READ) *data = 0xFF; //test3; else test3 = *data; break; case 0x40023: if (op_type == MTS_READ) *data = 0xFF; break; case 0x40040: if (op_type == MTS_READ) *data = 0x04; break; /* Channels enabled ? */ case 0x40044: if (op_type == MTS_READ) *data = 0xFF; /* 0x02 */ break; /* SID */ case 0x40050: if (op_type == MTS_WRITE) { test1 = *data; } else { switch(test1) { case TP3420_SID_PUP: *data = TP3420_SR_AI; vm_set_irq(d->vm,C7200_PA_MGMT_IRQ); break; case TP3420_SID_ENST: *data = 0xB0; break; default: *data = 0x03; break; } } break; default: if (offset < MUNICH32_MEM_SIZE) return(m32_gen_access(&d->m32_data,cpu,offset - d->m32_offset, op_size,op_type,data)); } return NULL;}/* * pci_munich32_read() */static m_uint32_t pci_munich32_read(cpu_mips_t *cpu,struct pci_device *dev, int reg){ struct pa_4b_data *d = dev->priv_data;#if DEBUG_ACCESS BRI_LOG(d,"read PCI register 0x%x\n",reg);#endif switch(reg) { case PCI_REG_BAR0: return(d->dev->phys_addr); default: return(0); }}/* * pci_munich32_write() */static void pci_munich32_write(cpu_mips_t *cpu,struct pci_device *dev, int reg,m_uint32_t value){ struct pa_4b_data *d = dev->priv_data;#if DEBUG_ACCESS BRI_LOG(d,"write 0x%x to PCI register 0x%x\n",value,reg);#endif switch(reg) { case PCI_REG_BAR0: vm_map_device(cpu->vm,d->dev,(m_uint64_t)value); BRI_LOG(d,"registers are mapped at 0x%x\n",value); break; }}/* * dev_c7200_bri_init() * * Add a PA-4B/PA-8B port adapter into specified slot. */int dev_c7200_pa_bri_init(c7200_t *router,char *name,u_int pa_bay){ struct pci_device *pci_dev; struct pa_4b_data *d; struct vdevice *dev; /* Allocate the private data structure for PA-4B chip */ if (!(d = malloc(sizeof(*d)))) { fprintf(stderr,"%s (PA-4B): out of memory\n",name); return(-1); } memset(d,0,sizeof(*d)); d->m32_offset = 0x08; d->m32_data.vm = router->vm; /* Set the EEPROM */ c7200_pa_set_eeprom(router,pa_bay,cisco_eeprom_find_pa("PA-4B")); /* Add as PCI device PA-4B */ pci_dev = pci_dev_add(router->pa_bay[pa_bay].pci_map,name, BRI_PCI_VENDOR_ID,BRI_PCI_PRODUCT_ID, 0,0,C7200_NETIO_IRQ,d, NULL,pci_munich32_read,pci_munich32_write); if (!pci_dev) { fprintf(stderr,"%s (PA-4B): unable to create PCI device.\n",name); return(-1); } /* Create the PA-4B structure */ d->name = name; d->pci_dev = pci_dev; d->vm = router->vm; /* Create the device itself */ if (!(dev = dev_create(name))) { fprintf(stderr,"%s (PA-4B): unable to create device.\n",name); return(-1); } dev->phys_len = 0x800000; dev->handler = pa_4b_access; /* Store device info */ dev->priv_data = d; d->dev = dev; /* Map this device to the VM */ vm_bind_device(router->vm,dev); /* Store device info into the router structure */ return(c7200_pa_set_drvinfo(router,pa_bay,d));}/* Remove a PA-4B from the specified slot */int dev_c7200_pa_bri_shutdown(c7200_t *router,u_int pa_bay){ struct c7200_pa_bay *bay; struct pa_4b_data *d; if (!(bay = c7200_pa_get_info(router,pa_bay))) return(-1); d = bay->drv_info; /* Remove the PA EEPROM */ c7200_pa_unset_eeprom(router,pa_bay); /* Remove the PCI device */ pci_dev_remove(d->pci_dev); /* Remove the device from the CPU address space */ vm_unbind_device(router->vm,d->dev); cpu_group_rebuild_mts(router->vm->cpu_group); /* Free the device structure itself */ free(d->dev); free(d); return(0);}/* Bind a Network IO descriptor to a specific port */int dev_c7200_pa_bri_set_nio(c7200_t *router,u_int pa_bay,u_int port_id, netio_desc_t *nio){ struct pa_4b_data *d; if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay))) return(-1); if (d->nio != NULL) return(-1); d->nio = nio; /* TEST */ d->m32_data.tx_tid = ptask_add((ptask_callback)m32_tx_scan_all_channels,&d->m32_data,NULL); //netio_rxl_add(nio,(netio_rx_handler_t)dev_pa_4b_handle_rxring,d,NULL); return(0);}/* Bind a Network IO descriptor to a specific port */int dev_c7200_pa_bri_unset_nio(c7200_t *router,u_int pa_bay,u_int port_id){ struct pa_4b_data *d; if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay))) return(-1); if (d->nio) { /* TEST */ ptask_remove(d->m32_data.tx_tid); //netio_rxl_remove(d->nio); d->nio = NULL; } return(0);}/* PA-4B driver */struct c7200_pa_driver dev_c7200_pa_4b_driver = { "PA-4B", 0, dev_c7200_pa_bri_init, dev_c7200_pa_bri_shutdown, dev_c7200_pa_bri_set_nio, dev_c7200_pa_bri_unset_nio, NULL,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -