Annotation of qemu/hw/mipsnet.c, revision 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.