📄 dev_c7200.c
字号:
{ c7200_t *router = VM_C7200(vm); int i; /* Stop all CPUs */ if (vm->cpu_group != NULL) { vm_stop(vm); if (cpu_group_sync_state(vm->cpu_group) == -1) { vm_error(vm,"unable to sync with system CPUs.\n"); return(FALSE); } } /* Remove NIO bindings */ for(i=0;i<vm->nr_slots;i++) vm_slot_remove_all_nio_bindings(vm,i); /* Free specific HW resources */ c7200_free_hw_ressources(router); /* Free EEPROMs */ cisco_eeprom_free(&router->cpu_eeprom); cisco_eeprom_free(&router->mp_eeprom); cisco_eeprom_free(&router->pem_eeprom); /* Free all resources used by VM */ vm_free(vm); /* Free the router structure */ free(router); return(TRUE);}/* Save configuration of a C7200 instance */static void c7200_save_config(vm_instance_t *vm,FILE *fd){ c7200_t *router = VM_C7200(vm); fprintf(fd,"c7200 set_npe %s %s\n",vm->name,router->npe_driver->npe_type); fprintf(fd,"c7200 set_midplane %s %s\n\n",vm->name,router->midplane_type);}/* Set EEPROM for the specified slot */int c7200_set_slot_eeprom(c7200_t *router,u_int slot, struct cisco_eeprom *eeprom){ if (slot >= C7200_MAX_PA_BAYS) return(-1); switch(slot) { /* Group 1: bays 0, 1, 3, 4 */ case 0: router->pa_eeprom_g1.eeprom[0] = eeprom; break; case 1: router->pa_eeprom_g1.eeprom[1] = eeprom; break; case 3: router->pa_eeprom_g1.eeprom[2] = eeprom; break; case 4: router->pa_eeprom_g1.eeprom[3] = eeprom; break; /* Group 2: bays 2, 5, 6 */ case 2: router->pa_eeprom_g2.eeprom[0] = eeprom; break; case 5: router->pa_eeprom_g2.eeprom[1] = eeprom; break; case 6: router->pa_eeprom_g2.eeprom[2] = eeprom; break; } return(0);}/* Get slot/port corresponding to specified network IRQ */static inline void c7200_net_irq_get_slot_port(u_int irq,u_int *slot,u_int *port){ irq -= C7200_NETIO_IRQ_BASE; *port = irq & C7200_NETIO_IRQ_PORT_MASK; *slot = irq >> C7200_NETIO_IRQ_PORT_BITS;}/* Get network IRQ for specified slot/port */u_int c7200_net_irq_for_slot_port(u_int slot,u_int port){ u_int irq; irq = (slot << C7200_NETIO_IRQ_PORT_BITS) + port; irq += C7200_NETIO_IRQ_BASE; return(irq);}/* Set NPE eeprom definition */static int c7200_npe_set_eeprom(c7200_t *router){ const struct cisco_eeprom *eeprom; if (!(eeprom = c7200_get_cpu_eeprom(router->npe_driver->npe_type))) { vm_error(router->vm,"unknown NPE \"%s\" (internal error)!\n", router->npe_driver->npe_type); return(-1); } if (cisco_eeprom_copy(&router->cpu_eeprom,eeprom) == -1) { vm_error(router->vm,"unable to set NPE EEPROM.\n"); return(-1); } return(0);}/* Set PEM eeprom definition */static int c7200_pem_set_eeprom(c7200_t *router){ const struct cisco_eeprom *eeprom; if (!(eeprom = c7200_get_pem_eeprom(router->npe_driver->npe_type))) { vm_error(router->vm,"no PEM EEPROM found for NPE type \"%s\"!\n", router->npe_driver->npe_type); return(-1); } if (cisco_eeprom_copy(&router->pem_eeprom,eeprom) == -1) { vm_error(router->vm,"unable to set PEM EEPROM.\n"); return(-1); } return(0);}/* Get an NPE driver */struct c7200_npe_driver *c7200_npe_get_driver(char *npe_type){ int i; for(i=0;npe_drivers[i].npe_type;i++) if (!strcmp(npe_drivers[i].npe_type,npe_type)) return(&npe_drivers[i]); return NULL;}/* Set the NPE type */int c7200_npe_set_type(c7200_t *router,char *npe_type){ struct c7200_npe_driver *driver; if (router->vm->status == VM_STATUS_RUNNING) { vm_error(router->vm,"unable to change NPE type when online.\n"); return(-1); } if (!(driver = c7200_npe_get_driver(npe_type))) { vm_error(router->vm,"unknown NPE type '%s'.\n",npe_type); return(-1); } router->npe_driver = driver; if (c7200_npe_set_eeprom(router) == -1) { vm_error(router->vm,"unable to find NPE '%s' EEPROM!\n", router->npe_driver->npe_type); return(-1); }#if 1 /* FIXME - for a later release */ /* Use a C7200-IO-FE by default in slot 0 if an I/O card is required */ if (driver->iocard_required) { vm_slot_add_binding(router->vm,"C7200-IO-FE",0,0); vm_slot_set_flag(router->vm,0,0,CISCO_CARD_FLAG_OVERRIDE); }#endif return(0);}/* Show the list of available NPE drivers */static void c7200_npe_show_drivers(void){ int i; printf("Available C7200 NPE drivers:\n"); for(i=0;npe_drivers[i].npe_type;i++) { printf(" * %s %s\n", npe_drivers[i].npe_type, !npe_drivers[i].supported ? "(NOT WORKING)" : ""); } printf("\n");}/* Set Midplane type */int c7200_midplane_set_type(c7200_t *router,char *midplane_type){ const struct cisco_eeprom *eeprom; m_uint8_t version; if (router->vm->status == VM_STATUS_RUNNING) { vm_error(router->vm,"unable to change Midplane type when online.\n"); return(-1); } /* Set EEPROM */ if (!(eeprom = c7200_get_midplane_eeprom(midplane_type))) { vm_error(router->vm,"unknown Midplane \"%s\"!\n",midplane_type); return(-1); } /* Copy the midplane EEPROM */ if (cisco_eeprom_copy(&router->mp_eeprom,eeprom) == -1) { vm_error(router->vm,"unable to set midplane EEPROM.\n"); return(-1); } /* Set the chassis base MAC address */ c7200_burn_mac_addr(router,&router->mac_addr); /* Get the midplane version */ cisco_eeprom_get_byte(&router->mp_eeprom,2,&version); router->midplane_version = version; router->midplane_type = eeprom->name; return(0);}/* Set chassis MAC address */int c7200_midplane_set_mac_addr(c7200_t *router,char *mac_addr){ if (parse_mac_addr(&router->mac_addr,mac_addr) == -1) { vm_error(router->vm,"unable to parse MAC address '%s'.\n",mac_addr); return(-1); } /* Set the chassis base MAC address */ c7200_burn_mac_addr(router,&router->mac_addr); return(0);}/* Create the main PCI bus for a GT64010 based system */static int c7200_init_gt64010(c7200_t *router){ vm_instance_t *vm = router->vm; if (!(vm->pci_bus[0] = pci_bus_create("MB0/MB1/MB2",0))) { vm_error(vm,"unable to create PCI data.\n"); return(-1); } return(dev_gt64010_init(vm,"gt64010",C7200_GT64K_ADDR,0x1000, C7200_GT64K_IRQ));}/* Create the two main PCI busses for a GT64120 based system */static int c7200_init_gt64120(c7200_t *router){ vm_instance_t *vm = router->vm; vm->pci_bus[0] = pci_bus_create("MB0/MB1",0); vm->pci_bus[1] = pci_bus_create("MB2",0); if (!vm->pci_bus[0] || !vm->pci_bus[1]) { vm_error(vm,"unable to create PCI data.\n"); return(-1); } return(dev_gt64120_init(vm,"gt64120",C7200_GT64K_ADDR,0x1000, C7200_GT64K_IRQ));}/* Create the two main PCI busses for a dual GT64120 system */static int c7200_init_dual_gt64120(c7200_t *router){ vm_instance_t *vm = router->vm; vm->pci_bus[0] = pci_bus_create("MB0/MB1",0); vm->pci_bus[1] = pci_bus_create("MB2",0); if (!vm->pci_bus[0] || !vm->pci_bus[1]) { vm_error(vm,"unable to create PCI data.\n",vm->name); return(-1); } /* Initialize the first GT64120 at 0x14000000 */ if (dev_gt64120_init(vm,"gt64120(1)",C7200_GT64K_ADDR,0x1000, C7200_GT64K_IRQ) == -1) return(-1); /* Initialize the second GT64120 at 0x15000000 */ if (dev_gt64120_init(vm,"gt64120(2)",C7200_GT64K_SEC_ADDR,0x1000, C7200_GT64K_IRQ) == -1) return(-1); return(0);}/* Create the two main PCI busses for a MV64460 based system */static int c7200_init_mv64460(c7200_t *router){ vm_instance_t *vm = router->vm; vm->pci_bus[0] = pci_bus_create("MB0/MB1",3); vm->pci_bus[1] = pci_bus_create("MB2",0); if (!vm->pci_bus[0] || !vm->pci_bus[1]) { vm_error(vm,"unable to create PCI data.\n"); return(-1); } return(dev_mv64460_init(vm,"mv64460",C7200_G2_MV64460_ADDR,0x10000));}/* Create the PA PCI busses */static int c7200_pa_create_pci_busses(c7200_t *router){ vm_instance_t *vm = router->vm; char bus_name[128]; int i; for(i=1;i<C7200_MAX_PA_BAYS;i++) { snprintf(bus_name,sizeof(bus_name),"PA Slot %d",i); vm->pci_bus_pool[i] = pci_bus_create(bus_name,-1); if (!vm->pci_bus_pool[i]) return(-1); } return(0);}/* Create a PA bridge, depending on the midplane */static int c7200_pa_init_pci_bridge(c7200_t *router,u_int pa_bay, struct pci_bus *pci_bus,int pci_device){ struct pci_bus *pa_bus; pa_bus = router->vm->slots_pci_bus[pa_bay]; switch(router->midplane_version) { case 0: case 1: dev_dec21050_init(pci_bus,pci_device,pa_bus); break; default: dev_dec21150_init(pci_bus,pci_device,pa_bus); } return(0);}/* * Hidden "I/O" PCI bridge hack for PCMCIA controller. * * On NPE-175, NPE-225, NPE-300 and NPE-400, PCMCIA controller is * identified on PCI as Bus=2,Device=16. On NPE-G1, this is Bus=17,Device=16. * * However, I don't understand how the bridging between PCI bus 1 and 2 * is done (16 and 17 on NPE-G1). * * Maybe I'm missing something about PCI-to-PCI bridge mechanism, or there * is a special hidden device that does the job silently (it should be * visible on the PCI bus...) * * BTW, it works. */static int c7200_create_io_pci_bridge(c7200_t *router,struct pci_bus *parent_bus){ vm_instance_t *vm = router->vm; /* Create the PCI bus where the PCMCIA controller will seat */ if (!(vm->pci_bus_pool[16] = pci_bus_create("I/O secondary bus",-1))) return(-1); /* Create the hidden bridge with "special" handling... */ if (!(router->io_pci_bridge = pci_bridge_add(parent_bus))) return(-1); router->io_pci_bridge->skip_bus_check = TRUE; pci_bridge_map_bus(router->io_pci_bridge,vm->pci_bus_pool[16]); router->pcmcia_bus = vm->pci_bus_pool[16]; return(0);}/* Initialize an NPE-100 board */int c7200_init_npe100(c7200_t *router){ vm_instance_t *vm = router->vm; int i; /* Set the processor type: R4600 */ mips64_set_prid(CPU_MIPS64(vm->boot_cpu),MIPS_PRID_R4600); /* Initialize the Galileo GT-64010 system controller */ if (c7200_init_gt64010(router) == -1) return(-1); /* PCMCIA controller is on bus 0 */ router->pcmcia_bus = vm->pci_bus[0]; /* Initialize the PA PCI busses */ if (c7200_pa_create_pci_busses(router) == -1) return(-1); /* Create PCI busses for PA Bays 1,3,5 and PA Bays 2,4,6 */ vm->pci_bus_pool[24] = pci_bus_create("PA Slots 1,3,5",-1); vm->pci_bus_pool[25] = pci_bus_create("PA Slots 2,4,6",-1); /* PCI bridges (MB0/MB1, MB0/MB2) */ dev_dec21050_init(vm->pci_bus[0],1,NULL); dev_dec21050_init(vm->pci_bus[0],2,vm->pci_bus_pool[24]); dev_dec21050_init(vm->pci_bus[0],3,NULL); dev_dec21050_init(vm->pci_bus[0],4,vm->pci_bus_pool[25]); /* Map the PA PCI busses */ vm->slots_pci_bus[0] = vm->pci_bus[0]; for(i=1;i<C7200_MAX_PA_BAYS;i++) vm->slots_pci_bus[i] = vm->pci_bus_pool[i];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -