Annotation of qemu/hw/mipsnet.c, revision 1.1.1.9

1.1       root        1: #include "hw.h"
                      2: #include "net.h"
1.1.1.9 ! root        3: #include "trace.h"
        !             4: #include "sysbus.h"
1.1       root        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: typedef struct MIPSnetState {
1.1.1.9 ! root       23:     SysBusDevice busdev;
        !            24: 
1.1       root       25:     uint32_t busy;
                     26:     uint32_t rx_count;
                     27:     uint32_t rx_read;
                     28:     uint32_t tx_count;
                     29:     uint32_t tx_written;
                     30:     uint32_t intctl;
                     31:     uint8_t rx_buffer[MAX_ETH_FRAME_SIZE];
                     32:     uint8_t tx_buffer[MAX_ETH_FRAME_SIZE];
1.1.1.9 ! root       33:     MemoryRegion io;
1.1       root       34:     qemu_irq irq;
1.1.1.5   root       35:     NICState *nic;
                     36:     NICConf conf;
1.1       root       37: } MIPSnetState;
                     38: 
                     39: static void mipsnet_reset(MIPSnetState *s)
                     40: {
                     41:     s->busy = 1;
                     42:     s->rx_count = 0;
                     43:     s->rx_read = 0;
                     44:     s->tx_count = 0;
                     45:     s->tx_written = 0;
                     46:     s->intctl = 0;
                     47:     memset(s->rx_buffer, 0, MAX_ETH_FRAME_SIZE);
                     48:     memset(s->tx_buffer, 0, MAX_ETH_FRAME_SIZE);
                     49: }
                     50: 
                     51: static void mipsnet_update_irq(MIPSnetState *s)
                     52: {
                     53:     int isr = !!s->intctl;
1.1.1.9 ! root       54:     trace_mipsnet_irq(isr, s->intctl);
1.1       root       55:     qemu_set_irq(s->irq, isr);
                     56: }
                     57: 
                     58: static int mipsnet_buffer_full(MIPSnetState *s)
                     59: {
                     60:     if (s->rx_count >= MAX_ETH_FRAME_SIZE)
                     61:         return 1;
                     62:     return 0;
                     63: }
                     64: 
1.1.1.5   root       65: static int mipsnet_can_receive(VLANClientState *nc)
1.1       root       66: {
1.1.1.5   root       67:     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1.1       root       68: 
                     69:     if (s->busy)
                     70:         return 0;
                     71:     return !mipsnet_buffer_full(s);
                     72: }
                     73: 
1.1.1.5   root       74: static ssize_t mipsnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
1.1       root       75: {
1.1.1.5   root       76:     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1.1       root       77: 
1.1.1.9 ! root       78:     trace_mipsnet_receive(size);
1.1.1.5   root       79:     if (!mipsnet_can_receive(nc))
1.1.1.4   root       80:         return -1;
1.1       root       81: 
                     82:     s->busy = 1;
                     83: 
                     84:     /* Just accept everything. */
                     85: 
                     86:     /* Write packet data. */
                     87:     memcpy(s->rx_buffer, buf, size);
                     88: 
                     89:     s->rx_count = size;
                     90:     s->rx_read = 0;
                     91: 
                     92:     /* Now we can signal we have received something. */
                     93:     s->intctl |= MIPSNET_INTCTL_RXDONE;
                     94:     mipsnet_update_irq(s);
1.1.1.4   root       95: 
                     96:     return size;
1.1       root       97: }
                     98: 
1.1.1.9 ! root       99: static uint64_t mipsnet_ioport_read(void *opaque, target_phys_addr_t addr,
        !           100:                                     unsigned int size)
