1 |
/* |
/* |
2 |
* Cisco 7200 (Predator) simulation platform. |
* Cisco router simulation platform. |
3 |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
4 |
* |
* |
5 |
* Galileo GT64010/GT64120A/GT96100A system controller. |
* Galileo GT64010/GT64120A/GT96100A system controller. |
18 |
|
|
19 |
#include "utils.h" |
#include "utils.h" |
20 |
#include "net.h" |
#include "net.h" |
21 |
#include "mips64.h" |
#include "cpu.h" |
22 |
|
#include "vm.h" |
23 |
#include "dynamips.h" |
#include "dynamips.h" |
24 |
#include "memory.h" |
#include "memory.h" |
25 |
#include "device.h" |
#include "device.h" |
387 |
*data = swap32(gt_data->dma[ch].reg_name); |
*data = swap32(gt_data->dma[ch].reg_name); |
388 |
|
|
389 |
/* Handle a DMA channel */ |
/* Handle a DMA channel */ |
390 |
static int gt_dma_access(cpu_mips_t *cpu,struct vdevice *dev, |
static int gt_dma_access(cpu_gen_t *cpu,struct vdevice *dev, |
391 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
392 |
m_uint64_t *data) |
m_uint64_t *data) |
393 |
{ |
{ |
394 |
struct gt_data *gt_data = dev->priv_data; |
struct gt_data *gt_data = dev->priv_data; |
395 |
|
|
459 |
/* |
/* |
460 |
* dev_gt64010_access() |
* dev_gt64010_access() |
461 |
*/ |
*/ |
462 |
void *dev_gt64010_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, |
void *dev_gt64010_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset, |
463 |
u_int op_size,u_int op_type,m_uint64_t *data) |
u_int op_size,u_int op_type,m_uint64_t *data) |
464 |
{ |
{ |
465 |
struct gt_data *gt_data = dev->priv_data; |
struct gt_data *gt_data = dev->priv_data; |
567 |
default: |
default: |
568 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
569 |
cpu_log(cpu,"GT64010","read from addr 0x%x, pc=0x%llx\n", |
cpu_log(cpu,"GT64010","read from addr 0x%x, pc=0x%llx\n", |
570 |
offset,cpu->pc); |
offset,cpu_get_pc(cpu)); |
571 |
} else { |
} else { |
572 |
cpu_log(cpu,"GT64010","write to addr 0x%x, value=0x%llx, " |
cpu_log(cpu,"GT64010","write to addr 0x%x, value=0x%llx, " |
573 |
"pc=0x%llx\n",offset,*data,cpu->pc); |
"pc=0x%llx\n",offset,*data,cpu_get_pc(cpu)); |
574 |
} |
} |
575 |
#endif |
#endif |
576 |
} |
} |
581 |
/* |
/* |
582 |
* dev_gt64120_access() |
* dev_gt64120_access() |
583 |
*/ |
*/ |
584 |
void *dev_gt64120_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, |
void *dev_gt64120_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset, |
585 |
u_int op_size,u_int op_type,m_uint64_t *data) |
u_int op_size,u_int op_type,m_uint64_t *data) |
586 |
{ |
{ |
587 |
struct gt_data *gt_data = dev->priv_data; |
struct gt_data *gt_data = dev->priv_data; |
697 |
default: |
default: |
698 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
699 |
cpu_log(cpu,"GT64120","read from addr 0x%x, pc=0x%llx\n", |
cpu_log(cpu,"GT64120","read from addr 0x%x, pc=0x%llx\n", |
700 |
offset,cpu->pc); |
offset,cpu_get_pc(cpu)); |
701 |
} else { |
} else { |
702 |
cpu_log(cpu,"GT64120","write to addr 0x%x, value=0x%llx, " |
cpu_log(cpu,"GT64120","write to addr 0x%x, value=0x%llx, " |
703 |
"pc=0x%llx\n",offset,*data,cpu->pc); |
"pc=0x%llx\n",offset,*data,cpu_get_pc(cpu)); |
704 |
} |
} |
705 |
#endif |
#endif |
706 |
} |
} |
708 |
return NULL; |
return NULL; |
709 |
} |
} |
710 |
|
|
711 |
|
/* Trigger/clear Ethernet interrupt if one or both port have pending events */ |
712 |
|
static void gt_eth_set_int_status(struct gt_data *d) |
713 |
|
{ |
714 |
|
if ((d->eth_ports[0].icr & GT_ICR_INT_SUM) || |
715 |
|
(d->eth_ports[1].icr & GT_ICR_INT_SUM)) |
716 |
|
vm_set_irq(d->vm,d->eth_irq); |
717 |
|
else |
718 |
|
vm_clear_irq(d->vm,d->eth_irq); |
719 |
|
} |
720 |
|
|
721 |
/* Update the Ethernet port interrupt status */ |
/* Update the Ethernet port interrupt status */ |
722 |
static void gt_eth_update_int_status(struct gt_data *d,struct eth_port *port) |
static void gt_eth_update_int_status(struct gt_data *d,struct eth_port *port) |
723 |
{ |
{ |
724 |
if (port->icr & GT_ICR_MASK) |
if (port->icr & port->imr & GT_ICR_MASK) { |
725 |
port->icr |= GT_ICR_INT_SUM; |
port->icr |= GT_ICR_INT_SUM; |
726 |
|
} else { |
727 |
|
port->icr &= ~GT_ICR_INT_SUM; |
728 |
|
} |
729 |
|
|
730 |
if (port->icr & port->imr & GT_ICR_MASK) |
gt_eth_set_int_status(d); |
|
vm_set_irq(d->vm,d->eth_irq); |
|
731 |
} |
} |
732 |
|
|
733 |
/* Read a MII register */ |
/* Read a MII register */ |
816 |
} |
} |
817 |
|
|
818 |
/* Handle registers of Ethernet ports */ |
/* Handle registers of Ethernet ports */ |
819 |
static int gt_eth_access(cpu_mips_t *cpu,struct vdevice *dev, |
static int gt_eth_access(cpu_gen_t *cpu,struct vdevice *dev, |
820 |
m_uint32_t offset,u_int op_size,u_int op_type, |
m_uint32_t offset,u_int op_size,u_int op_type, |
821 |
m_uint64_t *data) |
m_uint64_t *data) |
822 |
{ |
{ |
859 |
/* ICR: Interrupt Cause Register */ |
/* ICR: Interrupt Cause Register */ |
860 |
case 0x84850: |
case 0x84850: |
861 |
case 0x88850: |
case 0x88850: |
862 |
if (op_type == MTS_READ) |
if (op_type == MTS_READ) { |
863 |
*data = port->icr; |
*data = port->icr; |
864 |
else |
} else { |
865 |
port->icr &= *data; |
port->icr &= *data; |
866 |
|
gt_eth_update_int_status(d,port); |
867 |
|
} |
868 |
break; |
break; |
869 |
|
|
870 |
/* IMR: Interrupt Mask Register */ |
/* IMR: Interrupt Mask Register */ |
871 |
case 0x84858: |
case 0x84858: |
872 |
case 0x88858: |
case 0x88858: |
873 |
if (op_type == MTS_READ) |
if (op_type == MTS_READ) { |
874 |
*data = port->imr; |
*data = port->imr; |
875 |
else |
} else { |
876 |
port->imr = *data; |
port->imr = *data; |
877 |
|
gt_eth_update_int_status(d,port); |
878 |
|
} |
879 |
break; |
break; |
880 |
|
|
881 |
/* PCR: Port Configuration Register */ |
/* PCR: Port Configuration Register */ |
1054 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
1055 |
cpu_log(cpu,"GT96100/ETH", |
cpu_log(cpu,"GT96100/ETH", |
1056 |
"read access to unknown register 0x%x, pc=0x%llx\n", |
"read access to unknown register 0x%x, pc=0x%llx\n", |
1057 |
offset,cpu->pc); |
offset,cpu_get_pc(cpu)); |
1058 |
} else { |
} else { |
1059 |
cpu_log(cpu,"GT96100/ETH", |
cpu_log(cpu,"GT96100/ETH", |
1060 |
"write access to unknown register 0x%x, value=0x%llx, " |
"write access to unknown register 0x%x, value=0x%llx, " |
1061 |
"pc=0x%llx\n",offset,*data,cpu->pc); |
"pc=0x%llx\n",offset,*data,cpu_get_pc(cpu)); |
1062 |
} |
} |
1063 |
#endif |
#endif |
1064 |
} |
} |
1072 |
/* |
/* |
1073 |
* dev_gt96100_access() |
* dev_gt96100_access() |
1074 |
*/ |
*/ |
1075 |
void *dev_gt96100_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, |
void *dev_gt96100_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset, |
1076 |
u_int op_size,u_int op_type,m_uint64_t *data) |
u_int op_size,u_int op_type,m_uint64_t *data) |
1077 |
{ |
{ |
1078 |
struct gt_data *gt_data = dev->priv_data; |
struct gt_data *gt_data = dev->priv_data; |
1212 |
if (gt_data->eth_ports[1].icr & GT_ICR_INT_SUM) |
if (gt_data->eth_ports[1].icr & GT_ICR_INT_SUM) |
1213 |
*data |= GT_SCR_ETH1_SUM; |
*data |= GT_SCR_ETH1_SUM; |
1214 |
|
|
1215 |
|
gt_update_irq_status(gt_data); |
1216 |
*data = swap32(*data); |
*data = swap32(*data); |
1217 |
} |
} |
1218 |
break; |
break; |
1239 |
default: |
default: |
1240 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
1241 |
cpu_log(cpu,"GT96100","read from addr 0x%x, pc=0x%llx\n", |
cpu_log(cpu,"GT96100","read from addr 0x%x, pc=0x%llx\n", |
1242 |
offset,cpu->pc); |
offset,cpu_get_pc(cpu)); |
1243 |
} else { |
} else { |
1244 |
cpu_log(cpu,"GT96100","write to addr 0x%x, value=0x%llx, " |
cpu_log(cpu,"GT96100","write to addr 0x%x, value=0x%llx, " |
1245 |
"pc=0x%llx\n",offset,*data,cpu->pc); |
"pc=0x%llx\n",offset,*data,cpu_get_pc(cpu)); |
1246 |
} |
} |
1247 |
#endif |
#endif |
1248 |
} |
} |
1299 |
tx_start = tx_current = port->tx_current[queue]; |
tx_start = tx_current = port->tx_current[queue]; |
1300 |
|
|
1301 |
if (!tx_start) |
if (!tx_start) |
1302 |
goto done; |
return(FALSE); |
1303 |
|
|
1304 |
ptxd = &txd0; |
ptxd = &txd0; |
1305 |
gt_eth_desc_read(d,tx_start,ptxd); |
gt_eth_desc_read(d,tx_start,ptxd); |
1306 |
|
|
1307 |
/* If we don't own the first descriptor, we cannot transmit */ |
/* If we don't own the first descriptor, we cannot transmit */ |
1308 |
if (!(txd0.cmd_stat & GT_TXDESC_OWN)) |
if (!(txd0.cmd_stat & GT_TXDESC_OWN)) |
1309 |
goto done; |
return(FALSE); |
1310 |
|
|
1311 |
/* Empty packet for now */ |
/* Empty packet for now */ |
1312 |
pkt_ptr = pkt; |
pkt_ptr = pkt; |
1379 |
else |
else |
1380 |
port->icr |= GT_ICR_TXBUFH; |
port->icr |= GT_ICR_TXBUFH; |
1381 |
|
|
|
done: |
|
1382 |
if (abort) { |
if (abort) { |
1383 |
/* TX underrun */ |
/* TX underrun */ |
1384 |
port->icr |= GT_ICR_TXUDR; |
port->icr |= GT_ICR_TXUDR; |
1789 |
* |
* |
1790 |
* Read a PCI register. |
* Read a PCI register. |
1791 |
*/ |
*/ |
1792 |
static m_uint32_t pci_gt64120_read(cpu_mips_t *cpu,struct pci_device *dev, |
static m_uint32_t pci_gt64120_read(cpu_gen_t *cpu,struct pci_device *dev, |
1793 |
int reg) |
int reg) |
1794 |
{ |
{ |
1795 |
switch (reg) { |
switch (reg) { |
1850 |
* |
* |
1851 |
* Read a PCI register. |
* Read a PCI register. |
1852 |
*/ |
*/ |
1853 |
static m_uint32_t pci_gt96100_read(cpu_mips_t *cpu,struct pci_device *dev, |
static m_uint32_t pci_gt96100_read(cpu_gen_t *cpu,struct pci_device *dev, |
1854 |
int reg) |
int reg) |
1855 |
{ |
{ |
1856 |
switch (reg) { |
switch (reg) { |