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

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;
                     38:     VLANClientState *vc;
                     39: } MIPSnetState;
                     40: 
                     41: static void mipsnet_reset(MIPSnetState *s)
                     42: {
                     43:     s->busy = 1;
                     44:     s->rx_count = 0;
                     45:     s->rx_read = 0;
                     46:     s->tx_count = 0;
                     47:     s->tx_written = 0;
                     48:     s->intctl = 0;
                     49:     memset(s->rx_buffer, 0, MAX_ETH_FRAME_SIZE);
                     50:     memset(s->tx_buffer, 0, MAX_ETH_FRAME_SIZE);
                     51: }
                     52: 
                     53: static void mipsnet_update_irq(MIPSnetState *s)
                     54: {
                     55:     int isr = !!s->intctl;
                     56: #ifdef DEBUG_MIPSNET_IRQ
                     57:     printf("mipsnet: Set IRQ to %d (%02x)\n", isr, s->intctl);
                     58: #endif
                     59:     qemu_set_irq(s->irq, isr);
                     60: }
                     61: 
                     62: static int mipsnet_buffer_full(MIPSnetState *s)
                     63: {
                     64:     if (s->rx_count >= MAX_ETH_FRAME_SIZE)
                     65:         return 1;
                     66:     return 0;
                     67: }
                     68: 
                     69: static int mipsnet_can_receive(void *opaque)
                     70: {
                     71:     MIPSnetState *s = opaque;
                     72: 
                     73:     if (s->busy)
                     74:         return 0;
                     75:     return !mipsnet_buffer_full(s);
                     76: }
                     77: 
                     78: static void mipsnet_receive(void *opaque, const uint8_t *buf, int size)
                     79: {
                     80:     MIPSnetState *s = opaque;
                     81: 
                     82: #ifdef DEBUG_MIPSNET_RECEIVE
                     83:     printf("mipsnet: receiving len=%d\n", size);
                     84: #endif
                     85:     if (!mipsnet_can_receive(opaque))
                     86:         return;
                     87: 
                     88:     s->busy = 1;
                     89: 
                     90:     /* Just accept everything. */
                     91: 
                     92:     /* Write packet data. */
                     93:     memcpy(s->rx_buffer, buf, size);
                     94: 
                     95:     s->rx_count = size;
                     96:     s->rx_read = 0;
                     97: 
                     98:     /* Now we can signal we have received something. */
                     99:     s->intctl |= MIPSNET_INTCTL_RXDONE;
                    100:     mipsnet_update_irq(s);
                    101: }
                    102: 
                    103: static uint32_t mipsnet_ioport_read(void *opaque, uint32_t addr)
                    104: {
                    105:     MIPSnetState *s = opaque;
                    106:     int ret = 0;
                    107: 
                    108:     addr &= 0x3f;
                    109:     switch (addr) {
                    110:     case MIPSNET_DEV_ID:
1.1.1.2   root      111:        ret = be32_to_cpu(0x4d495053);          /* MIPS */
1.1       root      112:         break;
                    113:     case MIPSNET_DEV_ID + 4:
1.1.1.2   root      114:        ret = be32_to_cpu(0x4e455430);          /* NET0 */
1.1       root      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: #ifdef DEBUG_MIPSNET_DATA
                    145:     printf("mipsnet: read addr=0x%02x val=0x%02x\n", addr, ret);
                    146: #endif
                    147:     return ret;
                    148: }
                    149: 
                    150: static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                    151: {
                    152:     MIPSnetState *s = opaque;
                    153: 
                    154:     addr &= 0x3f;
                    155: #ifdef DEBUG_MIPSNET_DATA
                    156:     printf("mipsnet: write addr=0x%02x val=0x%02x\n", addr, val);
                    157: #endif
                    158:     switch (addr) {
                    159:     case MIPSNET_TX_DATA_COUNT:
                    160:        s->tx_count = (val <= MAX_ETH_FRAME_SIZE) ? val : 0;
                    161:         s->tx_written = 0;
                    162:         break;
                    163:     case MIPSNET_INT_CTL:
                    164:         if (val & MIPSNET_INTCTL_TXDONE) {
                    165:             s->intctl &= ~MIPSNET_INTCTL_TXDONE;
                    166:         } else if (val & MIPSNET_INTCTL_RXDONE) {
                    167:             s->intctl &= ~MIPSNET_INTCTL_RXDONE;
                    168:         } else if (val & MIPSNET_INTCTL_TESTBIT) {
                    169:             mipsnet_reset(s);
                    170:             s->intctl |= MIPSNET_INTCTL_TESTBIT;
                    171:         } else if (!val) {
                    172:             /* ACK testbit interrupt, flag was cleared on read. */
                    173:         }
                    174:         s->busy = !!s->intctl;
                    175:         mipsnet_update_irq(s);
                    176:         break;
                    177:     case MIPSNET_TX_DATA_BUFFER:
                    178:         s->tx_buffer[s->tx_written++] = val;
                    179:         if (s->tx_written == s->tx_count) {
                    180:             /* Send buffer. */
                    181: #ifdef DEBUG_MIPSNET_SEND
                    182:             printf("mipsnet: sending len=%d\n", s->tx_count);
                    183: #endif
                    184:             qemu_send_packet(s->vc, s->tx_buffer, s->tx_count);
                    185:             s->tx_count = s->tx_written = 0;
                    186:             s->intctl |= MIPSNET_INTCTL_TXDONE;
                    187:             s->busy = 1;
                    188:             mipsnet_update_irq(s);
                    189:         }
                    190:         break;
                    191:     /* Read-only registers */
                    192:     case MIPSNET_DEV_ID:
                    193:     case MIPSNET_BUSY:
                    194:     case MIPSNET_RX_DATA_COUNT:
                    195:     case MIPSNET_INTERRUPT_INFO:
                    196:     case MIPSNET_RX_DATA_BUFFER:
                    197:     default:
                    198:         break;
                    199:     }
                    200: }
                    201: 
                    202: static void mipsnet_save(QEMUFile *f, void *opaque)
                    203: {
                    204:     MIPSnetState *s = opaque;
                    205: 
                    206:     qemu_put_be32s(f, &s->busy);
                    207:     qemu_put_be32s(f, &s->rx_count);
                    208:     qemu_put_be32s(f, &s->rx_read);
                    209:     qemu_put_be32s(f, &s->tx_count);
                    210:     qemu_put_be32s(f, &s->tx_written);
                    211:     qemu_put_be32s(f, &s->intctl);
                    212:     qemu_put_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
                    213:     qemu_put_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
                    214: }
                    215: 
                    216: static int mipsnet_load(QEMUFile *f, void *opaque, int version_id)
                    217: {
                    218:     MIPSnetState *s = opaque;
                    219: 
                    220:     if (version_id > 0)
                    221:         return -EINVAL;
                    222: 
                    223:     qemu_get_be32s(f, &s->busy);
                    224:     qemu_get_be32s(f, &s->rx_count);
                    225:     qemu_get_be32s(f, &s->rx_read);
                    226:     qemu_get_be32s(f, &s->tx_count);
                    227:     qemu_get_be32s(f, &s->tx_written);
                    228:     qemu_get_be32s(f, &s->intctl);
                    229:     qemu_get_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
                    230:     qemu_get_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
                    231: 
                    232:     return 0;
                    233: }
                    234: 
1.1.1.3 ! root      235: static void mipsnet_cleanup(VLANClientState *vc)
        !           236: {
        !           237:     MIPSnetState *s = vc->opaque;
        !           238: 
        !           239:     unregister_savevm("mipsnet", s);
        !           240: 
        !           241:     isa_unassign_ioport(s->io_base, 36);
        !           242: 
        !           243:     qemu_free(s);
        !           244: }
        !           245: 
1.1       root      246: void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
                    247: {
                    248:     MIPSnetState *s;
                    249: 
1.1.1.2   root      250:     qemu_check_nic_model(nd, "mipsnet");
                    251: 
1.1       root      252:     s = qemu_mallocz(sizeof(MIPSnetState));
                    253: 
                    254:     register_ioport_write(base, 36, 1, mipsnet_ioport_write, s);
                    255:     register_ioport_read(base, 36, 1, mipsnet_ioport_read, s);
                    256:     register_ioport_write(base, 36, 2, mipsnet_ioport_write, s);
                    257:     register_ioport_read(base, 36, 2, mipsnet_ioport_read, s);
                    258:     register_ioport_write(base, 36, 4, mipsnet_ioport_write, s);
                    259:     register_ioport_read(base, 36, 4, mipsnet_ioport_read, s);
                    260: 
1.1.1.3 ! root      261:     s->io_base = base;
1.1       root      262:     s->irq = irq;
                    263:     if (nd && nd->vlan) {
1.1.1.2   root      264:         s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
1.1.1.3 ! root      265:                                      mipsnet_receive, mipsnet_can_receive,
        !           266:                                      mipsnet_cleanup, s);
1.1       root      267:     } else {
                    268:         s->vc = NULL;
                    269:     }
                    270: 
1.1.1.3 ! root      271:     qemu_format_nic_info_str(s->vc, nd->macaddr);
1.1       root      272: 
                    273:     mipsnet_reset(s);
                    274:     register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
                    275: }

unix.superglobalmegacorp.com

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