Statistics
| Branch: | Revision:

root / hw / net / mipsnet.c @ a4dbb8bd

History | View | Annotate | Download (7.4 kB)

1
#include "hw/hw.h"
2
#include "net/net.h"
3
#include "trace.h"
4
#include "hw/sysbus.h"
5

    
6
/* MIPSnet register offsets */
7

    
8
#define MIPSNET_DEV_ID                0x00
9
#define MIPSNET_BUSY                0x08
10
#define MIPSNET_RX_DATA_COUNT        0x0c
11
#define MIPSNET_TX_DATA_COUNT        0x10
12
#define MIPSNET_INT_CTL                0x14
13
# define MIPSNET_INTCTL_TXDONE                0x00000001
14
# define MIPSNET_INTCTL_RXDONE                0x00000002
15
# define MIPSNET_INTCTL_TESTBIT                0x80000000
16
#define MIPSNET_INTERRUPT_INFO        0x18
17
#define MIPSNET_RX_DATA_BUFFER        0x1c
18
#define MIPSNET_TX_DATA_BUFFER        0x20
19

    
20
#define MAX_ETH_FRAME_SIZE        1514
21

    
22
#define TYPE_MIPS_NET "mipsnet"
23
#define MIPS_NET(obj) OBJECT_CHECK(MIPSnetState, (obj), TYPE_MIPS_NET)
24

    
25
typedef struct MIPSnetState {
26
    SysBusDevice parent_obj;
27

    
28
    uint32_t busy;
29
    uint32_t rx_count;
30
    uint32_t rx_read;
31
    uint32_t tx_count;
32
    uint32_t tx_written;
33
    uint32_t intctl;
34
    uint8_t rx_buffer[MAX_ETH_FRAME_SIZE];
35
    uint8_t tx_buffer[MAX_ETH_FRAME_SIZE];
36
    MemoryRegion io;
37
    qemu_irq irq;
38
    NICState *nic;
39
    NICConf conf;
40
} MIPSnetState;
41

    
42
static void mipsnet_reset(MIPSnetState *s)
43
{
44
    s->busy = 1;
45
    s->rx_count = 0;
46
    s->rx_read = 0;
47
    s->tx_count = 0;
48
    s->tx_written = 0;
49
    s->intctl = 0;
50
    memset(s->rx_buffer, 0, MAX_ETH_FRAME_SIZE);
51
    memset(s->tx_buffer, 0, MAX_ETH_FRAME_SIZE);
52
}
53

    
54
static void mipsnet_update_irq(MIPSnetState *s)
55
{
56
    int isr = !!s->intctl;
57
    trace_mipsnet_irq(isr, s->intctl);
58
    qemu_set_irq(s->irq, isr);
59
}
60

    
61
static int mipsnet_buffer_full(MIPSnetState *s)
62
{
63
    if (s->rx_count >= MAX_ETH_FRAME_SIZE)
64
        return 1;
65
    return 0;
66
}
67

    
68
static int mipsnet_can_receive(NetClientState *nc)
69
{
70
    MIPSnetState *s = qemu_get_nic_opaque(nc);
71

    
72
    if (s->busy)
73
        return 0;
74
    return !mipsnet_buffer_full(s);
75
}
76

    
77
static ssize_t mipsnet_receive(NetClientState *nc, const uint8_t *buf, size_t size)
78
{
79
    MIPSnetState *s = qemu_get_nic_opaque(nc);
80

    
81
    trace_mipsnet_receive(size);
82
    if (!mipsnet_can_receive(nc))
83
        return -1;
84

    
85
    s->busy = 1;
86

    
87
    /* Just accept everything. */
88

    
89
    /* Write packet data. */
90
    memcpy(s->rx_buffer, buf, size);
91

    
92
    s->rx_count = size;
93
    s->rx_read = 0;
94

    
95
    /* Now we can signal we have received something. */
96
    s->intctl |= MIPSNET_INTCTL_RXDONE;
97
    mipsnet_update_irq(s);
98

    
99
    return size;
100
}
101

    
102
static uint64_t mipsnet_ioport_read(void *opaque, hwaddr addr,
103
                                    unsigned int size)
