Revision ad00a9b9 hw/e1000.c
b/hw/e1000.c | ||
---|---|---|
82 | 82 |
PCIDevice dev; |
83 | 83 |
NICState *nic; |
84 | 84 |
NICConf conf; |
85 |
int mmio_index; |
|
85 |
MemoryRegion mmio; |
|
86 |
MemoryRegion io; |
|
86 | 87 |
|
87 | 88 |
uint32_t mac_reg[0x8000]; |
88 | 89 |
uint16_t phy_reg[0x20]; |
... | ... | |
151 | 152 |
}; |
152 | 153 |
|
153 | 154 |
static void |
154 |
ioport_map(PCIDevice *pci_dev, int region_num, pcibus_t addr, |
|
155 |
pcibus_t size, int type) |
|
156 |
{ |
|
157 |
DBGOUT(IO, "e1000_ioport_map addr=0x%04"FMT_PCIBUS |
|
158 |
" size=0x%08"FMT_PCIBUS"\n", addr, size); |
|
159 |
} |
|
160 |
|
|
161 |
static void |
|
162 | 155 |
set_interrupt_cause(E1000State *s, int index, uint32_t val) |
163 | 156 |
{ |
164 | 157 |
if (val) |
... | ... | |
905 | 898 |
enum { NWRITEOPS = ARRAY_SIZE(macreg_writeops) }; |
906 | 899 |
|
907 | 900 |
static void |
908 |
e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
901 |
e1000_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val, |
|
902 |
unsigned size) |
|
909 | 903 |
{ |
910 | 904 |
E1000State *s = opaque; |
911 | 905 |
unsigned int index = (addr & 0x1ffff) >> 2; |
... | ... | |
913 | 907 |
if (index < NWRITEOPS && macreg_writeops[index]) { |
914 | 908 |
macreg_writeops[index](s, index, val); |
915 | 909 |
} else if (index < NREADOPS && macreg_readops[index]) { |
916 |
DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val);
|
|
910 |
DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04"PRIx64"\n", index<<2, val);
|
|
917 | 911 |
} else { |
918 |
DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08x\n",
|
|
912 |
DBGOUT(UNKNOWN, "MMIO unknown write addr=0x%08x,val=0x%08"PRIx64"\n",
|
|
919 | 913 |
index<<2, val); |
920 | 914 |
} |
921 | 915 |
} |
922 | 916 |
|
923 |
static void |
|
924 |
e1000_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
925 |
{ |
|
926 |
// emulate hw without byte enables: no RMW |
|
927 |
e1000_mmio_writel(opaque, addr & ~3, |
|
928 |
(val & 0xffff) << (8*(addr & 3))); |
|
929 |
} |
|
930 |
|
|
931 |
static void |
|
932 |
e1000_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
933 |
{ |
|
934 |
// emulate hw without byte enables: no RMW |
|
935 |
e1000_mmio_writel(opaque, addr & ~3, |
|
936 |
(val & 0xff) << (8*(addr & 3))); |
|
937 |
} |
|
938 |
|
|
939 |
static uint32_t |
|
940 |
e1000_mmio_readl(void *opaque, target_phys_addr_t addr) |
|
917 |
static uint64_t |
|
918 |
e1000_mmio_read(void *opaque, target_phys_addr_t addr, unsigned size) |
|
941 | 919 |
{ |
942 | 920 |
E1000State *s = opaque; |
943 | 921 |
unsigned int index = (addr & 0x1ffff) >> 2; |
... | ... | |
950 | 928 |
return 0; |
951 | 929 |
} |
952 | 930 |
|
953 |
static uint32_t |
|
954 |
e1000_mmio_readb(void *opaque, target_phys_addr_t addr) |
|
931 |
static const MemoryRegionOps e1000_mmio_ops = { |
|
932 |
.read = e1000_mmio_read, |
|
933 |
.write = e1000_mmio_write, |
|
934 |
.endianness = DEVICE_LITTLE_ENDIAN, |
|
935 |
.impl = { |
|
936 |
.min_access_size = 4, |
|
937 |
.max_access_size = 4, |
|
938 |
}, |
|
939 |
}; |
|
940 |
|
|
941 |
static uint64_t e1000_io_read(void *opaque, target_phys_addr_t addr, |
|
942 |
unsigned size) |
|
955 | 943 |
{ |
956 |
return ((e1000_mmio_readl(opaque, addr & ~3)) >> |
|
957 |
(8 * (addr & 3))) & 0xff; |
|
944 |
E1000State *s = opaque; |
|
945 |
|
|
946 |
(void)s; |
|
947 |
return 0; |
|
958 | 948 |
} |
959 | 949 |
|
960 |
static uint32_t
|
|
961 |
e1000_mmio_readw(void *opaque, target_phys_addr_t addr)
|
|
950 |
static void e1000_io_write(void *opaque, target_phys_addr_t addr,
|
|
951 |
uint64_t val, unsigned size)
|
|
962 | 952 |
{ |
963 |
return ((e1000_mmio_readl(opaque, addr & ~3)) >> |
|
964 |
(8 * (addr & 3))) & 0xffff; |
|
953 |
E1000State *s = opaque; |
|
954 |
|
|
955 |
(void)s; |
|
965 | 956 |
} |
966 | 957 |
|
958 |
static const MemoryRegionOps e1000_io_ops = { |
|
959 |
.read = e1000_io_read, |
|
960 |
.write = e1000_io_write, |
|
961 |
.endianness = DEVICE_LITTLE_ENDIAN, |
|
962 |
}; |
|
963 |
|
|
967 | 964 |
static bool is_version_1(void *opaque, int version_id) |
968 | 965 |
{ |
969 | 966 |
return version_id == 1; |
... | ... | |
1083 | 1080 |
|
1084 | 1081 |
/* PCI interface */ |
1085 | 1082 |
|
1086 |
static CPUWriteMemoryFunc * const e1000_mmio_write[] = { |
|
1087 |
e1000_mmio_writeb, e1000_mmio_writew, e1000_mmio_writel |
|
1088 |
}; |
|
1089 |
|
|
1090 |
static CPUReadMemoryFunc * const e1000_mmio_read[] = { |
|
1091 |
e1000_mmio_readb, e1000_mmio_readw, e1000_mmio_readl |
|
1092 |
}; |
|
1093 |
|
|
1094 | 1083 |
static void |
1095 |
e1000_mmio_map(PCIDevice *pci_dev, int region_num, |
|
1096 |
pcibus_t addr, pcibus_t size, int type) |
|
1084 |
e1000_mmio_setup(E1000State *d) |
|
1097 | 1085 |
{ |
1098 |
E1000State *d = DO_UPCAST(E1000State, dev, pci_dev); |
|
1099 | 1086 |
int i; |
1100 | 1087 |
const uint32_t excluded_regs[] = { |
1101 | 1088 |
E1000_MDIC, E1000_ICR, E1000_ICS, E1000_IMS, |
1102 | 1089 |
E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE |
1103 | 1090 |
}; |
1104 | 1091 |
|
1105 |
|
|
1106 |
DBGOUT(MMIO, "e1000_mmio_map addr=0x%08"FMT_PCIBUS" 0x%08"FMT_PCIBUS"\n", |
|
1107 |
addr, size); |
|
1108 |
|
|
1109 |
cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index); |
|
1110 |
qemu_register_coalesced_mmio(addr, excluded_regs[0]); |
|
1111 |
|
|
1092 |
memory_region_init_io(&d->mmio, &e1000_mmio_ops, d, "e1000-mmio", |
|
1093 |
PNPMMIO_SIZE); |
|
1094 |
memory_region_add_coalescing(&d->mmio, 0, excluded_regs[0]); |
|
1112 | 1095 |
for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++) |
1113 |
qemu_register_coalesced_mmio(addr + excluded_regs[i] + 4,
|
|
1114 |
excluded_regs[i + 1] -
|
|
1115 |
excluded_regs[i] - 4);
|
|
1096 |
memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4,
|
|
1097 |
excluded_regs[i+1] - excluded_regs[i] - 4);
|
|
1098 |
memory_region_init_io(&d->io, &e1000_io_ops, d, "e1000-io", IOPORT_SIZE);
|
|
1116 | 1099 |
} |
1117 | 1100 |
|
1118 | 1101 |
static void |
... | ... | |
1128 | 1111 |
{ |
1129 | 1112 |
E1000State *d = DO_UPCAST(E1000State, dev, dev); |
1130 | 1113 |
|
1131 |
cpu_unregister_io_memory(d->mmio_index); |
|
1114 |
memory_region_destroy(&d->mmio); |
|
1115 |
memory_region_destroy(&d->io); |
|
1132 | 1116 |
qemu_del_vlan_client(&d->nic->nc); |
1133 | 1117 |
return 0; |
1134 | 1118 |
} |
... | ... | |
1172 | 1156 |
/* TODO: RST# value should be 0 if programmable, PCI spec 6.2.4 */ |
1173 | 1157 |
pci_conf[PCI_INTERRUPT_PIN] = 1; // interrupt pin 0 |
1174 | 1158 |
|
1175 |
d->mmio_index = cpu_register_io_memory(e1000_mmio_read, |
|
1176 |
e1000_mmio_write, d, DEVICE_LITTLE_ENDIAN); |
|
1159 |
e1000_mmio_setup(d); |
|
1177 | 1160 |
|
1178 |
pci_register_bar(&d->dev, 0, PNPMMIO_SIZE,
|
|
1179 |
PCI_BASE_ADDRESS_SPACE_MEMORY, e1000_mmio_map);
|
|
1161 |
pci_register_bar_region(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY,
|
|
1162 |
&d->mmio);
|
|
1180 | 1163 |
|
1181 |
pci_register_bar(&d->dev, 1, IOPORT_SIZE, |
|
1182 |
PCI_BASE_ADDRESS_SPACE_IO, ioport_map); |
|
1164 |
pci_register_bar_region(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->io); |
|
1183 | 1165 |
|
1184 | 1166 |
memmove(d->eeprom_data, e1000_eeprom_template, |
1185 | 1167 |
sizeof e1000_eeprom_template); |
Also available in: Unified diff