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

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: 
1.1.1.4 ! root       69: static int mipsnet_can_receive(VLANClientState *vc)
1.1       root       70: {
1.1.1.4 ! root       71:     MIPSnetState *s = vc->opaque;
1.1       root       72: 
                     73:     if (s->busy)
                     74:         return 0;
                     75:     return !mipsnet_buffer_full(s);
                     76: }
                     77: 
1.1.1.4 ! root       78: static ssize_t mipsnet_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
1.1       root       79: {
1.1.1.4 ! root       80:     MIPSnetState *s = vc->opaque;
1.1       root       81: 
                     82: #ifdef DEBUG_MIPSNET_RECEIVE
                     83:     printf("mipsnet: receiving len=%d\n", size);
                     84: #endif
1.1.1.4 ! root       85:     if (!mipsnet_can_receive(vc))
        !            86:         return -1;
1.1       root       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);
1.1.1.4 ! root      101: 
        !           102:     return size;
1.1       root      103: }
                    104: 
                    105: static uint32_t mipsnet_ioport_read(void *opaque, uint32_t addr)
                    106: {
                    107:     MIPSnetState *s = opaque;
                    108:     int ret = 0;
                    109: 
                    110:     addr &= 0x3f;
                    111:     switch (addr) {
                    112:     case MIPSNET_DEV_ID:
1.1.1.2   root      113:        ret = be32_to_cpu(0x4d495053);          /* MIPS */
1.1       root      114:         break;
                    115:     case MIPSNET_DEV_ID + 4:
1.1.1.2   root      116:        ret = be32_to_cpu(0x4e455430);          /* NET0 */
1.1       root      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: 
1.1.1.3   root      237: static void mipsnet_cleanup(VLANClientState *vc)
                    238: {
                    239:     MIPSnetState *s = vc->opaque;
                    240: 
                    241:     unregister_savevm("mipsnet", s);
                    242: 
                    243:     isa_unassign_ioport(s->io_base, 36);
                    244: 
                    245:     qemu_free(s);
                    246: }
                    247: 
1.1       root      248: void mipsnet_init (int base, qemu_irq irq, NICInfo *nd)
                    249: {
                    250:     MIPSnetState *s;
                    251: 
1.1.1.2   root      252:     qemu_check_nic_model(nd, "mipsnet");
                    253: 
1.1       root      254:     s = qemu_mallocz(sizeof(MIPSnetState));
                    255: 
                    256:     register_ioport_write(base, 36, 1, mipsnet_ioport_write, s);
                    257:     register_ioport_read(base, 36, 1, mipsnet_ioport_read, s);
                    258:     register_ioport_write(base, 36, 2, mipsnet_ioport_write, s);
                    259:     register_ioport_read(base, 36, 2, mipsnet_ioport_read, s);
                    260:     register_ioport_write(base, 36, 4, mipsnet_ioport_write, s);
                    261:     register_ioport_read(base, 36, 4, mipsnet_ioport_read, s);
                    262: 
1.1.1.3   root      263:     s->io_base = base;
1.1       root      264:     s->irq = irq;
                    265:     if (nd && nd->vlan) {
1.1.1.4 ! root      266:         s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
        !           267:                                               mipsnet_can_receive, mipsnet_receive,
        !           268:                                               NULL, mipsnet_cleanup, s);
1.1       root      269:     } else {
                    270:         s->vc = NULL;
                    271:     }
                    272: 
1.1.1.3   root      273:     qemu_format_nic_info_str(s->vc, nd->macaddr);
1.1       root      274: 
                    275:     mipsnet_reset(s);
                    276:     register_savevm("mipsnet", 0, 0, mipsnet_save, mipsnet_load, s);
                    277: }

unix.superglobalmegacorp.com

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