104
{
105
    MIPSnetState *s = opaque;
106
    int ret = 0;
107

    
108
    addr &= 0x3f;
109
    switch (addr) {
110
    case MIPSNET_DEV_ID:
111
        ret = be32_to_cpu(0x4d495053);                /* MIPS */
112
        break;
113
    case MIPSNET_DEV_ID + 4:
114
        ret = be32_to_cpu(0x4e455430);                /* NET0 */
115
        break;
116
    case MIPSNET_BUSY:
117
        ret = s->busy;
118
        break;
119
    case MIPSNET_RX_DATA_COUNT:
120
        ret = s->rx_count;
121
        break;
122
    case MIPSNET_TX_DATA_COUNT:
123
        ret = s->tx_count;
124
        break;
125
    case MIPSNET_INT_CTL:
126
        ret = s->intctl;
127
        s->intctl &= ~MIPSNET_INTCTL_TESTBIT;
128
        break;
129
    case MIPSNET_INTERRUPT_INFO:
130
        /* XXX: This seems to be a per-VPE interrupt number. */
131
        ret = 0;
132
        break;
133
    case MIPSNET_RX_DATA_BUFFER:
134
        if (s->rx_count) {
135
            s->rx_count--;
136
            ret = s->rx_buffer[s->rx_read++];
137
        }
138
        break;
139
    /* Reads as zero. */
140
    case MIPSNET_TX_DATA_BUFFER:
141
    default:
142
        break;
143
    }
144
    trace_mipsnet_read(addr, ret);
145
    return ret;
146
}
147

    
148
static void mipsnet_ioport_write(void *opaque, hwaddr addr,
149
                                 uint64_t val, unsigned int size)
