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

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_DEV_ID_STRING "MIPSNET0"
                     15: #define MIPSNET_BUSY           0x08
                     16: #define MIPSNET_RX_DATA_COUNT  0x0c
                     17: #define MIPSNET_TX_DATA_COUNT  0x10
                     18: #define MIPSNET_INT_CTL                0x14
                     19: # define MIPSNET_INTCTL_TXDONE         0x00000001
                     20: # define MIPSNET_INTCTL_RXDONE         0x00000002
                     21: # define MIPSNET_INTCTL_TESTBIT                0x80000000
                     22: #define MIPSNET_INTERRUPT_INFO 0x18
                     23: #define MIPSNET_RX_DATA_BUFFER 0x1c
                     24: #define MIPSNET_TX_DATA_BUFFER 0x20
                     25: 
                     26: #define MAX_ETH_FRAME_SIZE     1514
                     27: 
                     28: typedef struct MIPSnetState {
                     29:     uint32_t busy;
                     30:     uint32_t rx_count;
                     31:     uint32_t rx_read;
                     32:     uint32_t tx_count;
                     33:     uint32_t tx_written;
                     34:     uint32_t intctl;
                     35:     uint8_t rx_buffer[MAX_ETH_FRAME_SIZE];
                     36:     uint8_t tx_buffer[MAX_ETH_FRAME_SIZE];
                     37:     qemu_irq irq;
                     38:     VLANClientState *vc;
                     39:     NICInfo *nd;
                     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: 
                     70: static int mipsnet_can_receive(void *opaque)
                     71: {
                     72:     MIPSnetState *s = opaque;
                     73: 
                     74:     if (s->busy)
                     75:         return 0;
                     76:     return !mipsnet_buffer_full(s);
                     77: }
                     78: 
                     79: static void mipsnet_receive(void *opaque, const uint8_t *buf, int size)
                     80: {
                     81:     MIPSnetState *s = opaque;
                     82: 
                     83: #ifdef DEBUG_MIPSNET_RECEIVE
                     84:     printf("mipsnet: receiving len=%d\n", size);
                     85: #endif
                     86:     if (!mipsnet_can_receive(opaque))
                     87:         return;
                     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);
                    102: }
                    103: 
                    104: static uint32_t mipsnet_ioport_read(void *opaque, uint32_t addr)
                    105: {
                    106:     MIPSnetState *s = opaque;
                    107:     int ret = 0;
                    108:     const char *devid = MIPSNET_DEV_ID_STRING;
                    109: 
                    110:     addr &= 0x3f;
                    111:     switch (addr) {
                    112:     case MIPSNET_DEV_ID:
                    113:        ret = *((uint32_t *)&devid);
                    114:         break;
                    115:     case MIPSNET_DEV_ID + 4:
                    116:        ret = *((uint32_t *)(&devid + 4));
                    117:         break;
                    118:     case MIPSNET_BUSY:
                    119:        ret = s->busy;
                    120:         break;
                    121:     case MIPSNET_RX_DATA_COUNT:
                    122:        ret = s->rx_count;
                    123:         break;
                    124:     case MIPSNET_TX_DATA_COUNT:
                    125:        ret = s->tx_count;
                    126:         break;
                    127:     case MIPSNET_INT_CTL:
                    128:        ret = s->intctl;
                    129:         s->intctl &= ~MIPSNET_INTCTL_TESTBIT;
                    130:         break;
                    131:     case MIPSNET_INTERRUPT_INFO:
                    132:         /* XXX: This seems to be a per-VPE interrupt number. */
                    133:        ret = 0;
                    134:         break;
                    135:     case MIPSNET_RX_DATA_BUFFER:
                    136:         if (s->rx_count) {
                    137:             s->rx_count--;
                    138:             ret = s->rx_buffer[s->rx_read++];
                    139:         }
                    140:         break;
                    141:     /* Reads as zero. */
                    142:     case MIPSNET_TX_DATA_BUFFER:
                    143:     default:
                    144:         break;
                    145:     }
                    146: #ifdef DEBUG_MIPSNET_DATA
                    147:     printf("mipsnet: read addr=0x%02x val=0x%02x\n", addr, ret);
                    148: #endif
                    149:     return ret;
                    150: }
                    151: 
                    152: static void mipsnet_ioport_write(void *opaque, uint32_t addr, uint32_t val)
                    153: {
                    154:     MIPSnetState *s = opaque;
                    155: 
                    156:     addr &= 0x3f;
                    157: #ifdef DEBUG_MIPSNET_DATA
                    158:     printf("mipsnet: write addr=0x%02x val=0x%02x\n", addr, val);
                    159: #endif
                    160:     switch (addr) {
                    161:     case MIPSNET_TX_DATA_COUNT:
                    162:        s->tx_count = (val <= MAX_ETH_FRAME_SIZE) ? val : 0;
                    163:         s->tx_written = 0;
                    164:         break;
                    165:     case MIPSNET_INT_CTL:
                    166:         if (val & MIPSNET_INTCTL_TXDONE) {
                    167:             s->intctl &= ~MIPSNET_INTCTL_TXDONE;
                    168:         } else if (val & MIPSNET_INTCTL_RXDONE) {
                    169:             s->intctl &= ~MIPSNET_INTCTL_RXDONE;
                    170:         } else if (val & MIPSNET_INTCTL_TESTBIT) {
                    171:             mipsnet_reset(s);
                    172:             s->intctl |= MIPSNET_INTCTL_TESTBIT;
                    173:         } else if (!val) {
                    174:             /* ACK testbit interrupt, flag was cleared on read. */
                    175:         }
                    176:         s->busy = !!s->intctl;
                    177:         mipsnet_update_irq(s);
                    178:         break;
                    179:     case MIPSNET_TX_DATA_BUFFER:
                    180:         s->tx_buffer[s->tx_written++] = val;
                    181:         if (s->tx_written == s->tx_count) {
                    182:             /* Send buffer. */
                    183: #ifdef DEBUG_MIPSNET_SEND
                    184:             printf("mipsnet: sending len=%d\n", s->tx_count);
                    185: #endif
                    186:             qemu_send_packet(s->vc, s->tx_buffer, s->tx_count);
                    187:             s->tx_count = s->tx_written = 0;
                    188:             s->intctl |= MIPSNET_INTCTL_TXDONE;
                    189:             s->busy = 1;
                    190:             mipsnet_update_irq(s);
                    191:         }
                    192:         break;
                    193:     /* Read-only registers */
                    194:     case MIPSNET_DEV_ID:
                    195:     case MIPSNET_BUSY:
                    196:     case MIPSNET_RX_DATA_COUNT:
                    197:     case MIPSNET_INTERRUPT_INFO:
                    198:     case MIPSNET_RX_DATA_BUFFER:
                    199:     default:
                    200:         break;
                    201:     }
                    202: }
                    203: 
                    204: static void mipsnet_save(QEMUFile *f, void *opaque)
                    205: {
                    206:     MIPSnetState *s = opaque;
                    207: 
                    208:     qemu_put_be32s(f, &s->busy);
                    209:     qemu_put_be32s(f, &s->rx_count);
                    210:     qemu_put_be32s(f, &s->rx_read);
                    211:     qemu_put_be32s(f, &s->tx_count);
                    212:     qemu_put_be32s(f, &s->tx_written);
                    213:     qemu_put_be32s(f, &s->intctl);
                    214:     qemu_put_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
                    215:     qemu_put_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
                    216: }
                    217: 
                    218: static int mipsnet_load(QEMUFile *f, void *opaque, int version_id)
                    219: {
                    220:     MIPSnetState *s = opaque;
                    221: 
                    222:     if (version_id > 0)
                    223:         return -EINVAL;
                    224: 
                    225:     qemu_get_be32s(f, &s->busy);
                    226:     qemu_get_be32s(f, &s->rx_count);
                    227:     qemu_get_be32s(f, &s->rx_read);
                    228:     qemu_get_be32s(f, &s->tx_count);
                    229:     qemu_get_be32s(f, &s->tx_written);
                    230:     qemu_get_be32s(f, &s->intctl);
                    231:     qemu_get_buffer(f, s->rx_buffer, MAX_ETH_FRAME_SIZE);
                    232:     qemu_get_buffer(f, s->tx_buffer, MAX_ETH_FRAME_SIZE);
                    233: 
                    234:     return 0;
                    235: }
                    236: 
                    237: void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
                    238: {
                    239:     MIPSnetState *s;
                    240: 
                    241:     s = qemu_mallocz(sizeof(MIPSnetState));
                    242:     if (!s)
                    243:         return;
                    244: 
                    245:     register_ioport_write(base, 36, 1, mipsnet_ioport_write, s);
                    246:     register_ioport_read(base, 36, 1, mipsnet_ioport_read, s);
                    247:     register_ioport_write(base, 36, 2, mipsnet_ioport_write, s);
                    248:     register_ioport_read(base, 36, 2, mipsnet_ioport_read, s);
                    249:     register_ioport_write(base, 36, 4, mipsnet_ioport_write, s);
                    250:     register_ioport_read(base, 36, 4, mipsnet_ioport_read, s);
                    251: 
                    252:     s->irq = irq;
                    253:     s->nd = nd;
                    254:     if (nd && nd->vlan) {
                    255:         s->vc = qemu_new_vlan_client(nd->vlan, mipsnet_receive,
                    256:                                      mipsnet_can_receive, s);
                    257:     } else {
                    258:         s->vc = NULL;
                    259:     }
                    260: 
                    261:     snprintf(s->vc->info_str, sizeof(s->vc->info_str),
                    262:              "mipsnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
                    263:               s->nd->macaddr[0],
                    264:               s->nd->macaddr[1],
                    265:               s->nd->macaddr[2],
                    266:               s->nd->macaddr[3],
                    267:               s->nd->macaddr[4],
                    268:               s->nd->macaddr[5]);
                    269: 
                    270:     mipsnet_reset(s);
                    271:     register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
                    272: }

unix.superglobalmegacorp.com

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