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

1.1       root        1: #include "hw.h"
                      2: #include "mips.h"
                      3: #include "net.h"
                      4: #include "isa.h"
                      5: 
                      6: //#define DEBUG_MIPSNET_SEND
                      7: //#define DEBUG_MIPSNET_RECEIVE
                      8: //#define DEBUG_MIPSNET_DATA
                      9: //#define DEBUG_MIPSNET_IRQ
                     10: 
                     11: /* MIPSnet register offsets */
                     12: 
                     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
                     24: 
                     25: #define MAX_ETH_FRAME_SIZE     1514
                     26: 
                     27: typedef struct MIPSnetState {
                     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];
1.1.1.3   root       36:     int io_base;
1.1       root       37:     qemu_irq irq;
1.1.1.5   root       38:     NICState *nic;
                     39:     NICConf conf;
1.1       root       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: #ifdef DEBUG_MIPSNET_IRQ
                     58:     printf("mipsnet: Set IRQ to %d (%02x)\n", isr, s->intctl);
                     59: #endif
                     60:     qemu_set_irq(s->irq, isr);
                     61: }
                     62: 
                     63: static int mipsnet_buffer_full(MIPSnetState *s)
                     64: {
                     65:     if (s->rx_count >= MAX_ETH_FRAME_SIZE)
                     66:         return 1;
                     67:     return 0;
                     68: }
                     69: 
1.1.1.5   root       70: static int mipsnet_can_receive(VLANClientState *nc)
1.1       root       71: {
1.1.1.5   root       72:     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1.1       root       73: 
                     74:     if (s->busy)
                     75:         return 0;
                     76:     return !mipsnet_buffer_full(s);
                     77: }
                     78: 
1.1.1.5   root       79: static ssize_t mipsnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
1.1       root       80: {
1.1.1.5   root       81:     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1.1       root       82: 
                     83: #ifdef DEBUG_MIPSNET_RECEIVE
1.1.1.7   root       84:     printf("mipsnet: receiving len=%zu\n", size);
1.1       root       85: #endif
1.1.1.5   root       86:     if (!mipsnet_can_receive(nc))
1.1.1.4   root       87:         return -1;
1.1       root       88: 
                     89:     s->busy = 1;
                     90: 
                     91:     /* Just accept everything. */
                     92: 
                     93:     /* Write packet data. */
                     94:     memcpy(s->rx_buffer, buf, size);
                     95: 
                     96:     s->rx_count = size;
                     97:     s->rx_read = 0;
                     98: 
                     99:     /* Now we can signal we have received something. */
                    100:     s->intctl |= MIPSNET_INTCTL_RXDONE;
                    101:     mipsnet_update_irq(s);
1.1.1.4   root      102: 
                    103:     return size;
1.1       root      104: }
                    105: 
                    106: static uint32_t mipsnet_ioport_read(void *opaque, uint32_t addr)
                    107: {
                    108:     MIPSnetState *s = opaque;
                    109:     int ret = 0;
                    110: 
                    111:     addr &= 0x3f;
                    112:     switch (addr) {
                    113:     case MIPSNET_DEV_ID:
1.1.1.2   root      114:        ret = be32_to_cpu(0x4d495053);          /* MIPS */
1.1       root      115:         break;
                    116:     case MIPSNET_DEV_ID + 4:
1.1.1.2   root      117:        ret = be32_to_cpu(0x4e455430);          /* NET0 */
1.1       root      118:         break;
                    119:     case MIPSNET_BUSY:
                    120:        ret = s->busy;
                    121:         break;
                    122:     case MIPSNET_RX_DATA_COUNT:
                    123:        ret = s->rx_count;
                    124:         break;
                    125:     case MIPSNET_TX_DATA_COUNT:
                    126:        ret = s->tx_count;
                    127:         break;
                    128:     case MIPSNET_INT_CTL:
                    129:        ret = s->intctl;
                    130:         s->intctl &= ~MIPSNET_INTCTL_TESTBIT;
                    131:         break;
                    132:     case MIPSNET_INTERRUPT_INFO:
                    133:         /* XXX: This seems to be a per-VPE interrupt number. */
                    134:        ret = 0;
                    135:         break;
                    136:     case MIPSNET_RX_DATA_BUFFER:
                    137:         if (s->rx_count) {
                    138:             s->rx_count--;
                    139:             ret = s->rx_buffer[s->rx_read++];
                    140:         }
                    141:         break;
                    142:     /* Reads as zero. */
                    143:     case MIPSNET_TX_DATA_BUFFER:
                    144:     default:
                    145:         break;
                    146:     }
                    147: #ifdef DEBUG_MIPSNET_DATA
                    148:     printf("mipsnet: read addr=0x%02x val=0x%02x\n", addr, ret);
                    149: #endif
                    150:     return ret;
                    151: }
                    152: 
                    153: static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                    154: {
                    155:     MIPSnetState *s = opaque;
                    156: 
                    157:     addr &= 0x3f;
                    158: #ifdef DEBUG_MIPSNET_DATA
                    159:     printf("mipsnet: write addr=0x%02x val=0x%02x\n", addr, val);
                    160: #endif
                    161:     switch (addr) {
                    162:     case MIPSNET_TX_DATA_COUNT:
                    163:        s->tx_count = (val <= MAX_ETH_FRAME_SIZE) ? val : 0;
                    164:         s->tx_written = 0;
                    165:         break;
                    166:     case MIPSNET_INT_CTL:
                    167:         if (val & MIPSNET_INTCTL_TXDONE) {
                    168:             s->intctl &= ~MIPSNET_INTCTL_TXDONE;
                    169:         } else if (val & MIPSNET_INTCTL_RXDONE) {
                    170:             s->intctl &= ~MIPSNET_INTCTL_RXDONE;
                    171:         } else if (val & MIPSNET_INTCTL_TESTBIT) {
                    172:             mipsnet_reset(s);
                    173:             s->intctl |= MIPSNET_INTCTL_TESTBIT;
                    174:         } else if (!val) {
                    175:             /* ACK testbit interrupt, flag was cleared on read. */
                    176:         }
                    177:         s->busy = !!s->intctl;
                    178:         mipsnet_update_irq(s);
                    179:         break;
                    180:     case MIPSNET_TX_DATA_BUFFER:
                    181:         s->tx_buffer[s->tx_written++] = val;
                    182:         if (s->tx_written == s->tx_count) {
                    183:             /* Send buffer. */
                    184: #ifdef DEBUG_MIPSNET_SEND
                    185:             printf("mipsnet: sending len=%d\n", s->tx_count);
                    186: #endif
1.1.1.5   root      187:             qemu_send_packet(&s->nic->nc, s->tx_buffer, s->tx_count);
1.1       root      188:             s->tx_count = s->tx_written = 0;
                    189:             s->intctl |= MIPSNET_INTCTL_TXDONE;
                    190:             s->busy = 1;
                    191:             mipsnet_update_irq(s);
                    192:         }
                    193:         break;
                    194:     /* Read-only registers */
                    195:     case MIPSNET_DEV_ID:
                    196:     case MIPSNET_BUSY:
                    197:     case MIPSNET_RX_DATA_COUNT:
                    198:     case MIPSNET_INTERRUPT_INFO:
                    199:     case MIPSNET_RX_DATA_BUFFER:
                    200:     default:
                    201:         break;
                    202:     }
                    203: }
                    204: 
