Revision 94e1a912
b/Makefile.target | ||
---|---|---|
260 | 260 |
obj-sparc-y += fdc.o mc146818rtc.o serial.o |
261 | 261 |
obj-sparc-y += cirrus_vga.o parallel.o |
262 | 262 |
else |
263 |
obj-sparc-y = sun4m.o tcx.o iommu.o slavio_intctl.o |
|
263 |
obj-sparc-y = sun4m.o lance.o tcx.o iommu.o slavio_intctl.o
|
|
264 | 264 |
obj-sparc-y += slavio_timer.o slavio_misc.o fdc.o sparc32_dma.o |
265 | 265 |
obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o |
266 | 266 |
endif |
b/hw/lance.c | ||
---|---|---|
1 |
/* |
|
2 |
* QEMU AMD PC-Net II (Am79C970A) emulation |
|
3 |
* |
|
4 |
* Copyright (c) 2004 Antony T Curtis |
|
5 |
* |
|
6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
|
7 |
* of this software and associated documentation files (the "Software"), to deal |
|
8 |
* in the Software without restriction, including without limitation the rights |
|
9 |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
10 |
* copies of the Software, and to permit persons to whom the Software is |
|
11 |
* furnished to do so, subject to the following conditions: |
|
12 |
* |
|
13 |
* The above copyright notice and this permission notice shall be included in |
|
14 |
* all copies or substantial portions of the Software. |
|
15 |
* |
|
16 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
17 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
18 |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
19 |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
20 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
22 |
* THE SOFTWARE. |
|
23 |
*/ |
|
24 |
|
|
25 |
/* This software was written to be compatible with the specification: |
|
26 |
* AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet |
|
27 |
* AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000 |
|
28 |
*/ |
|
29 |
|
|
30 |
/* |
|
31 |
* On Sparc32, this is the Lance (Am7990) part of chip STP2000 (Master I/O), also |
|
32 |
* produced as NCR89C100. See |
|
33 |
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt |
|
34 |
* and |
|
35 |
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt |
|
36 |
*/ |
|
37 |
|
|
38 |
#include "sysbus.h" |
|
39 |
#include "net.h" |
|
40 |
#include "qemu-timer.h" |
|
41 |
#include "qemu_socket.h" |
|
42 |
#include "sun4m.h" |
|
43 |
|
|
44 |
#include "pcnet.h" |
|
45 |
|
|
46 |
typedef struct { |
|
47 |
SysBusDevice busdev; |
|
48 |
PCNetState state; |
|
49 |
} SysBusPCNetState; |
|
50 |
|
|
51 |
static void parent_lance_reset(void *opaque, int irq, int level) |
|
52 |
{ |
|
53 |
SysBusPCNetState *d = opaque; |
|
54 |
if (level) |
|
55 |
pcnet_h_reset(&d->state); |
|
56 |
} |
|
57 |
|
|
58 |
static void lance_mem_writew(void *opaque, target_phys_addr_t addr, |
|
59 |
uint32_t val) |
|
60 |
{ |
|
61 |
SysBusPCNetState *d = opaque; |
|
62 |
#ifdef PCNET_DEBUG_IO |
|
63 |
printf("lance_mem_writew addr=" TARGET_FMT_plx " val=0x%04x\n", addr, |
|
64 |
val & 0xffff); |
|
65 |
#endif |
|
66 |
pcnet_ioport_writew(&d->state, addr, val & 0xffff); |
|
67 |
} |
|
68 |
|
|
69 |
static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr) |
|
70 |
{ |
|
71 |
SysBusPCNetState *d = opaque; |
|
72 |
uint32_t val; |
|
73 |
|
|
74 |
val = pcnet_ioport_readw(&d->state, addr); |
|
75 |
#ifdef PCNET_DEBUG_IO |
|
76 |
printf("lance_mem_readw addr=" TARGET_FMT_plx " val = 0x%04x\n", addr, |
|
77 |
val & 0xffff); |
|
78 |
#endif |
|
79 |
|
|
80 |
return val & 0xffff; |
|
81 |
} |
|
82 |
|
|
83 |
static CPUReadMemoryFunc * const lance_mem_read[3] = { |
|
84 |
NULL, |
|
85 |
lance_mem_readw, |
|
86 |
NULL, |
|
87 |
}; |
|
88 |
|
|
89 |
static CPUWriteMemoryFunc * const lance_mem_write[3] = { |
|
90 |
NULL, |
|
91 |
lance_mem_writew, |
|
92 |
NULL, |
|
93 |
}; |
|
94 |
|
|
95 |
static void lance_cleanup(VLANClientState *vc) |
|
96 |
{ |
|
97 |
PCNetState *d = vc->opaque; |
|
98 |
|
|
99 |
pcnet_common_cleanup(d); |
|
100 |
} |
|
101 |
|
|
102 |
static int lance_init(SysBusDevice *dev) |
|
103 |
{ |
|
104 |
SysBusPCNetState *d = FROM_SYSBUS(SysBusPCNetState, dev); |
|
105 |
PCNetState *s = &d->state; |
|
106 |
|
|
107 |
s->mmio_index = |
|
108 |
cpu_register_io_memory(lance_mem_read, lance_mem_write, d); |
|
109 |
|
|
110 |
qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1); |
|
111 |
|
|
112 |
sysbus_init_mmio(dev, 4, s->mmio_index); |
|
113 |
|
|
114 |
sysbus_init_irq(dev, &s->irq); |
|
115 |
|
|
116 |
s->phys_mem_read = ledma_memory_read; |
|
117 |
s->phys_mem_write = ledma_memory_write; |
|
118 |
|
|
119 |
register_savevm("pcnet", -1, 3, pcnet_save, pcnet_load, s); |
|
120 |
return pcnet_common_init(&dev->qdev, s, lance_cleanup); |
|
121 |
} |
|
122 |
|
|
123 |
static void lance_reset(DeviceState *dev) |
|
124 |
{ |
|
125 |
SysBusPCNetState *d = DO_UPCAST(SysBusPCNetState, busdev.qdev, dev); |
|
126 |
|
|
127 |
pcnet_h_reset(&d->state); |
|
128 |
} |
|
129 |
|
|
130 |
static SysBusDeviceInfo lance_info = { |
|
131 |
.init = lance_init, |
|
132 |
.qdev.name = "lance", |
|
133 |
.qdev.size = sizeof(SysBusPCNetState), |
|
134 |
.qdev.reset = lance_reset, |
|
135 |
.qdev.props = (Property[]) { |
|
136 |
DEFINE_PROP_PTR("dma", SysBusPCNetState, state.dma_opaque), |
|
137 |
DEFINE_NIC_PROPERTIES(SysBusPCNetState, state.conf), |
|
138 |
DEFINE_PROP_END_OF_LIST(), |
|
139 |
} |
|
140 |
}; |
|
141 |
|
|
142 |
static void lance_register_devices(void) |
|
143 |
{ |
|
144 |
sysbus_register_withprop(&lance_info); |
|
145 |
} |
|
146 |
device_init(lance_register_devices) |
b/hw/pcnet.c | ||
---|---|---|
35 | 35 |
* http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt |
36 | 36 |
*/ |
37 | 37 |
|
38 |
#include "sysbus.h" |
|
39 | 38 |
#include "pci.h" |
40 | 39 |
#include "net.h" |
41 | 40 |
#include "loader.h" |
42 | 41 |
#include "qemu-timer.h" |
43 | 42 |
#include "qemu_socket.h" |
44 | 43 |
|
44 |
#include "pcnet.h" |
|
45 |
|
|
45 | 46 |
//#define PCNET_DEBUG |
46 | 47 |
//#define PCNET_DEBUG_IO |
47 | 48 |
//#define PCNET_DEBUG_BCR |
... | ... | |
51 | 52 |
//#define PCNET_DEBUG_MATCH |
52 | 53 |
|
53 | 54 |
|
54 |
#define PCNET_IOPORT_SIZE 0x20 |
|
55 |
#define PCNET_PNPMMIO_SIZE 0x20 |
|
56 |
|
|
57 |
#define PCNET_LOOPTEST_CRC 1 |
|
58 |
#define PCNET_LOOPTEST_NOCRC 2 |
|
59 |
|
|
60 |
|
|
61 |
typedef struct PCNetState_st PCNetState; |
|
62 |
|
|
63 |
struct PCNetState_st { |
|
64 |
VLANClientState *vc; |
|
65 |
NICConf conf; |
|
66 |
QEMUTimer *poll_timer; |
|
67 |
int rap, isr, lnkst; |
|
68 |
uint32_t rdra, tdra; |
|
69 |
uint8_t prom[16]; |
|
70 |
uint16_t csr[128]; |
|
71 |
uint16_t bcr[32]; |
|
72 |
uint64_t timer; |
|
73 |
int mmio_index, xmit_pos; |
|
74 |
uint8_t buffer[4096]; |
|
75 |
int tx_busy; |
|
76 |
qemu_irq irq; |
|
77 |
void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr, |
|
78 |
uint8_t *buf, int len, int do_bswap); |
|
79 |
void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr, |
|
80 |
uint8_t *buf, int len, int do_bswap); |
|
81 |
void *dma_opaque; |
|
82 |
int looptest; |
|
83 |
}; |
|
84 |
|
|
85 | 55 |
typedef struct { |
86 | 56 |
PCIDevice pci_dev; |
87 | 57 |
PCNetState state; |
88 | 58 |
} PCIPCNetState; |
89 | 59 |
|
90 |
typedef struct { |
|
91 |
SysBusDevice busdev; |
|
92 |
PCNetState state; |
|
93 |
} SysBusPCNetState; |
|
94 |
|
|
95 | 60 |
struct qemu_ether_header { |
96 | 61 |
uint8_t ether_dhost[6]; |
97 | 62 |
uint8_t ether_shost[6]; |
... | ... | |
1594 | 1559 |
return val; |
1595 | 1560 |
} |
1596 | 1561 |
|
1597 |
static void pcnet_h_reset(void *opaque)
|
|
1562 |
void pcnet_h_reset(void *opaque) |
|
1598 | 1563 |
{ |
1599 | 1564 |
PCNetState *s = opaque; |
1600 | 1565 |
int i; |
... | ... | |
1650 | 1615 |
return val; |
1651 | 1616 |
} |
1652 | 1617 |
|
1653 |
static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
|
|
1618 |
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val) |
|
1654 | 1619 |
{ |
1655 | 1620 |
PCNetState *s = opaque; |
1656 | 1621 |
pcnet_poll_timer(s); |
... | ... | |
1673 | 1638 |
pcnet_update_irq(s); |
1674 | 1639 |
} |
1675 | 1640 |
|
1676 |
static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
|
|
1641 |
uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr) |
|
1677 | 1642 |
{ |
1678 | 1643 |
PCNetState *s = opaque; |
1679 | 1644 |
uint32_t val = -1; |
... | ... | |
1880 | 1845 |
} |
1881 | 1846 |
|
1882 | 1847 |
|
1883 |
static void pcnet_save(QEMUFile *f, void *opaque)
|
|
1848 |
void pcnet_save(QEMUFile *f, void *opaque) |
|
1884 | 1849 |
{ |
1885 | 1850 |
PCNetState *s = opaque; |
1886 | 1851 |
unsigned int i; |
... | ... | |
1902 | 1867 |
qemu_put_timer(f, s->poll_timer); |
1903 | 1868 |
} |
1904 | 1869 |
|
1905 |
static int pcnet_load(QEMUFile *f, void *opaque, int version_id)
|
|
1870 |
int pcnet_load(QEMUFile *f, void *opaque, int version_id) |
|
1906 | 1871 |
{ |
1907 | 1872 |
PCNetState *s = opaque; |
1908 | 1873 |
int i, dummy; |
... | ... | |
1952 | 1917 |
return pcnet_load(f, &s->state, version_id); |
1953 | 1918 |
} |
1954 | 1919 |
|
1955 |
static void pcnet_common_cleanup(PCNetState *d)
|
|
1920 |
void pcnet_common_cleanup(PCNetState *d) |
|
1956 | 1921 |
{ |
1957 | 1922 |
d->vc = NULL; |
1958 | 1923 |
} |
1959 | 1924 |
|
1960 |
static int pcnet_common_init(DeviceState *dev, PCNetState *s,
|
|
1925 |
int pcnet_common_init(DeviceState *dev, PCNetState *s, |
|
1961 | 1926 |
NetCleanup *cleanup) |
1962 | 1927 |
{ |
1963 | 1928 |
s->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, s); |
... | ... | |
2093 | 2058 |
pcnet_h_reset(&d->state); |
2094 | 2059 |
} |
2095 | 2060 |
|
2096 |
/* SPARC32 interface */ |
|
2097 |
|
|
2098 |
#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) // Avoid compile failure |
|
2099 |
#include "sun4m.h" |
|
2100 |
|
|
2101 |
static void parent_lance_reset(void *opaque, int irq, int level) |
|
2102 |
{ |
|
2103 |
SysBusPCNetState *d = opaque; |
|
2104 |
if (level) |
|
2105 |
pcnet_h_reset(&d->state); |
|
2106 |
} |
|
2107 |
|
|
2108 |
static void lance_mem_writew(void *opaque, target_phys_addr_t addr, |
|
2109 |
uint32_t val) |
|
2110 |
{ |
|
2111 |
SysBusPCNetState *d = opaque; |
|
2112 |
#ifdef PCNET_DEBUG_IO |
|
2113 |
printf("lance_mem_writew addr=" TARGET_FMT_plx " val=0x%04x\n", addr, |
|
2114 |
val & 0xffff); |
|
2115 |
#endif |
|
2116 |
pcnet_ioport_writew(&d->state, addr, val & 0xffff); |
|
2117 |
} |
|
2118 |
|
|
2119 |
static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr) |
|
2120 |
{ |
|
2121 |
SysBusPCNetState *d = opaque; |
|
2122 |
uint32_t val; |
|
2123 |
|
|
2124 |
val = pcnet_ioport_readw(&d->state, addr); |
|
2125 |
#ifdef PCNET_DEBUG_IO |
|
2126 |
printf("lance_mem_readw addr=" TARGET_FMT_plx " val = 0x%04x\n", addr, |
|
2127 |
val & 0xffff); |
|
2128 |
#endif |
|
2129 |
|
|
2130 |
return val & 0xffff; |
|
2131 |
} |
|
2132 |
|
|
2133 |
static CPUReadMemoryFunc * const lance_mem_read[3] = { |
|
2134 |
NULL, |
|
2135 |
lance_mem_readw, |
|
2136 |
NULL, |
|
2137 |
}; |
|
2138 |
|
|
2139 |
static CPUWriteMemoryFunc * const lance_mem_write[3] = { |
|
2140 |
NULL, |
|
2141 |
lance_mem_writew, |
|
2142 |
NULL, |
|
2143 |
}; |
|
2144 |
|
|
2145 |
static void lance_cleanup(VLANClientState *vc) |
|
2146 |
{ |
|
2147 |
PCNetState *d = vc->opaque; |
|
2148 |
|
|
2149 |
pcnet_common_cleanup(d); |
|
2150 |
} |
|
2151 |
|
|
2152 |
static int lance_init(SysBusDevice *dev) |
|
2153 |
{ |
|
2154 |
SysBusPCNetState *d = FROM_SYSBUS(SysBusPCNetState, dev); |
|
2155 |
PCNetState *s = &d->state; |
|
2156 |
|
|
2157 |
s->mmio_index = |
|
2158 |
cpu_register_io_memory(lance_mem_read, lance_mem_write, d); |
|
2159 |
|
|
2160 |
qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1); |
|
2161 |
|
|
2162 |
sysbus_init_mmio(dev, 4, s->mmio_index); |
|
2163 |
|
|
2164 |
sysbus_init_irq(dev, &s->irq); |
|
2165 |
|
|
2166 |
s->phys_mem_read = ledma_memory_read; |
|
2167 |
s->phys_mem_write = ledma_memory_write; |
|
2168 |
|
|
2169 |
register_savevm("pcnet", -1, 3, pcnet_save, pcnet_load, s); |
|
2170 |
return pcnet_common_init(&dev->qdev, s, lance_cleanup); |
|
2171 |
} |
|
2172 |
|
|
2173 |
static void lance_reset(DeviceState *dev) |
|
2174 |
{ |
|
2175 |
SysBusPCNetState *d = DO_UPCAST(SysBusPCNetState, busdev.qdev, dev); |
|
2176 |
|
|
2177 |
pcnet_h_reset(&d->state); |
|
2178 |
} |
|
2179 |
|
|
2180 |
static SysBusDeviceInfo lance_info = { |
|
2181 |
.init = lance_init, |
|
2182 |
.qdev.name = "lance", |
|
2183 |
.qdev.size = sizeof(SysBusPCNetState), |
|
2184 |
.qdev.reset = lance_reset, |
|
2185 |
.qdev.props = (Property[]) { |
|
2186 |
DEFINE_PROP_PTR("dma", SysBusPCNetState, state.dma_opaque), |
|
2187 |
DEFINE_NIC_PROPERTIES(SysBusPCNetState, state.conf), |
|
2188 |
DEFINE_PROP_END_OF_LIST(), |
|
2189 |
} |
|
2190 |
}; |
|
2191 |
|
|
2192 |
#endif /* TARGET_SPARC */ |
|
2193 |
|
|
2194 | 2061 |
static PCIDeviceInfo pcnet_info = { |
2195 | 2062 |
.qdev.name = "pcnet", |
2196 | 2063 |
.qdev.size = sizeof(PCIPCNetState), |
... | ... | |
2206 | 2073 |
static void pcnet_register_devices(void) |
2207 | 2074 |
{ |
2208 | 2075 |
pci_qdev_register(&pcnet_info); |
2209 |
#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) |
|
2210 |
sysbus_register_withprop(&lance_info); |
|
2211 |
#endif |
|
2212 | 2076 |
} |
2213 | 2077 |
|
2214 | 2078 |
device_init(pcnet_register_devices) |
b/hw/pcnet.h | ||
---|---|---|
1 |
#define PCNET_IOPORT_SIZE 0x20 |
|
2 |
#define PCNET_PNPMMIO_SIZE 0x20 |
|
3 |
|
|
4 |
#define PCNET_LOOPTEST_CRC 1 |
|
5 |
#define PCNET_LOOPTEST_NOCRC 2 |
|
6 |
|
|
7 |
|
|
8 |
typedef struct PCNetState_st PCNetState; |
|
9 |
|
|
10 |
struct PCNetState_st { |
|
11 |
VLANClientState *vc; |
|
12 |
NICConf conf; |
|
13 |
QEMUTimer *poll_timer; |
|
14 |
int rap, isr, lnkst; |
|
15 |
uint32_t rdra, tdra; |
|
16 |
uint8_t prom[16]; |
|
17 |
uint16_t csr[128]; |
|
18 |
uint16_t bcr[32]; |
|
19 |
uint64_t timer; |
|
20 |
int mmio_index, xmit_pos; |
|
21 |
uint8_t buffer[4096]; |
|
22 |
int tx_busy; |
|
23 |
qemu_irq irq; |
|
24 |
void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr, |
|
25 |
uint8_t *buf, int len, int do_bswap); |
|
26 |
void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr, |
|
27 |
uint8_t *buf, int len, int do_bswap); |
|
28 |
void *dma_opaque; |
|
29 |
int looptest; |
|
30 |
}; |
|
31 |
|
|
32 |
void pcnet_h_reset(void *opaque); |
|
33 |
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val); |
|
34 |
uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr); |
|
35 |
void pcnet_common_cleanup(PCNetState *d); |
|
36 |
int pcnet_common_init(DeviceState *dev, PCNetState *s, |
|
37 |
NetCleanup *cleanup); |
|
38 |
void pcnet_save(QEMUFile *f, void *opaque); |
|
39 |
int pcnet_load(QEMUFile *f, void *opaque, int version_id); |
Also available in: Unified diff