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

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
                     84:     printf("mipsnet: receiving len=%d\n", size);
                     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: 
                    205: static void mipsnet_save(QEMUFile *f, void *opaque)
                    206: {
                    207:     MIPSnetState *s = opaque;
                    208: 
                    209:     qemu_put_be32s(f, &s->busy);
                    210:     qemu_put_be32s(f, &s->rx_count);
                    211:     qemu_put_be32s(f, &s->rx_read);
                    212:     qemu_put_be32s(f, &s->tx_count);
                    213:     qemu_put_be32s(f, &s->tx_written);
                    214:     qemu_put_be32s(f, &s->intctl);
                    215:     qemu_put_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
                    216:     qemu_put_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
                    217: }
                    218: 
                    219: static int mipsnet_load(QEMUFile *f, void *opaque, int version_id)
                    220: {
                    221:     MIPSnetState *s = opaque;
                    222: 
                    223:     if (version_id > 0)
                    224:         return -EINVAL;
                    225: 
                    226:     qemu_get_be32s(f, &s->busy);
                    227:     qemu_get_be32s(f, &s->rx_count);
                    228:     qemu_get_be32s(f, &s->rx_read);
                    229:     qemu_get_be32s(f, &s->tx_count);
                    230:     qemu_get_be32s(f, &s->tx_written);
                    231:     qemu_get_be32s(f, &s->intctl);
                    232:     qemu_get_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
                    233:     qemu_get_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
                    234: 
                    235:     return 0;
                    236: }
                    237: 
1.1.1.5 ! root      238: static void mipsnet_cleanup(VLANClientState *nc)
1.1.1.3   root      239: {
1.1.1.5 ! root      240:     MIPSnetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1.1.1.3   root      241: 
                    242:     unregister_savevm("mipsnet", s);
                    243: 
                    244:     isa_unassign_ioport(s->io_base, 36);
                    245: 
                    246:     qemu_free(s);
                    247: }
                    248: 
1.1.1.5 ! root      249: static NetClientInfo net_mipsnet_info = {
        !           250:     .type = NET_CLIENT_TYPE_NIC,
        !           251:     .size = sizeof(NICState),
        !           252:     .can_receive = mipsnet_can_receive,
        !           253:     .receive = mipsnet_receive,
        !           254:     .cleanup = mipsnet_cleanup,
        !           255: };
        !           256: 
1.1       root      257: void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
                    258: {
                    259:     MIPSnetState *s;
                    260: 
1.1.1.2   root      261:     qemu_check_nic_model(nd, "mipsnet");
                    262: 
1.1       root      263:     s = qemu_mallocz(sizeof(MIPSnetState));
                    264: 
                    265:     register_ioport_write(base, 36, 1, mipsnet_ioport_write, s);
                    266:     register_ioport_read(base, 36, 1, mipsnet_ioport_read, s);
                    267:     register_ioport_write(base, 36, 2, mipsnet_ioport_write, s);
                    268:     register_ioport_read(base, 36, 2, mipsnet_ioport_read, s);
                    269:     register_ioport_write(base, 36, 4, mipsnet_ioport_write, s);
                    270:     register_ioport_read(base, 36, 4, mipsnet_ioport_read, s);
                    271: 
1.1.1.3   root      272:     s->io_base = base;
1.1       root      273:     s->irq = irq;
                    274: 
1.1.1.5 ! root      275:     if (nd) {
        !           276:         memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr));
        !           277:         s->conf.vlan = nd->vlan;
        !           278:         s->conf.peer = nd->netdev;
        !           279: 
        !           280:         s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
        !           281:                               nd->model, nd->name, s);
        !           282: 
        !           283:         qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
        !           284:     }
1.1       root      285: 
                    286:     mipsnet_reset(s);
                    287:     register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
                    288: }

unix.superglobalmegacorp.com

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