1.1.1.8 ! root      205: static const VMStateDescription vmstate_mipsnet = {
        !           206:     .name = "mipsnet",
        !           207:     .version_id = 0,
        !           208:     .minimum_version_id = 0,
        !           209:     .minimum_version_id_old = 0,
        !           210:     .fields      = (VMStateField[]) {
        !           211:         VMSTATE_UINT32(busy, MIPSnetState),
        !           212:         VMSTATE_UINT32(rx_count, MIPSnetState),
        !           213:         VMSTATE_UINT32(rx_read, MIPSnetState),
        !           214:         VMSTATE_UINT32(tx_count, MIPSnetState),
        !           215:         VMSTATE_UINT32(tx_written, MIPSnetState),
        !           216:         VMSTATE_UINT32(intctl, MIPSnetState),
        !           217:         VMSTATE_BUFFER(rx_buffer, MIPSnetState),
        !           218:         VMSTATE_BUFFER(tx_buffer, MIPSnetState),
        !           219:         VMSTATE_END_OF_LIST()
        !           220:     }
        !           221: };
1.1       root      222: 
1.1.1.5   root      223: static void mipsnet_cleanup(VLANClientState *nc)
1.1.1.3   root      224: {
1.1.1.5   root      225:     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1.1.1.3   root      226: 
1.1.1.8 ! root      227:     vmstate_unregister(NULL, &vmstate_mipsnet, s);
1.1.1.3   root      228: 
                    229:     isa_unassign_ioport(s->io_base, 36);
                    230: 
                    231:     qemu_free(s);
                    232: }
                    233: 
1.1.1.5   root      234: static NetClientInfo net_mipsnet_info = {
                    235:     .type = NET_CLIENT_TYPE_NIC,
                    236:     .size = sizeof(NICState),
                    237:     .can_receive = mipsnet_can_receive,
                    238:     .receive = mipsnet_receive,
                    239:     .cleanup = mipsnet_cleanup,
                    240: };
                    241: 
1.1       root      242: void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
                    243: {
                    244:     MIPSnetState *s;
                    245: 
1.1.1.2   root      246:     qemu_check_nic_model(nd, "mipsnet");
                    247: 
1.1       root      248:     s = qemu_mallocz(sizeof(MIPSnetState));
                    249: 
                    250:     register_ioport_write(base, 36, 1, mipsnet_ioport_write, s);
                    251:     register_ioport_read(base, 36, 1, mipsnet_ioport_read, s);
                    252:     register_ioport_write(base, 36, 2, mipsnet_ioport_write, s);
                    253:     register_ioport_read(base, 36, 2, mipsnet_ioport_read, s);
                    254:     register_ioport_write(base, 36, 4, mipsnet_ioport_write, s);
                    255:     register_ioport_read(base, 36, 4, mipsnet_ioport_read, s);
                    256: 
1.1.1.3   root      257:     s->io_base = base;
1.1       root      258:     s->irq = irq;
                    259: 
1.1.1.5   root      260:     if (nd) {
1.1.1.8 ! root      261:         s->conf.macaddr = nd->macaddr;
1.1.1.5   root      262:         s->conf.vlan = nd->vlan;
                    263:         s->conf.peer = nd->netdev;
                    264: 
                    265:         s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
                    266:                               nd->model, nd->name, s);
                    267: 
                    268:         qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
                    269:     }
1.1       root      270: 
                    271:     mipsnet_reset(s);
1.1.1.8 ! root      272:     vmstate_register(NULL, 0, &vmstate_mipsnet, s);
1.1       root      273: }

unix.superglobalmegacorp.com

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