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

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
1.1.1.4 ! root       17: #define DPRINTF(fmt, ...) \
        !            18: do { printf("mcf_fec: " fmt , ## __VA_ARGS__); } while (0)
1.1       root       19: #else
1.1.1.4 ! root       20: #define DPRINTF(fmt, ...) do {} while(0)
1.1       root       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:
1.1.1.4 ! root      249:         hw_error("mcf_fec_read: Bad address 0x%x\n", (int)addr);
1.1       root      250:         return 0;
                    251:     }
                    252: }
                    253: 
                    254: static void mcf_fec_write(void *opaque, target_phys_addr_t addr, uint32_t value)
                    255: {
                    256:     mcf_fec_state *s = (mcf_fec_state *)opaque;
                    257:     switch (addr & 0x3ff) {
                    258:     case 0x004:
                    259:         s->eir &= ~value;
                    260:         break;
                    261:     case 0x008:
                    262:         s->eimr = value;
                    263:         break;
                    264:     case 0x010: /* RDAR */
                    265:         if ((s->ecr & FEC_EN) && !s->rx_enabled) {
                    266:             DPRINTF("RX enable\n");
                    267:             mcf_fec_enable_rx(s);
                    268:         }
                    269:         break;
                    270:     case 0x014: /* TDAR */
                    271:         if (s->ecr & FEC_EN) {
                    272:             mcf_fec_do_tx(s);
                    273:         }
                    274:         break;
                    275:     case 0x024:
                    276:         s->ecr = value;
                    277:         if (value & FEC_RESET) {
                    278:             DPRINTF("Reset\n");
                    279:             mcf_fec_reset(s);
                    280:         }
                    281:         if ((s->ecr & FEC_EN) == 0) {
                    282:             s->rx_enabled = 0;
                    283:         }
                    284:         break;
                    285:     case 0x040:
                    286:         /* TODO: Implement MII.  */
                    287:         s->mmfr = value;
                    288:         break;
                    289:     case 0x044:
                    290:         s->mscr = value & 0xfe;
                    291:         break;
                    292:     case 0x064:
                    293:         /* TODO: Implement MIB.  */
                    294:         break;
                    295:     case 0x084:
                    296:         s->rcr = value & 0x07ff003f;
                    297:         /* TODO: Implement LOOP mode.  */
                    298:         break;
                    299:     case 0x0c4: /* TCR */
                    300:         /* We transmit immediately, so raise GRA immediately.  */
                    301:         s->tcr = value;
                    302:         if (value & 1)
                    303:             s->eir |= FEC_INT_GRA;
                    304:         break;
                    305:     case 0x0e4: /* PALR */
                    306:         s->macaddr[0] = value >> 24;
                    307:         s->macaddr[1] = value >> 16;
                    308:         s->macaddr[2] = value >> 8;
                    309:         s->macaddr[3] = value;
                    310:         break;
                    311:     case 0x0e8: /* PAUR */
                    312:         s->macaddr[4] = value >> 24;
                    313:         s->macaddr[5] = value >> 16;
                    314:         break;
                    315:     case 0x0ec:
                    316:         /* OPD */
                    317:         break;
                    318:     case 0x118:
                    319:     case 0x11c:
                    320:     case 0x120:
                    321:     case 0x124:
                    322:         /* TODO: implement MAC hash filtering.  */
                    323:         break;
                    324:     case 0x144:
                    325:         s->tfwr = value & 3;
                    326:         break;
                    327:     case 0x14c:
                    328:         /* FRBR writes ignored.  */
                    329:         break;
                    330:     case 0x150:
                    331:         s->rfsr = (value & 0x3fc) | 0x400;
                    332:         break;
                    333:     case 0x180:
                    334:         s->erdsr = value & ~3;
                    335:         s->rx_descriptor = s->erdsr;
                    336:         break;
                    337:     case 0x184:
                    338:         s->etdsr = value & ~3;
                    339:         s->tx_descriptor = s->etdsr;
                    340:         break;
                    341:     case 0x188:
                    342:         s->emrbr = value & 0x7f0;
                    343:         break;
                    344:     default:
1.1.1.4 ! root      345:         hw_error("mcf_fec_write Bad address 0x%x\n", (int)addr);
1.1       root      346:     }
                    347:     mcf_fec_update(s);
                    348: }
                    349: 
1.1.1.4 ! root      350: static int mcf_fec_can_receive(VLANClientState *vc)
1.1       root      351: {
1.1.1.4 ! root      352:     mcf_fec_state *s = vc->opaque;
1.1       root      353:     return s->rx_enabled;
                    354: }
                    355: 