1.1       root      101: {
                    102:     MIPSnetState *s = opaque;
                    103:     int ret = 0;
                    104: 
                    105:     addr &= 0x3f;
                    106:     switch (addr) {
                    107:     case MIPSNET_DEV_ID:
1.1.1.2   root      108:        ret = be32_to_cpu(0x4d495053);          /* MIPS */
1.1       root      109:         break;
                    110:     case MIPSNET_DEV_ID + 4:
1.1.1.2   root      111:        ret = be32_to_cpu(0x4e455430);          /* NET0 */
1.1       root      112:         break;
                    113:     case MIPSNET_BUSY:
                    114:        ret = s->busy;
                    115:         break;
                    116:     case MIPSNET_RX_DATA_COUNT:
                    117:        ret = s->rx_count;
                    118:         break;
                    119:     case MIPSNET_TX_DATA_COUNT:
                    120:        ret = s->tx_count;
                    121:         break;
                    122:     case MIPSNET_INT_CTL:
                    123:        ret = s->intctl;
                    124:         s->intctl &= ~MIPSNET_INTCTL_TESTBIT;
                    125:         break;
                    126:     case MIPSNET_INTERRUPT_INFO:
                    127:         /* XXX: This seems to be a per-VPE interrupt number. */
                    128:        ret = 0;
                    129:         break;
                    130:     case MIPSNET_RX_DATA_BUFFER:
                    131:         if (s->rx_count) {
                    132:             s->rx_count--;
                    133:             ret = s->rx_buffer[s->rx_read++];
                    134:         }
                    135:         break;
                    136:     /* Reads as zero. */
                    137:     case MIPSNET_TX_DATA_BUFFER:
                    138:     default:
                    139:         break;
                    140:     }
1.1.1.9 ! root      141:     trace_mipsnet_read(addr, ret);
1.1       root      142:     return ret;
                    143: }
                    144: 
1.1.1.9 ! root      145: static void mipsnet_ioport_write(void *opaque, target_phys_addr_t addr,
        !           146:                                  uint64_t val, unsigned int size)
1.1       root      147: {
                    148:     MIPSnetState *s = opaque;
                    149: 
                    150:     addr &= 0x3f;
1.1.1.9 ! root      151:     trace_mipsnet_write(addr, val);
1.1       root      152:     switch (addr) {
                    153:     case MIPSNET_TX_DATA_COUNT:
                    154:        s->tx_count = (val <= MAX_ETH_FRAME_SIZE) ? val : 0;
                    155:         s->tx_written = 0;
                    156:         break;
                    157:     case MIPSNET_INT_CTL:
                    158:         if (val & MIPSNET_INTCTL_TXDONE) {
                    159:             s->intctl &= ~MIPSNET_INTCTL_TXDONE;
                    160:         } else if (val & MIPSNET_INTCTL_RXDONE) {
                    161:             s->intctl &= ~MIPSNET_INTCTL_RXDONE;
                    162:         } else if (val & MIPSNET_INTCTL_TESTBIT) {
                    163:             mipsnet_reset(s);
                    164:             s->intctl |= MIPSNET_INTCTL_TESTBIT;
                    165:         } else if (!val) {
                    166:             /* ACK testbit interrupt, flag was cleared on read. */
                    167:         }
                    168:         s->busy = !!s->intctl;
                    169:         mipsnet_update_irq(s);
                    170:         break;
                    171:     case MIPSNET_TX_DATA_BUFFER:
                    172:         s->tx_buffer[s->tx_written++] = val;
                    173:         if (s->tx_written == s->tx_count) {
                    174:             /* Send buffer. */
1.1.1.9 ! root      175:             trace_mipsnet_send(s->tx_count);
1.1.1.5   root      176:             qemu_send_packet(&s->nic->nc, s->tx_buffer, s->tx_count);
1.1       root      177:             s->tx_count = s->tx_written = 0;
                    178:             s->intctl |= MIPSNET_INTCTL_TXDONE;
                    179:             s->busy = 1;
                    180:             mipsnet_update_irq(s);
                    181:         }
                    182:         break;
                    183:     /* Read-only registers */
                    184:     case MIPSNET_DEV_ID:
                    185:     case MIPSNET_BUSY:
                    186:     case MIPSNET_RX_DATA_COUNT:
                    187:     case MIPSNET_INTERRUPT_INFO:
                    188:     case MIPSNET_RX_DATA_BUFFER:
                    189:     default:
                    190:         break;
                    191:     }
                    192: }
                    193: 
