--- upstream/dynamips-0.2.6-RC5/dev_pa_a1.c 2007/10/06 16:09:07 6 +++ trunk/dev_pa_a1.c 2007/10/06 16:45:40 12 @@ -1,5 +1,5 @@ /* - * Cisco C7200 (Predator) Simulation Platform. + * Cisco router simulation platform. * Copyright (C) 2005,2006 Christophe Fillot. All rights reserved. * * PA-A1 ATM interface based on TI1570 and PLX 9060-ES. @@ -35,7 +35,8 @@ #include "crc.h" #include "atm.h" -#include "mips64.h" +#include "cpu.h" +#include "vm.h" #include "dynamips.h" #include "memory.h" #include "device.h" @@ -284,6 +285,9 @@ struct pa_a1_data { char *name; + /* IRQ clearing counter */ + u_int irq_clear_count; + /* Control Memory pointer */ m_uint32_t *ctrl_mem_ptr; @@ -335,10 +339,20 @@ /* Reset the TI1570 (forward declaration) */ static void ti1570_reset(struct pa_a1_data *d,int clear_ctrl_mem); +/* Update the interrupt status */ +static inline void dev_pa_a1_update_irq_status(struct pa_a1_data *d) +{ + if (d->iregs[TI1570_REG_STATUS] & d->iregs[TI1570_REG_IMASK]) { + pci_dev_trigger_irq(d->vm,d->pci_dev_ti); + } else { + pci_dev_clear_irq(d->vm,d->pci_dev_ti); + } +} + /* * dev_pa_a1_access() */ -void *dev_pa_a1_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, +void *dev_pa_a1_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 pa_a1_data *d = dev->priv_data; @@ -349,15 +363,30 @@ #if DEBUG_ACCESS if (op_type == MTS_READ) { cpu_log(cpu,"TI1570","read access to offset = 0x%x, pc = 0x%llx\n", - offset,cpu->pc); + offset,cpu_get_pc(cpu)); } else { cpu_log(cpu,"TI1570","write access to vaddr = 0x%x, pc = 0x%llx, " - "val = 0x%llx\n",offset,cpu->pc,*data); + "val = 0x%llx\n",offset,cpu_get_pc(cpu),*data); } #endif /* Specific cases */ switch(offset) { + /* Status register */ + case 0x3204: + if (op_type == MTS_READ) { + *data = d->iregs[TI1570_REG_STATUS]; + + if (++d->irq_clear_count == 2) { + d->iregs[TI1570_REG_STATUS] &= ~0x3FF; + d->irq_clear_count = 0; + } + + dev_pa_a1_update_irq_status(d); + } + break; + + /* Software Reset register */ case 0x3238: TI1570_LOG(d,"reset issued.\n"); ti1570_reset(d,FALSE); @@ -384,10 +413,10 @@ #if DEBUG_UNKNOWN if (op_type == MTS_READ) { cpu_log(cpu,d->name,"read from unknown addr 0x%x, pc=0x%llx (size=%u)\n", - offset,cpu->pc,op_size); + offset,cpu_get_pc(cpu),op_size); } else { cpu_log(cpu,d->name,"write to unknown addr 0x%x, value=0x%llx, " - "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size); + "pc=0x%llx (size=%u)\n",offset,*data,cpu_get_pc(cpu),op_size); } #endif return NULL; @@ -887,11 +916,11 @@ /* Generate an interrupt if required */ if (tde->ctrl_buf & TI1570_TX_DMA_TCR_SELECT) { - if (((d->iregs[TI1570_REG_STATUS] & TI1570_CFG_BP_SEL) && buf_end) || + if (((d->iregs[TI1570_REG_CONFIG] & TI1570_CFG_BP_SEL) && buf_end) || pkt_end) { d->iregs[TI1570_REG_STATUS] |= TI1570_STAT_CP_TX; - pci_dev_trigger_irq(d->vm,d->pci_dev_ti); + dev_pa_a1_update_irq_status(d); } } @@ -1024,7 +1053,7 @@ /* generate the appropriate IRQ */ d->iregs[TI1570_REG_STATUS] |= TI1570_STAT_CP_RX; - pci_dev_trigger_irq(d->vm,d->pci_dev_ti); + dev_pa_a1_update_irq_status(d); } else { rcr_end = (d->iregs[TI1570_REG_RX_CRING_SIZE] >> 16); rcr_end &= TI1570_RCR_SIZE_MASK; @@ -1428,7 +1457,7 @@ /* * pci_ti1570_read() */ -static m_uint32_t pci_ti1570_read(cpu_mips_t *cpu,struct pci_device *dev, +static m_uint32_t pci_ti1570_read(cpu_gen_t *cpu,struct pci_device *dev, int reg) { struct pa_a1_data *d = dev->priv_data; @@ -1448,7 +1477,7 @@ /* * pci_ti1570_write() */ -static void pci_ti1570_write(cpu_mips_t *cpu,struct pci_device *dev, +static void pci_ti1570_write(cpu_gen_t *cpu,struct pci_device *dev, int reg,m_uint32_t value) { struct pa_a1_data *d = dev->priv_data; @@ -1468,9 +1497,11 @@ /* * pci_plx9060es_read() */ -static m_uint32_t pci_plx9060es_read(cpu_mips_t *cpu,struct pci_device *dev, +static m_uint32_t pci_plx9060es_read(cpu_gen_t *cpu,struct pci_device *dev, int reg) { + struct pa_a1_data *d = dev->priv_data; + #if DEBUG_ACCESS TI1570_LOG(d,"PLX9060ES","read reg 0x%x\n",reg); #endif @@ -1483,9 +1514,11 @@ /* * pci_plx9060es_write() */ -static void pci_plx9060es_write(cpu_mips_t *cpu,struct pci_device *dev, +static void pci_plx9060es_write(cpu_gen_t *cpu,struct pci_device *dev, int reg,m_uint32_t value) { + struct pa_a1_data *d = dev->priv_data; + #if DEBUG_ACCESS TI1570_LOG(d,"PLX9060ES","write reg 0x%x, value 0x%x\n",reg,value); #endif @@ -1511,8 +1544,9 @@ * * Add a PA-A1 port adapter into specified slot. */ -int dev_c7200_pa_a1_init(c7200_t *router,char *name,u_int pa_bay) +int dev_c7200_pa_a1_init(vm_instance_t *vm,struct cisco_card *card) { + u_int slot = card->slot_id; struct pci_device *pci_dev_ti,*pci_dev_plx; struct pa_a1_data *d; struct vdevice *dev; @@ -1520,49 +1554,53 @@ /* Allocate the private data structure for TI1570 chip */ if (!(d = malloc(sizeof(*d)))) { - fprintf(stderr,"%s (TI1570): out of memory\n",name); + vm_error(vm,"%s: out of memory\n",card->dev_name); return(-1); } memset(d,0,sizeof(*d)); + /* Set the PCI bus */ + card->pci_bus = vm->slots_pci_bus[slot]; + /* Set the EEPROM */ - c7200_pa_set_eeprom(router,pa_bay,cisco_eeprom_find_pa("PA-A1")); + cisco_card_set_eeprom(vm,card,cisco_eeprom_find_pa("PA-A1")); + c7200_set_slot_eeprom(VM_C7200(vm),slot,&card->eeprom); /* Add PCI device TI1570 */ - pci_dev_ti = pci_dev_add(router->pa_bay[pa_bay].pci_map,name, + pci_dev_ti = pci_dev_add(card->pci_bus,card->dev_name, TI1570_PCI_VENDOR_ID,TI1570_PCI_PRODUCT_ID, - 0,0,C7200_NETIO_IRQ,d, + 0,0,c7200_net_irq_for_slot_port(slot,0),d, NULL,pci_ti1570_read,pci_ti1570_write); if (!pci_dev_ti) { - fprintf(stderr,"%s (TI1570): unable to create PCI device TI1570.\n", - name); + vm_error(vm,"%s: unable to create PCI device TI1570.\n", + card->dev_name); return(-1); } /* Add PCI device PLX9060ES */ - pci_dev_plx = pci_dev_add(router->pa_bay[pa_bay].pci_map,name, + pci_dev_plx = pci_dev_add(card->pci_bus,card->dev_name, PLX_9060ES_PCI_VENDOR_ID, PLX_9060ES_PCI_PRODUCT_ID, - 1,0,C7200_NETIO_IRQ,d, + 1,0,-1,d, NULL,pci_plx9060es_read,pci_plx9060es_write); if (!pci_dev_plx) { - fprintf(stderr,"%s (PLX_9060ES): unable to create PCI device " - "PLX 9060ES.\n",name); + vm_error(vm,"%s: unable to create PCI device PLX 9060ES.\n", + card->dev_name); return(-1); } /* Create the TI1570 structure */ - d->name = name; - d->vm = router->vm; + d->name = card->dev_name; + d->vm = vm; d->pci_dev_ti = pci_dev_ti; d->pci_dev_plx = pci_dev_plx; /* Allocate the control memory */ if (!(d->ctrl_mem_ptr = malloc(TI1570_CTRL_MEM_SIZE))) { - fprintf(stderr,"%s (PA-A1): unable to create control memory.\n",name); + vm_error(vm,"%s: unable to create control memory.\n",card->dev_name); return(-1); } @@ -1579,8 +1617,8 @@ ti1570_reset(d,TRUE); /* Create the device itself */ - if (!(dev = dev_create(name))) { - fprintf(stderr,"%s (PA-A1): unable to create device.\n",name); + if (!(dev = dev_create(card->dev_name))) { + vm_error(vm,"%s: unable to create device.\n",card->dev_name); return(-1); } @@ -1593,30 +1631,26 @@ d->dev = dev; /* Store device info into the router structure */ - return(c7200_pa_set_drvinfo(router,pa_bay,d)); + card->drv_info = d; + return(0); } /* Remove a PA-A1 from the specified slot */ -int dev_c7200_pa_a1_shutdown(c7200_t *router,u_int pa_bay) +int dev_c7200_pa_a1_shutdown(vm_instance_t *vm,struct cisco_card *card) { - struct c7200_pa_bay *bay; - struct pa_a1_data *d; - - if (!(bay = c7200_pa_get_info(router,pa_bay))) - return(-1); - - d = bay->drv_info; + struct pa_a1_data *d = card->drv_info; /* Remove the PA EEPROM */ - c7200_pa_unset_eeprom(router,pa_bay); + cisco_card_unset_eeprom(card); + c7200_set_slot_eeprom(VM_C7200(vm),card->slot_id,NULL); /* Remove the PCI devices */ pci_dev_remove(d->pci_dev_ti); pci_dev_remove(d->pci_dev_plx); /* Remove the device from the VM address space */ - vm_unbind_device(router->vm,d->dev); - cpu_group_rebuild_mts(router->vm->cpu_group); + vm_unbind_device(vm,d->dev); + cpu_group_rebuild_mts(vm->cpu_group); /* Free the control memory */ free(d->ctrl_mem_ptr); @@ -1628,12 +1662,12 @@ } /* Bind a Network IO descriptor to a specific port */ -int dev_c7200_pa_a1_set_nio(c7200_t *router,u_int pa_bay,u_int port_id, - netio_desc_t *nio) +int dev_c7200_pa_a1_set_nio(vm_instance_t *vm,struct cisco_card *card, + u_int port_id,netio_desc_t *nio) { - struct pa_a1_data *d; + struct pa_a1_data *d = card->drv_info; - if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay))) + if (!d || (port_id > 0)) return(-1); if (d->nio != NULL) @@ -1646,11 +1680,12 @@ } /* Unbind a Network IO descriptor to a specific port */ -int dev_c7200_pa_a1_unset_nio(c7200_t *router,u_int pa_bay,u_int port_id) +int dev_c7200_pa_a1_unset_nio(vm_instance_t *vm,struct cisco_card *card, + u_int port_id) { - struct pa_a1_data *d; + struct pa_a1_data *d = card->drv_info; - if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay))) + if (!d || (port_id > 0)) return(-1); if (d->nio) { @@ -1662,10 +1697,11 @@ } /* PA-A1 driver */ -struct c7200_pa_driver dev_c7200_pa_a1_driver = { - "PA-A1", 1, +struct cisco_card_driver dev_c7200_pa_a1_driver = { + "PA-A1", 1, 0, dev_c7200_pa_a1_init, dev_c7200_pa_a1_shutdown, + NULL, dev_c7200_pa_a1_set_nio, dev_c7200_pa_a1_unset_nio, NULL,