150
{
151
    MIPSnetState *s = opaque;
152

    
153
    addr &= 0x3f;
154
    trace_mipsnet_write(addr, val);
155
    switch (addr) {
156
    case MIPSNET_TX_DATA_COUNT:
157
        s->tx_count = (val <= MAX_ETH_FRAME_SIZE) ? val : 0;
158
        s->tx_written = 0;
159
        break;
160
    case MIPSNET_INT_CTL:
161
        if (val & MIPSNET_INTCTL_TXDONE) {
162
            s->intctl &= ~MIPSNET_INTCTL_TXDONE;
163
        } else if (val & MIPSNET_INTCTL_RXDONE) {
164
            s->intctl &= ~MIPSNET_INTCTL_RXDONE;
165
        } else if (val & MIPSNET_INTCTL_TESTBIT) {
166
            mipsnet_reset(s);
167
            s->intctl |= MIPSNET_INTCTL_TESTBIT;
168
        } else if (!val) {
169
            /* ACK testbit interrupt, flag was cleared on read. */
170
        }
171
        s->busy = !!s->intctl;
172
        mipsnet_update_irq(s);
173
        break;
174
    case MIPSNET_TX_DATA_BUFFER:
175
        s->tx_buffer[s->tx_written++] = val;
176
        if (s->tx_written == s->tx_count) {
177
            /* Send buffer. */
178
            trace_mipsnet_send(s->tx_count);
179
            qemu_send_packet(qemu_get_queue(s->nic), s->tx_buffer, s->tx_count);
180
            s->tx_count = s->tx_written = 0;
181
            s->intctl |= MIPSNET_INTCTL_TXDONE;
182
            s->busy = 1;
183
            mipsnet_update_irq(s);
184
        }
185
        break;
186
    /* Read-only registers */
187
    case MIPSNET_DEV_ID:
188
    case MIPSNET_BUSY:
189
    case MIPSNET_RX_DATA_COUNT:
190
    case MIPSNET_INTERRUPT_INFO:
191
    case MIPSNET_RX_DATA_BUFFER:
192
    default:
193
        break;
194
    }
195
}
196

    
197
static const VMStateDescription vmstate_mipsnet = {
198
    .name = "mipsnet",
199
    .version_id = 0,
200
    .minimum_version_id = 0,
201
    .minimum_version_id_old = 0,
202
    .fields      = (VMStateField[]) {
203
        VMSTATE_UINT32(busy, MIPSnetState),
204
        VMSTATE_UINT32(rx_count, MIPSnetState),
205
        VMSTATE_UINT32(rx_read, MIPSnetState),
206
        VMSTATE_UINT32(tx_count, MIPSnetState),
207
        VMSTATE_UINT32(tx_written, MIPSnetState),
208
        VMSTATE_UINT32(intctl, MIPSnetState),
209
        VMSTATE_BUFFER(rx_buffer, MIPSnetState),
210
        VMSTATE_BUFFER(tx_buffer, MIPSnetState),
211
        VMSTATE_END_OF_LIST()
212
    }
213
};
214

    
215
static void mipsnet_cleanup(NetClientState *nc)
216
{
217
    MIPSnetState *s = qemu_get_nic_opaque(nc);
218

    
219
    s->nic = NULL;
220
}
221

    
222
static NetClientInfo net_mipsnet_info = {
223
    .type = NET_CLIENT_OPTIONS_KIND_NIC,
224
    .size = sizeof(NICState),
225
    .can_receive = mipsnet_can_receive,
226
    .receive = mipsnet_receive,
227
    .cleanup = mipsnet_cleanup,
228
};
229

    
230
static const MemoryRegionOps mipsnet_ioport_ops = {
231
    .read = mipsnet_ioport_read,
232
    .write = mipsnet_ioport_write,
233
    .impl.min_access_size = 1,
234
    .impl.max_access_size = 4,
235
};
236

    
237
static int mipsnet_sysbus_init(SysBusDevice *sbd)
238
{
239
    DeviceState *dev = DEVICE(sbd);
240
    MIPSnetState *s = MIPS_NET(dev);
241

    
242
    memory_region_init_io(&s->io, OBJECT(dev), &mipsnet_ioport_ops, s,
243
                          "mipsnet-io", 36);
244
    sysbus_init_mmio(sbd, &s->io);
245
    sysbus_init_irq(sbd, &s->irq);
246

    
247
    s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
248
                          object_get_typename(OBJECT(dev)), dev->id, s);
249
    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
250

    
251
    return 0;
252
}
253

    
254
static void mipsnet_sysbus_reset(DeviceState *dev)
255
{
256
    MIPSnetState *s = MIPS_NET(dev);
257
    mipsnet_reset(s);
258
}
259

    
260
static Property mipsnet_properties[] = {
261
    DEFINE_NIC_PROPERTIES(MIPSnetState, conf),
262
    DEFINE_PROP_END_OF_LIST(),
263
};
264

    
265
static void mipsnet_class_init(ObjectClass *klass, void *data)
266
{
267
    DeviceClass *dc = DEVICE_CLASS(klass);
268
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
269

    
270
    k->init = mipsnet_sysbus_init;
271
    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
272
    dc->desc = "MIPS Simulator network device";
273
    dc->reset = mipsnet_sysbus_reset;
274
    dc->vmsd = &vmstate_mipsnet;
275
    dc->props = mipsnet_properties;
276
}
277

    
278
static const TypeInfo mipsnet_info = {
279
    .name          = TYPE_MIPS_NET,
280
    .parent        = TYPE_SYS_BUS_DEVICE,
281
    .instance_size = sizeof(MIPSnetState),
282
    .class_init    = mipsnet_class_init,
283
};
284

    
285
static void mipsnet_register_types(void)
286
{
287
    type_register_static(&mipsnet_info);
288
}
289

    
290
type_init(mipsnet_register_types)