1.1.1.8   root      194: static const VMStateDescription vmstate_mipsnet = {
                    195:     .name = "mipsnet",
                    196:     .version_id = 0,
                    197:     .minimum_version_id = 0,
                    198:     .minimum_version_id_old = 0,
                    199:     .fields      = (VMStateField[]) {
                    200:         VMSTATE_UINT32(busy, MIPSnetState),
                    201:         VMSTATE_UINT32(rx_count, MIPSnetState),
                    202:         VMSTATE_UINT32(rx_read, MIPSnetState),
                    203:         VMSTATE_UINT32(tx_count, MIPSnetState),
                    204:         VMSTATE_UINT32(tx_written, MIPSnetState),
                    205:         VMSTATE_UINT32(intctl, MIPSnetState),
                    206:         VMSTATE_BUFFER(rx_buffer, MIPSnetState),
                    207:         VMSTATE_BUFFER(tx_buffer, MIPSnetState),
                    208:         VMSTATE_END_OF_LIST()
                    209:     }
                    210: };
1.1       root      211: 
1.1.1.5   root      212: static void mipsnet_cleanup(VLANClientState *nc)
1.1.1.3   root      213: {
1.1.1.5   root      214:     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1.1.1.3   root      215: 
1.1.1.9 ! root      216:     s->nic = NULL;
1.1.1.3   root      217: }
                    218: 
1.1.1.5   root      219: static NetClientInfo net_mipsnet_info = {
                    220:     .type = NET_CLIENT_TYPE_NIC,
                    221:     .size = sizeof(NICState),
                    222:     .can_receive = mipsnet_can_receive,
                    223:     .receive = mipsnet_receive,
                    224:     .cleanup = mipsnet_cleanup,
                    225: };
                    226: 
1.1.1.9 ! root      227: static MemoryRegionOps mipsnet_ioport_ops = {
        !           228:     .read = mipsnet_ioport_read,
        !           229:     .write = mipsnet_ioport_write,
        !           230:     .impl.min_access_size = 1,
        !           231:     .impl.max_access_size = 4,
        !           232: };
1.1       root      233: 
1.1.1.9 ! root      234: static int mipsnet_sysbus_init(SysBusDevice *dev)
        !           235: {
        !           236:     MIPSnetState *s = DO_UPCAST(MIPSnetState, busdev, dev);
1.1       root      237: 
1.1.1.9 ! root      238:     memory_region_init_io(&s->io, &mipsnet_ioport_ops, s, "mipsnet-io", 36);
        !           239:     sysbus_init_mmio_region(dev, &s->io);
        !           240:     sysbus_init_irq(dev, &s->irq);
        !           241: 
        !           242:     s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
        !           243:                           dev->qdev.info->name, dev->qdev.id, s);
        !           244:     qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
1.1       root      245: 
1.1.1.9 ! root      246:     return 0;
        !           247: }
1.1.1.5   root      248: 
1.1.1.9 ! root      249: static void mipsnet_sysbus_reset(DeviceState *dev)
        !           250: {
        !           251:     MIPSnetState *s = DO_UPCAST(MIPSnetState, busdev.qdev, dev);
        !           252:     mipsnet_reset(s);
        !           253: }
1.1.1.5   root      254: 
1.1.1.9 ! root      255: static SysBusDeviceInfo mipsnet_info = {
        !           256:     .init = mipsnet_sysbus_init,
        !           257:     .qdev.name = "mipsnet",
        !           258:     .qdev.desc = "MIPS Simulator network device",
        !           259:     .qdev.size = sizeof(MIPSnetState),
        !           260:     .qdev.vmsd = &vmstate_mipsnet,
        !           261:     .qdev.reset = mipsnet_sysbus_reset,
        !           262:     .qdev.props = (Property[]) {
        !           263:         DEFINE_NIC_PROPERTIES(MIPSnetState, conf),
        !           264:         DEFINE_PROP_END_OF_LIST(),
1.1.1.5   root      265:     }
1.1.1.9 ! root      266: };
1.1       root      267: 
1.1.1.9 ! root      268: static void mipsnet_register_devices(void)
        !           269: {
        !           270:     sysbus_register_withprop(&mipsnet_info);
1.1       root      271: }
1.1.1.9 ! root      272: 
        !           273: device_init(mipsnet_register_devices)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.