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

1.1       root        1: /*
                      2:  * ColdFire Fast Ethernet Controller emulation.
                      3:  *
                      4:  * Copyright (c) 2007 CodeSourcery.
                      5:  *
                      6:  * This code is licenced under the GPL
                      7:  */
                      8: #include "hw.h"
                      9: #include "net.h"
                     10: #include "mcf.h"
                     11: /* For crc32 */
                     12: #include <zlib.h>
                     13: 
                     14: //#define DEBUG_FEC 1
                     15: 
                     16: #ifdef DEBUG_FEC
                     17: #define DPRINTF(fmt, args...) \
                     18: do { printf("mcf_fec: " fmt , ##args); } while (0)
                     19: #else
                     20: #define DPRINTF(fmt, args...) do {} while(0)
                     21: #endif
                     22: 
                     23: #define FEC_MAX_FRAME_SIZE 2032
                     24: 
                     25: typedef struct {
                     26:     qemu_irq *irq;
1.1.1.3 ! root       27:     int mmio_index;
1.1       root       28:     VLANClientState *vc;
                     29:     uint32_t irq_state;
                     30:     uint32_t eir;
                     31:     uint32_t eimr;
                     32:     int rx_enabled;
                     33:     uint32_t rx_descriptor;
                     34:     uint32_t tx_descriptor;
                     35:     uint32_t ecr;
                     36:     uint32_t mmfr;
                     37:     uint32_t mscr;
                     38:     uint32_t rcr;
                     39:     uint32_t tcr;
                     40:     uint32_t tfwr;
                     41:     uint32_t rfsr;
                     42:     uint32_t erdsr;
                     43:     uint32_t etdsr;
                     44:     uint32_t emrbr;
                     45:     uint8_t macaddr[6];
                     46: } mcf_fec_state;
                     47: 
                     48: #define FEC_INT_HB   0x80000000
                     49: #define FEC_INT_BABR 0x40000000
                     50: #define FEC_INT_BABT 0x20000000
                     51: #define FEC_INT_GRA  0x10000000
                     52: #define FEC_INT_TXF  0x08000000
                     53: #define FEC_INT_TXB  0x04000000
                     54: #define FEC_INT_RXF  0x02000000
                     55: #define FEC_INT_RXB  0x01000000
                     56: #define FEC_INT_MII  0x00800000
                     57: #define FEC_INT_EB   0x00400000
                     58: #define FEC_INT_LC   0x00200000
                     59: #define FEC_INT_RL   0x00100000
                     60: #define FEC_INT_UN   0x00080000
                     61: 
                     62: #define FEC_EN      2
                     63: #define FEC_RESET   1
                     64: 
                     65: /* Map interrupt flags onto IRQ lines.  */
                     66: #define FEC_NUM_IRQ 13
                     67: static const uint32_t mcf_fec_irq_map[FEC_NUM_IRQ] = {
                     68:     FEC_INT_TXF,
                     69:     FEC_INT_TXB,
                     70:     FEC_INT_UN,
                     71:     FEC_INT_RL,
                     72:     FEC_INT_RXF,
                     73:     FEC_INT_RXB,
                     74:     FEC_INT_MII,
                     75:     FEC_INT_LC,
                     76:     FEC_INT_HB,
                     77:     FEC_INT_GRA,
                     78:     FEC_INT_EB,
                     79:     FEC_INT_BABT,
                     80:     FEC_INT_BABR
                     81: };
                     82: 
                     83: /* Buffer Descriptor.  */
                     84: typedef struct {
                     85:     uint16_t flags;
                     86:     uint16_t length;
                     87:     uint32_t data;
                     88: } mcf_fec_bd;
                     89: 
                     90: #define FEC_BD_R    0x8000
                     91: #define FEC_BD_E    0x8000
                     92: #define FEC_BD_O1   0x4000
                     93: #define FEC_BD_W    0x2000
                     94: #define FEC_BD_O2   0x1000
                     95: #define FEC_BD_L    0x0800
                     96: #define FEC_BD_TC   0x0400
                     97: #define FEC_BD_ABC  0x0200
                     98: #define FEC_BD_M    0x0100
                     99: #define FEC_BD_BC   0x0080
                    100: #define FEC_BD_MC   0x0040
                    101: #define FEC_BD_LG   0x0020
                    102: #define FEC_BD_NO   0x0010
                    103: #define FEC_BD_CR   0x0004
                    104: #define FEC_BD_OV   0x0002
                    105: #define FEC_BD_TR   0x0001
                    106: 
                    107: static void mcf_fec_read_bd(mcf_fec_bd *bd, uint32_t addr)
                    108: {
                    109:     cpu_physical_memory_read(addr, (uint8_t *)bd, sizeof(*bd));
                    110:     be16_to_cpus(&bd->flags);
                    111:     be16_to_cpus(&bd->length);
                    112:     be32_to_cpus(&bd->data);
                    113: }
                    114: 
                    115: static void mcf_fec_write_bd(mcf_fec_bd *bd, uint32_t addr)
                    116: {
                    117:     mcf_fec_bd tmp;
                    118:     tmp.flags = cpu_to_be16(bd->flags);
                    119:     tmp.length = cpu_to_be16(bd->length);
                    120:     tmp.data = cpu_to_be32(bd->data);
                    121:     cpu_physical_memory_write(addr, (uint8_t *)&tmp, sizeof(tmp));
                    122: }
                    123: 
                    124: static void mcf_fec_update(mcf_fec_state *s)
                    125: {
                    126:     uint32_t active;
                    127:     uint32_t changed;
                    128:     uint32_t mask;
                    129:     int i;
                    130: 
                    131:     active = s->eir & s->eimr;
                    132:     changed = active ^s->irq_state;
                    133:     for (i = 0; i < FEC_NUM_IRQ; i++) {
                    134:         mask = mcf_fec_irq_map[i];
                    135:         if (changed & mask) {
                    136:             DPRINTF("IRQ %d = %d\n", i, (active & mask) != 0);
                    137:             qemu_set_irq(s->irq[i], (active & mask) != 0);
                    138:         }
                    139:     }
                    140:     s->irq_state = active;
                    141: }
                    142: 
                    143: static void mcf_fec_do_tx(mcf_fec_state *s)
                    144: {
                    145:     uint32_t addr;
                    146:     mcf_fec_bd bd;
                    147:     int frame_size;
                    148:     int len;
                    149:     uint8_t frame[FEC_MAX_FRAME_SIZE];
                    150:     uint8_t *ptr;
                    151: 
                    152:     DPRINTF("do_tx\n");
                    153:     ptr = frame;
                    154:     frame_size = 0;
                    155:     addr = s->tx_descriptor;
                    156:     while (1) {
                    157:         mcf_fec_read_bd(&bd, addr);
                    158:         DPRINTF("tx_bd %x flags %04x len %d data %08x\n",
                    159:                 addr, bd.flags, bd.length, bd.data);
                    160:         if ((bd.flags & FEC_BD_R) == 0) {
                    161:             /* Run out of descriptors to transmit.  */
                    162:             break;
                    163:         }
                    164:         len = bd.length;
                    165:         if (frame_size + len > FEC_MAX_FRAME_SIZE) {
                    166:             len = FEC_MAX_FRAME_SIZE - frame_size;
                    167:             s->eir |= FEC_INT_BABT;
                    168:         }
                    169:         cpu_physical_memory_read(bd.data, ptr, len);
                    170:         ptr += len;
                    171:         frame_size += len;
                    172:         if (bd.flags & FEC_BD_L) {
                    173:             /* Last buffer in frame.  */
                    174:             DPRINTF("Sending packet\n");
                    175:             qemu_send_packet(s->vc, frame, len);
                    176:             ptr = frame;
                    177:             frame_size = 0;
                    178:             s->eir |= FEC_INT_TXF;
                    179:         }
                    180:         s->eir |= FEC_INT_TXB;
                    181:         bd.flags &= ~FEC_BD_R;
                    182:         /* Write back the modified descriptor.  */
                    183:         mcf_fec_write_bd(&bd, addr);
                    184:         /* Advance to the next descriptor.  */
                    185:         if ((bd.flags & FEC_BD_W) != 0) {
                    186:             addr = s->etdsr;
                    187:         } else {
                    188:             addr += 8;
                    189:         }
                    190:     }
                    191:     s->tx_descriptor = addr;
                    192: }
                    193: 
                    194: static void mcf_fec_enable_rx(mcf_fec_state *s)
                    195: {
                    196:     mcf_fec_bd bd;
                    197: 
                    198:     mcf_fec_read_bd(&bd, s->rx_descriptor);
                    199:     s->rx_enabled = ((bd.flags & FEC_BD_E) != 0);
                    200:     if (!s->rx_enabled)
                    201:         DPRINTF("RX buffer full\n");
                    202: }
                    203: 
                    204: static void mcf_fec_reset(mcf_fec_state *s)
                    205: {
                    206:     s->eir = 0;
                    207:     s->eimr = 0;
                    208:     s->rx_enabled = 0;
                    209:     s->ecr = 0;
                    210:     s->mscr = 0;
                    211:     s->rcr = 0x05ee0001;
                    212:     s->tcr = 0;
                    213:     s->tfwr = 0;
                    214:     s->rfsr = 0x500;
                    215: }
                    216: 
                    217: static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr)
                    218: {
                    219:     mcf_fec_state *s = (mcf_fec_state *)opaque;
                    220:     switch (addr & 0x3ff) {
                    221:     case 0x004: return s->eir;
                    222:     case 0x008: return s->eimr;
                    223:     case 0x010: return s->rx_enabled ? (1 << 24) : 0; /* RDAR */
                    224:     case 0x014: return 0; /* TDAR */
                    225:     case 0x024: return s->ecr;
                    226:     case 0x040: return s->mmfr;
                    227:     case 0x044: return s->mscr;
                    228:     case 0x064: return 0; /* MIBC */
                    229:     case 0x084: return s->rcr;
                    230:     case 0x0c4: return s->tcr;
                    231:     case 0x0e4: /* PALR */
                    232:         return (s->macaddr[0] << 24) | (s->macaddr[1] << 16)
                    233:               | (s->macaddr[2] << 8) | s->macaddr[3];
                    234:         break;
                    235:     case 0x0e8: /* PAUR */
                    236:         return (s->macaddr[4] << 24) | (s->macaddr[5] << 16) | 0x8808;
                    237:     case 0x0ec: return 0x10000; /* OPD */
                    238:     case 0x118: return 0;
                    239:     case 0x11c: return 0;
                    240:     case 0x120: return 0;
                    241:     case 0x124: return 0;
                    242:     case 0x144: return s->tfwr;
                    243:     case 0x14c: return 0x600;
                    244:     case 0x150: return s->rfsr;
                    245:     case 0x180: return s->erdsr;
                    246:     case 0x184: return s->etdsr;
                    247:     case 0x188: return s->emrbr;
                    248:     default:
                    249:         cpu_abort(cpu_single_env, "mcf_fec_read: Bad address 0x%x\n",
                    250:                   (int)addr);
                    251:         return 0;
                    252:     }
                    253: }
                    254: 
                    255: static void mcf_fec_write(void *opaque, target_phys_addr_t addr, uint32_t value)
                    256: {
                    257:     mcf_fec_state *s = (mcf_fec_state *)opaque;
                    258:     switch (addr & 0x3ff) {
                    259:     case 0x004:
                    260:         s->eir &= ~value;
                    261:         break;
                    262:     case 0x008:
                    263:         s->eimr = value;
                    264:         break;
                    265:     case 0x010: /* RDAR */
                    266:         if ((s->ecr & FEC_EN) && !s->rx_enabled) {
                    267:             DPRINTF("RX enable\n");
                    268:             mcf_fec_enable_rx(s);
                    269:         }
                    270:         break;
                    271:     case 0x014: /* TDAR */
                    272:         if (s->ecr & FEC_EN) {
                    273:             mcf_fec_do_tx(s);
                    274:         }
                    275:         break;
                    276:     case 0x024:
                    277:         s->ecr = value;
                    278:         if (value & FEC_RESET) {
                    279:             DPRINTF("Reset\n");
                    280:             mcf_fec_reset(s);
                    281:         }
                    282:         if ((s->ecr & FEC_EN) == 0) {
                    283:             s->rx_enabled = 0;
                    284:         }
                    285:         break;
                    286:     case 0x040:
                    287:         /* TODO: Implement MII.  */
                    288:         s->mmfr = value;
                    289:         break;
                    290:     case 0x044:
                    291:         s->mscr = value & 0xfe;
                    292:         break;
                    293:     case 0x064:
                    294:         /* TODO: Implement MIB.  */
                    295:         break;
                    296:     case 0x084:
                    297:         s->rcr = value & 0x07ff003f;
                    298:         /* TODO: Implement LOOP mode.  */
                    299:         break;
                    300:     case 0x0c4: /* TCR */
                    301:         /* We transmit immediately, so raise GRA immediately.  */
                    302:         s->tcr = value;
                    303:         if (value & 1)
                    304:             s->eir |= FEC_INT_GRA;
                    305:         break;
                    306:     case 0x0e4: /* PALR */
                    307:         s->macaddr[0] = value >> 24;
                    308:         s->macaddr[1] = value >> 16;
                    309:         s->macaddr[2] = value >> 8;
                    310:         s->macaddr[3] = value;
                    311:         break;
                    312:     case 0x0e8: /* PAUR */
                    313:         s->macaddr[4] = value >> 24;
                    314:         s->macaddr[5] = value >> 16;
                    315:         break;
                    316:     case 0x0ec:
                    317:         /* OPD */
                    318:         break;
                    319:     case 0x118:
                    320:     case 0x11c:
                    321:     case 0x120:
                    322:     case 0x124:
                    323:         /* TODO: implement MAC hash filtering.  */
                    324:         break;
                    325:     case 0x144:
                    326:         s->tfwr = value & 3;
                    327:         break;
                    328:     case 0x14c:
                    329:         /* FRBR writes ignored.  */
                    330:         break;
                    331:     case 0x150:
                    332:         s->rfsr = (value & 0x3fc) | 0x400;
                    333:         break;
                    334:     case 0x180:
                    335:         s->erdsr = value & ~3;
                    336:         s->rx_descriptor = s->erdsr;
                    337:         break;
                    338:     case 0x184:
                    339:         s->etdsr = value & ~3;
                    340:         s->tx_descriptor = s->etdsr;
                    341:         break;
                    342:     case 0x188:
                    343:         s->emrbr = value & 0x7f0;
                    344:         break;
                    345:     default:
                    346:         cpu_abort(cpu_single_env, "mcf_fec_write Bad address 0x%x\n",
                    347:                   (int)addr);
                    348:     }
                    349:     mcf_fec_update(s);
                    350: }
                    351: 
                    352: static int mcf_fec_can_receive(void *opaque)
                    353: {
                    354:     mcf_fec_state *s = (mcf_fec_state *)opaque;
                    355:     return s->rx_enabled;
                    356: }
                    357: 
                    358: static void mcf_fec_receive(void *opaque, const uint8_t *buf, int size)
                    359: {
                    360:     mcf_fec_state *s = (mcf_fec_state *)opaque;
                    361:     mcf_fec_bd bd;
                    362:     uint32_t flags = 0;
                    363:     uint32_t addr;
                    364:     uint32_t crc;
                    365:     uint32_t buf_addr;
                    366:     uint8_t *crc_ptr;
                    367:     unsigned int buf_len;
                    368: 
                    369:     DPRINTF("do_rx len %d\n", size);
                    370:     if (!s->rx_enabled) {
                    371:         fprintf(stderr, "mcf_fec_receive: Unexpected packet\n");
                    372:     }
                    373:     /* 4 bytes for the CRC.  */
                    374:     size += 4;
                    375:     crc = cpu_to_be32(crc32(~0, buf, size));
                    376:     crc_ptr = (uint8_t *)&crc;
                    377:     /* Huge frames are truncted.  */
                    378:     if (size > FEC_MAX_FRAME_SIZE) {
                    379:         size = FEC_MAX_FRAME_SIZE;
                    380:         flags |= FEC_BD_TR | FEC_BD_LG;
                    381:     }
                    382:     /* Frames larger than the user limit just set error flags.  */
                    383:     if (size > (s->rcr >> 16)) {
                    384:         flags |= FEC_BD_LG;
                    385:     }
                    386:     addr = s->rx_descriptor;
                    387:     while (size > 0) {
                    388:         mcf_fec_read_bd(&bd, addr);
                    389:         if ((bd.flags & FEC_BD_E) == 0) {
                    390:             /* No descriptors available.  Bail out.  */
                    391:             /* FIXME: This is wrong.  We should probably either save the
                    392:                remainder for when more RX buffers are available, or
                    393:                flag an error.  */
                    394:             fprintf(stderr, "mcf_fec: Lost end of frame\n");
                    395:             break;
                    396:         }
                    397:         buf_len = (size <= s->emrbr) ? size: s->emrbr;
                    398:         bd.length = buf_len;
                    399:         size -= buf_len;
                    400:         DPRINTF("rx_bd %x length %d\n", addr, bd.length);
                    401:         /* The last 4 bytes are the CRC.  */
                    402:         if (size < 4)
                    403:             buf_len += size - 4;
                    404:         buf_addr = bd.data;
                    405:         cpu_physical_memory_write(buf_addr, buf, buf_len);
                    406:         buf += buf_len;
                    407:         if (size < 4) {
                    408:             cpu_physical_memory_write(buf_addr + buf_len, crc_ptr, 4 - size);
                    409:             crc_ptr += 4 - size;
                    410:         }
                    411:         bd.flags &= ~FEC_BD_E;
                    412:         if (size == 0) {
                    413:             /* Last buffer in frame.  */
                    414:             bd.flags |= flags | FEC_BD_L;
                    415:             DPRINTF("rx frame flags %04x\n", bd.flags);
                    416:             s->eir |= FEC_INT_RXF;
                    417:         } else {
                    418:             s->eir |= FEC_INT_RXB;
                    419:         }
                    420:         mcf_fec_write_bd(&bd, addr);
                    421:         /* Advance to the next descriptor.  */
                    422:         if ((bd.flags & FEC_BD_W) != 0) {
                    423:             addr = s->erdsr;
                    424:         } else {
                    425:             addr += 8;
                    426:         }
                    427:     }
                    428:     s->rx_descriptor = addr;
                    429:     mcf_fec_enable_rx(s);
                    430:     mcf_fec_update(s);
                    431: }
                    432: 
                    433: static CPUReadMemoryFunc *mcf_fec_readfn[] = {
                    434:    mcf_fec_read,
                    435:    mcf_fec_read,
                    436:    mcf_fec_read
                    437: };
                    438: 
                    439: static CPUWriteMemoryFunc *mcf_fec_writefn[] = {
                    440:    mcf_fec_write,
                    441:    mcf_fec_write,
                    442:    mcf_fec_write
                    443: };
                    444: 
1.1.1.3 ! root      445: static void mcf_fec_cleanup(VLANClientState *vc)
        !           446: {
        !           447:     mcf_fec_state *s = vc->opaque;
        !           448: 
        !           449:     cpu_unregister_io_memory(s->mmio_index);
        !           450: 
        !           451:     qemu_free(s);
        !           452: }
        !           453: 
1.1       root      454: void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
                    455: {
                    456:     mcf_fec_state *s;
                    457: 
1.1.1.2   root      458:     qemu_check_nic_model(nd, "mcf_fec");
                    459: 
1.1       root      460:     s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state));
                    461:     s->irq = irq;
1.1.1.3 ! root      462:     s->mmio_index = cpu_register_io_memory(0, mcf_fec_readfn,
        !           463:                                            mcf_fec_writefn, s);
        !           464:     cpu_register_physical_memory(base, 0x400, s->mmio_index);
1.1       root      465: 
1.1.1.2   root      466:     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
1.1.1.3 ! root      467:                                  mcf_fec_receive, mcf_fec_can_receive,
        !           468:                                  mcf_fec_cleanup, s);
1.1       root      469:     memcpy(s->macaddr, nd->macaddr, 6);
1.1.1.2   root      470:     qemu_format_nic_info_str(s->vc, s->macaddr);
1.1       root      471: }

unix.superglobalmegacorp.com

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