1.1.1.4 ! root      356: static ssize_t mcf_fec_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
1.1       root      357: {
1.1.1.4 ! root      358:     mcf_fec_state *s = vc->opaque;
1.1       root      359:     mcf_fec_bd bd;
                    360:     uint32_t flags = 0;
                    361:     uint32_t addr;
                    362:     uint32_t crc;
                    363:     uint32_t buf_addr;
                    364:     uint8_t *crc_ptr;
                    365:     unsigned int buf_len;
                    366: 
                    367:     DPRINTF("do_rx len %d\n", size);
                    368:     if (!s->rx_enabled) {
                    369:         fprintf(stderr, "mcf_fec_receive: Unexpected packet\n");
                    370:     }
                    371:     /* 4 bytes for the CRC.  */
                    372:     size += 4;
                    373:     crc = cpu_to_be32(crc32(~0, buf, size));
                    374:     crc_ptr = (uint8_t *)&crc;
                    375:     /* Huge frames are truncted.  */
                    376:     if (size > FEC_MAX_FRAME_SIZE) {
                    377:         size = FEC_MAX_FRAME_SIZE;
                    378:         flags |= FEC_BD_TR | FEC_BD_LG;
                    379:     }
                    380:     /* Frames larger than the user limit just set error flags.  */
                    381:     if (size > (s->rcr >> 16)) {
                    382:         flags |= FEC_BD_LG;
                    383:     }
                    384:     addr = s->rx_descriptor;
                    385:     while (size > 0) {
                    386:         mcf_fec_read_bd(&bd, addr);
                    387:         if ((bd.flags & FEC_BD_E) == 0) {
                    388:             /* No descriptors available.  Bail out.  */
                    389:             /* FIXME: This is wrong.  We should probably either save the
                    390:                remainder for when more RX buffers are available, or
                    391:                flag an error.  */
                    392:             fprintf(stderr, "mcf_fec: Lost end of frame\n");
                    393:             break;
                    394:         }
                    395:         buf_len = (size <= s->emrbr) ? size: s->emrbr;
                    396:         bd.length = buf_len;
                    397:         size -= buf_len;
                    398:         DPRINTF("rx_bd %x length %d\n", addr, bd.length);
                    399:         /* The last 4 bytes are the CRC.  */
                    400:         if (size < 4)
                    401:             buf_len += size - 4;
                    402:         buf_addr = bd.data;
                    403:         cpu_physical_memory_write(buf_addr, buf, buf_len);
                    404:         buf += buf_len;
                    405:         if (size < 4) {
                    406:             cpu_physical_memory_write(buf_addr + buf_len, crc_ptr, 4 - size);
                    407:             crc_ptr += 4 - size;
                    408:         }
                    409:         bd.flags &= ~FEC_BD_E;
                    410:         if (size == 0) {
                    411:             /* Last buffer in frame.  */
                    412:             bd.flags |= flags | FEC_BD_L;
                    413:             DPRINTF("rx frame flags %04x\n", bd.flags);
                    414:             s->eir |= FEC_INT_RXF;
                    415:         } else {
                    416:             s->eir |= FEC_INT_RXB;
                    417:         }
                    418:         mcf_fec_write_bd(&bd, addr);
                    419:         /* Advance to the next descriptor.  */
                    420:         if ((bd.flags & FEC_BD_W) != 0) {
                    421:             addr = s->erdsr;
                    422:         } else {
                    423:             addr += 8;
                    424:         }
                    425:     }
                    426:     s->rx_descriptor = addr;
                    427:     mcf_fec_enable_rx(s);
                    428:     mcf_fec_update(s);
1.1.1.4 ! root      429:     return size;
1.1       root      430: }
                    431: 
                    432: static CPUReadMemoryFunc *mcf_fec_readfn[] = {
                    433:    mcf_fec_read,
                    434:    mcf_fec_read,
                    435:    mcf_fec_read
                    436: };
                    437: 
                    438: static CPUWriteMemoryFunc *mcf_fec_writefn[] = {
                    439:    mcf_fec_write,
                    440:    mcf_fec_write,
                    441:    mcf_fec_write
                    442: };
                    443: 
1.1.1.3   root      444: static void mcf_fec_cleanup(VLANClientState *vc)
                    445: {
                    446:     mcf_fec_state *s = vc->opaque;
                    447: 
                    448:     cpu_unregister_io_memory(s->mmio_index);
                    449: 
                    450:     qemu_free(s);
                    451: }
                    452: 
1.1       root      453: void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
                    454: {
                    455:     mcf_fec_state *s;
                    456: 
1.1.1.2   root      457:     qemu_check_nic_model(nd, "mcf_fec");
                    458: 
1.1       root      459:     s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state));
                    460:     s->irq = irq;
1.1.1.4 ! root      461:     s->mmio_index = cpu_register_io_memory(mcf_fec_readfn,
1.1.1.3   root      462:                                            mcf_fec_writefn, s);
                    463:     cpu_register_physical_memory(base, 0x400, s->mmio_index);
1.1       root      464: 
1.1.1.4 ! root      465:     s->vc = nd->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
        !           466:                                           mcf_fec_can_receive, mcf_fec_receive,
        !           467:                                           NULL, mcf_fec_cleanup, s);
1.1       root      468:     memcpy(s->macaddr, nd->macaddr, 6);
1.1.1.2   root      469:     qemu_format_nic_info_str(s->vc, s->macaddr);
1.1       root      470: }

unix.superglobalmegacorp.com

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