1 #include "qemu/osdep.h"
3 #include "hw/qdev-properties.h"
5 #include "qemu/module.h"
8 #include "migration/vmstate.h"
9 #include "qom/object.h"
11 /* MIPSnet register offsets */
13 #define MIPSNET_DEV_ID 0x00
14 #define MIPSNET_BUSY 0x08
15 #define MIPSNET_RX_DATA_COUNT 0x0c
16 #define MIPSNET_TX_DATA_COUNT 0x10
17 #define MIPSNET_INT_CTL 0x14
18 # define MIPSNET_INTCTL_TXDONE 0x00000001
19 # define MIPSNET_INTCTL_RXDONE 0x00000002
20 # define MIPSNET_INTCTL_TESTBIT 0x80000000
21 #define MIPSNET_INTERRUPT_INFO 0x18
22 #define MIPSNET_RX_DATA_BUFFER 0x1c
23 #define MIPSNET_TX_DATA_BUFFER 0x20
25 #define MAX_ETH_FRAME_SIZE 1514
27 #define TYPE_MIPS_NET "mipsnet"
28 OBJECT_DECLARE_SIMPLE_TYPE(MIPSnetState
, MIPS_NET
)
31 SysBusDevice parent_obj
;
39 uint8_t rx_buffer
[MAX_ETH_FRAME_SIZE
];
40 uint8_t tx_buffer
[MAX_ETH_FRAME_SIZE
];
47 static void mipsnet_reset(MIPSnetState
*s
)
55 memset(s
->rx_buffer
, 0, MAX_ETH_FRAME_SIZE
);
56 memset(s
->tx_buffer
, 0, MAX_ETH_FRAME_SIZE
);
59 static void mipsnet_update_irq(MIPSnetState
*s
)
61 int isr
= !!s
->intctl
;
62 trace_mipsnet_irq(isr
, s
->intctl
);
63 qemu_set_irq(s
->irq
, isr
);
66 static int mipsnet_buffer_full(MIPSnetState
*s
)
68 if (s
->rx_count
>= MAX_ETH_FRAME_SIZE
) {
74 static int mipsnet_can_receive(NetClientState
*nc
)
76 MIPSnetState
*s
= qemu_get_nic_opaque(nc
);
81 return !mipsnet_buffer_full(s
);
84 static ssize_t
mipsnet_receive(NetClientState
*nc
,
85 const uint8_t *buf
, size_t size
)
87 MIPSnetState
*s
= qemu_get_nic_opaque(nc
);
89 trace_mipsnet_receive(size
);
90 if (!mipsnet_can_receive(nc
)) {
94 if (size
>= sizeof(s
->rx_buffer
)) {
99 /* Just accept everything. */
101 /* Write packet data. */
102 memcpy(s
->rx_buffer
, buf
, size
);
107 /* Now we can signal we have received something. */
108 s
->intctl
|= MIPSNET_INTCTL_RXDONE
;
109 mipsnet_update_irq(s
);
114 static uint64_t mipsnet_ioport_read(void *opaque
, hwaddr addr
,
117 MIPSnetState
*s
= opaque
;
123 ret
= be32_to_cpu(0x4d495053); /* MIPS */
125 case MIPSNET_DEV_ID
+ 4:
126 ret
= be32_to_cpu(0x4e455430); /* NET0 */
131 case MIPSNET_RX_DATA_COUNT
:
134 case MIPSNET_TX_DATA_COUNT
:
137 case MIPSNET_INT_CTL
:
139 s
->intctl
&= ~MIPSNET_INTCTL_TESTBIT
;
141 case MIPSNET_INTERRUPT_INFO
:
142 /* XXX: This seems to be a per-VPE interrupt number. */
145 case MIPSNET_RX_DATA_BUFFER
:
148 ret
= s
->rx_buffer
[s
->rx_read
++];
149 if (mipsnet_can_receive(s
->nic
->ncs
)) {
150 qemu_flush_queued_packets(qemu_get_queue(s
->nic
));
155 case MIPSNET_TX_DATA_BUFFER
:
159 trace_mipsnet_read(addr
, ret
);
163 static void mipsnet_ioport_write(void *opaque
, hwaddr addr
,
164 uint64_t val
, unsigned int size
)
166 MIPSnetState
*s
= opaque
;
169 trace_mipsnet_write(addr
, val
);
171 case MIPSNET_TX_DATA_COUNT
:
172 s
->tx_count
= (val
<= MAX_ETH_FRAME_SIZE
) ? val
: 0;
175 case MIPSNET_INT_CTL
:
176 if (val
& MIPSNET_INTCTL_TXDONE
) {
177 s
->intctl
&= ~MIPSNET_INTCTL_TXDONE
;
178 } else if (val
& MIPSNET_INTCTL_RXDONE
) {
179 s
->intctl
&= ~MIPSNET_INTCTL_RXDONE
;
180 } else if (val
& MIPSNET_INTCTL_TESTBIT
) {
182 s
->intctl
|= MIPSNET_INTCTL_TESTBIT
;
184 /* ACK testbit interrupt, flag was cleared on read. */
186 s
->busy
= !!s
->intctl
;
187 mipsnet_update_irq(s
);
188 if (mipsnet_can_receive(s
->nic
->ncs
)) {
189 qemu_flush_queued_packets(qemu_get_queue(s
->nic
));
192 case MIPSNET_TX_DATA_BUFFER
:
193 s
->tx_buffer
[s
->tx_written
++] = val
;
194 if ((s
->tx_written
>= MAX_ETH_FRAME_SIZE
)
195 || (s
->tx_written
== s
->tx_count
)) {
197 trace_mipsnet_send(s
->tx_written
);
198 qemu_send_packet(qemu_get_queue(s
->nic
),
199 s
->tx_buffer
, s
->tx_written
);
200 s
->tx_count
= s
->tx_written
= 0;
201 s
->intctl
|= MIPSNET_INTCTL_TXDONE
;
203 mipsnet_update_irq(s
);
206 /* Read-only registers */
209 case MIPSNET_RX_DATA_COUNT
:
210 case MIPSNET_INTERRUPT_INFO
:
211 case MIPSNET_RX_DATA_BUFFER
:
217 static const VMStateDescription vmstate_mipsnet
= {
220 .minimum_version_id
= 0,
221 .fields
= (const VMStateField
[]) {
222 VMSTATE_UINT32(busy
, MIPSnetState
),
223 VMSTATE_UINT32(rx_count
, MIPSnetState
),
224 VMSTATE_UINT32(rx_read
, MIPSnetState
),
225 VMSTATE_UINT32(tx_count
, MIPSnetState
),
226 VMSTATE_UINT32(tx_written
, MIPSnetState
),
227 VMSTATE_UINT32(intctl
, MIPSnetState
),
228 VMSTATE_BUFFER(rx_buffer
, MIPSnetState
),
229 VMSTATE_BUFFER(tx_buffer
, MIPSnetState
),
230 VMSTATE_END_OF_LIST()
234 static NetClientInfo net_mipsnet_info
= {
235 .type
= NET_CLIENT_DRIVER_NIC
,
236 .size
= sizeof(NICState
),
237 .receive
= mipsnet_receive
,
240 static const MemoryRegionOps mipsnet_ioport_ops
= {
241 .read
= mipsnet_ioport_read
,
242 .write
= mipsnet_ioport_write
,
243 .impl
.min_access_size
= 1,
244 .impl
.max_access_size
= 4,
247 static void mipsnet_realize(DeviceState
*dev
, Error
**errp
)
249 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
250 MIPSnetState
*s
= MIPS_NET(dev
);
252 memory_region_init_io(&s
->io
, OBJECT(dev
), &mipsnet_ioport_ops
, s
,
254 sysbus_init_mmio(sbd
, &s
->io
);
255 sysbus_init_irq(sbd
, &s
->irq
);
257 s
->nic
= qemu_new_nic(&net_mipsnet_info
, &s
->conf
,
258 object_get_typename(OBJECT(dev
)), dev
->id
,
259 &dev
->mem_reentrancy_guard
, s
);
260 qemu_format_nic_info_str(qemu_get_queue(s
->nic
), s
->conf
.macaddr
.a
);
263 static void mipsnet_sysbus_reset(DeviceState
*dev
)
265 MIPSnetState
*s
= MIPS_NET(dev
);
269 static Property mipsnet_properties
[] = {
270 DEFINE_NIC_PROPERTIES(MIPSnetState
, conf
),
271 DEFINE_PROP_END_OF_LIST(),
274 static void mipsnet_class_init(ObjectClass
*klass
, void *data
)
276 DeviceClass
*dc
= DEVICE_CLASS(klass
);
278 dc
->realize
= mipsnet_realize
;
279 set_bit(DEVICE_CATEGORY_NETWORK
, dc
->categories
);
280 dc
->desc
= "MIPS Simulator network device";
281 dc
->reset
= mipsnet_sysbus_reset
;
282 dc
->vmsd
= &vmstate_mipsnet
;
283 device_class_set_props(dc
, mipsnet_properties
);
286 static const TypeInfo mipsnet_info
= {
287 .name
= TYPE_MIPS_NET
,
288 .parent
= TYPE_SYS_BUS_DEVICE
,
289 .instance_size
= sizeof(MIPSnetState
),
290 .class_init
= mipsnet_class_init
,
293 static void mipsnet_register_types(void)
295 type_register_static(&mipsnet_info
);
298 type_init(mipsnet_register_types
)