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

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;
                     27:     VLANClientState *vc;
                     28:     uint32_t irq_state;
                     29:     uint32_t eir;
                     30:     uint32_t eimr;
                     31:     int rx_enabled;
                     32:     uint32_t rx_descriptor;
                     33:     uint32_t tx_descriptor;
                     34:     uint32_t ecr;
                     35:     uint32_t mmfr;
                     36:     uint32_t mscr;
                     37:     uint32_t rcr;
                     38:     uint32_t tcr;
                     39:     uint32_t tfwr;
                     40:     uint32_t rfsr;
                     41:     uint32_t erdsr;
                     42:     uint32_t etdsr;
                     43:     uint32_t emrbr;
                     44:     uint8_t macaddr[6];
                     45: } mcf_fec_state;
                     46: 
                     47: #define FEC_INT_HB   0x80000000
                     48: #define FEC_INT_BABR 0x40000000
                     49: #define FEC_INT_BABT 0x20000000
                     50: #define FEC_INT_GRA  0x10000000
                     51: #define FEC_INT_TXF  0x08000000
                     52: #define FEC_INT_TXB  0x04000000
                     53: #define FEC_INT_RXF  0x02000000
                     54: #define FEC_INT_RXB  0x01000000
                     55: #define FEC_INT_MII  0x00800000
                     56: #define FEC_INT_EB   0x00400000
                     57: #define FEC_INT_LC   0x00200000
                     58: #define FEC_INT_RL   0x00100000
                     59: #define FEC_INT_UN   0x00080000
                     60: 
                     61: #define FEC_EN      2
                     62: #define FEC_RESET   1
                     63: 
                     64: /* Map interrupt flags onto IRQ lines.  */
                     65: #define FEC_NUM_IRQ 13
                     66: static const uint32_t mcf_fec_irq_map[FEC_NUM_IRQ] = {
                     67:     FEC_INT_TXF,
                     68:     FEC_INT_TXB,
                     69:     FEC_INT_UN,
                     70:     FEC_INT_RL,
                     71:     FEC_INT_RXF,
                     72:     FEC_INT_RXB,
                     73:     FEC_INT_MII,
                     74:     FEC_INT_LC,
                     75:     FEC_INT_HB,
                     76:     FEC_INT_GRA,
                     77:     FEC_INT_EB,
                     78:     FEC_INT_BABT,
                     79:     FEC_INT_BABR
                     80: };
                     81: 
                     82: /* Buffer Descriptor.  */
                     83: typedef struct {
                     84:     uint16_t flags;
                     85:     uint16_t length;
                     86:     uint32_t data;
                     87: } mcf_fec_bd;
                     88: 
                     89: #define FEC_BD_R    0x8000
                     90: #define FEC_BD_E    0x8000
                     91: #define FEC_BD_O1   0x4000
                     92: #define FEC_BD_W    0x2000
                     93: #define FEC_BD_O2   0x1000
                     94: #define FEC_BD_L    0x0800
                     95: #define FEC_BD_TC   0x0400
                     96: #define FEC_BD_ABC  0x0200
                     97: #define FEC_BD_M    0x0100
                     98: #define FEC_BD_BC   0x0080
                     99: #define FEC_BD_MC   0x0040
                    100: #define FEC_BD_LG   0x0020
                    101: #define FEC_BD_NO   0x0010
                    102: #define FEC_BD_CR   0x0004
                    103: #define FEC_BD_OV   0x0002
                    104: #define FEC_BD_TR   0x0001
                    105: 
                    106: static void mcf_fec_read_bd(mcf_fec_bd *bd, uint32_t addr)
                    107: {
                    108:     cpu_physical_memory_read(addr, (uint8_t *)bd, sizeof(*bd));
                    109:     be16_to_cpus(&bd->flags);
                    110:     be16_to_cpus(&bd->length);
                    111:     be32_to_cpus(&bd->data);
                    112: }
                    113: 
                    114: static void mcf_fec_write_bd(mcf_fec_bd *bd, uint32_t addr)
                    115: {
                    116:     mcf_fec_bd tmp;
                    117:     tmp.flags = cpu_to_be16(bd->flags);
                    118:     tmp.length = cpu_to_be16(bd->length);
                    119:     tmp.data = cpu_to_be32(bd->data);
                    120:     cpu_physical_memory_write(addr, (uint8_t *)&tmp, sizeof(tmp));
                    121: }
                    122: 
                    123: static void mcf_fec_update(mcf_fec_state *s)
                    124: {
                    125:     uint32_t active;
                    126:     uint32_t changed;
                    127:     uint32_t mask;
                    128:     int i;
                    129: 
                    130:     active = s->eir & s->eimr;
                    131:     changed = active ^s->irq_state;
                    132:     for (i = 0; i < FEC_NUM_IRQ; i++) {
                    133:         mask = mcf_fec_irq_map[i];
                    134:         if (changed & mask) {
                    135:             DPRINTF("IRQ %d = %d\n", i, (active & mask) != 0);
                    136:             qemu_set_irq(s->irq[i], (active & mask) != 0);
                    137:         }
                    138:     }
                    139:     s->irq_state = active;
                    140: }
                    141: 
                    142: static void mcf_fec_do_tx(mcf_fec_state *s)
                    143: {
                    144:     uint32_t addr;
                    145:     mcf_fec_bd bd;
                    146:     int frame_size;
                    147:     int len;
                    148:     uint8_t frame[FEC_MAX_FRAME_SIZE];
                    149:     uint8_t *ptr;
                    150: 
                    151:     DPRINTF("do_tx\n");
                    152:     ptr = frame;
                    153:     frame_size = 0;
                    154:     addr = s->tx_descriptor;
                    155:     while (1) {
                    156:         mcf_fec_read_bd(&bd, addr);
                    157:         DPRINTF("tx_bd %x flags %04x len %d data %08x\n",
                    158:                 addr, bd.flags, bd.length, bd.data);
                    159:         if ((bd.flags & FEC_BD_R) == 0) {
                    160:             /* Run out of descriptors to transmit.  */
                    161:             break;
                    162:         }
                    163:         len = bd.length;
                    164:         if (frame_size + len > FEC_MAX_FRAME_SIZE) {
                    165:             len = FEC_MAX_FRAME_SIZE - frame_size;
                    166:             s->eir |= FEC_INT_BABT;
                    167:         }
                    168:         cpu_physical_memory_read(bd.data, ptr, len);
                    169:         ptr += len;
                    170:         frame_size += len;
                    171:         if (bd.flags & FEC_BD_L) {
                    172:             /* Last buffer in frame.  */
                    173:             DPRINTF("Sending packet\n");
                    174:             qemu_send_packet(s->vc, frame, len);
                    175:             ptr = frame;
                    176:             frame_size = 0;
                    177:             s->eir |= FEC_INT_TXF;
                    178:         }
                    179:         s->eir |= FEC_INT_TXB;
                    180:         bd.flags &= ~FEC_BD_R;
                    181:         /* Write back the modified descriptor.  */
                    182:         mcf_fec_write_bd(&bd, addr);
                    183:         /* Advance to the next descriptor.  */
                    184:         if ((bd.flags & FEC_BD_W) != 0) {
                    185:             addr = s->etdsr;
                    186:         } else {
                    187:             addr += 8;
                    188:         }
                    189:     }
                    190:     s->tx_descriptor = addr;
                    191: }
                    192: 
                    193: static void mcf_fec_enable_rx(mcf_fec_state *s)
                    194: {
                    195:     mcf_fec_bd bd;
                    196: 
                    197:     mcf_fec_read_bd(&bd, s->rx_descriptor);
                    198:     s->rx_enabled = ((bd.flags & FEC_BD_E) != 0);
                    199:     if (!s->rx_enabled)
                    200:         DPRINTF("RX buffer full\n");
                    201: }
                    202: 
                    203: static void mcf_fec_reset(mcf_fec_state *s)
                    204: {
                    205:     s->eir = 0;
                    206:     s->eimr = 0;
                    207:     s->rx_enabled = 0;
                    208:     s->ecr = 0;
                    209:     s->mscr = 0;
                    210:     s->rcr = 0x05ee0001;
                    211:     s->tcr = 0;
                    212:     s->tfwr = 0;
                    213:     s->rfsr = 0x500;
                    214: }
                    215: 
                    216: static uint32_t mcf_fec_read(void *opaque, target_phys_addr_t addr)
                    217: {
                    218:     mcf_fec_state *s = (mcf_fec_state *)opaque;
                    219:     switch (addr & 0x3ff) {
                    220:     case 0x004: return s->eir;
                    221:     case 0x008: return s->eimr;
                    222:     case 0x010: return s->rx_enabled ? (1 << 24) : 0; /* RDAR */
                    223:     case 0x014: return 0; /* TDAR */
                    224:     case 0x024: return s->ecr;
                    225:     case 0x040: return s->mmfr;
                    226:     case 0x044: return s->mscr;
                    227:     case 0x064: return 0; /* MIBC */
                    228:     case 0x084: return s->rcr;
                    229:     case 0x0c4: return s->tcr;
                    230:     case 0x0e4: /* PALR */
                    231:         return (s->macaddr[0] << 24) | (s->macaddr[1] << 16)
                    232:               | (s->macaddr[2] << 8) | s->macaddr[3];
                    233:         break;
                    234:     case 0x0e8: /* PAUR */
                    235:         return (s->macaddr[4] << 24) | (s->macaddr[5] << 16) | 0x8808;
                    236:     case 0x0ec: return 0x10000; /* OPD */
                    237:     case 0x118: return 0;
                    238:     case 0x11c: return 0;
                    239:     case 0x120: return 0;
                    240:     case 0x124: return 0;
                    241:     case 0x144: return s->tfwr;
                    242:     case 0x14c: return 0x600;
                    243:     case 0x150: return s->rfsr;
                    244:     case 0x180: return s->erdsr;
                    245:     case 0x184: return s->etdsr;
                    246:     case 0x188: return s->emrbr;
                    247:     default:
                    248:         cpu_abort(cpu_single_env, "mcf_fec_read: Bad address 0x%x\n",
                    249:                   (int)addr);
                    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:
                    345:         cpu_abort(cpu_single_env, "mcf_fec_write Bad address 0x%x\n",
                    346:                   (int)addr);
                    347:     }
                    348:     mcf_fec_update(s);
                    349: }
                    350: 
                    351: static int mcf_fec_can_receive(void *opaque)
                    352: {
                    353:     mcf_fec_state *s = (mcf_fec_state *)opaque;
                    354:     return s->rx_enabled;
                    355: }
                    356: 
                    357: static void mcf_fec_receive(void *opaque, const uint8_t *buf, int size)
                    358: {
                    359:     mcf_fec_state *s = (mcf_fec_state *)opaque;
                    360:     mcf_fec_bd bd;
                    361:     uint32_t flags = 0;
                    362:     uint32_t addr;
                    363:     uint32_t crc;
                    364:     uint32_t buf_addr;
                    365:     uint8_t *crc_ptr;
                    366:     unsigned int buf_len;
                    367: 
                    368:     DPRINTF("do_rx len %d\n", size);
                    369:     if (!s->rx_enabled) {
                    370:         fprintf(stderr, "mcf_fec_receive: Unexpected packet\n");
                    371:     }
                    372:     /* 4 bytes for the CRC.  */
                    373:     size += 4;
                    374:     crc = cpu_to_be32(crc32(~0, buf, size));
                    375:     crc_ptr = (uint8_t *)&crc;
                    376:     /* Huge frames are truncted.  */
                    377:     if (size > FEC_MAX_FRAME_SIZE) {
                    378:         size = FEC_MAX_FRAME_SIZE;
                    379:         flags |= FEC_BD_TR | FEC_BD_LG;
                    380:     }
                    381:     /* Frames larger than the user limit just set error flags.  */
                    382:     if (size > (s->rcr >> 16)) {
                    383:         flags |= FEC_BD_LG;
                    384:     }
                    385:     addr = s->rx_descriptor;
                    386:     while (size > 0) {
                    387:         mcf_fec_read_bd(&bd, addr);
                    388:         if ((bd.flags & FEC_BD_E) == 0) {
                    389:             /* No descriptors available.  Bail out.  */
                    390:             /* FIXME: This is wrong.  We should probably either save the
                    391:                remainder for when more RX buffers are available, or
                    392:                flag an error.  */
                    393:             fprintf(stderr, "mcf_fec: Lost end of frame\n");
                    394:             break;
                    395:         }
                    396:         buf_len = (size <= s->emrbr) ? size: s->emrbr;
                    397:         bd.length = buf_len;
                    398:         size -= buf_len;
                    399:         DPRINTF("rx_bd %x length %d\n", addr, bd.length);
                    400:         /* The last 4 bytes are the CRC.  */
                    401:         if (size < 4)
                    402:             buf_len += size - 4;
                    403:         buf_addr = bd.data;
                    404:         cpu_physical_memory_write(buf_addr, buf, buf_len);
                    405:         buf += buf_len;
                    406:         if (size < 4) {
                    407:             cpu_physical_memory_write(buf_addr + buf_len, crc_ptr, 4 - size);
                    408:             crc_ptr += 4 - size;
                    409:         }
                    410:         bd.flags &= ~FEC_BD_E;
                    411:         if (size == 0) {
                    412:             /* Last buffer in frame.  */
                    413:             bd.flags |= flags | FEC_BD_L;
                    414:             DPRINTF("rx frame flags %04x\n", bd.flags);
                    415:             s->eir |= FEC_INT_RXF;
                    416:         } else {
                    417:             s->eir |= FEC_INT_RXB;
                    418:         }
                    419:         mcf_fec_write_bd(&bd, addr);
                    420:         /* Advance to the next descriptor.  */
                    421:         if ((bd.flags & FEC_BD_W) != 0) {
                    422:             addr = s->erdsr;
                    423:         } else {
                    424:             addr += 8;
                    425:         }
                    426:     }
                    427:     s->rx_descriptor = addr;
                    428:     mcf_fec_enable_rx(s);
                    429:     mcf_fec_update(s);
                    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: 
                    444: void mcf_fec_init(NICInfo *nd, target_phys_addr_t base, qemu_irq *irq)
                    445: {
                    446:     mcf_fec_state *s;
                    447:     int iomemtype;
                    448: 
1.1.1.2 ! root      449:     qemu_check_nic_model(nd, "mcf_fec");
        !           450: 
1.1       root      451:     s = (mcf_fec_state *)qemu_mallocz(sizeof(mcf_fec_state));
                    452:     s->irq = irq;
                    453:     iomemtype = cpu_register_io_memory(0, mcf_fec_readfn,
                    454:                                        mcf_fec_writefn, s);
                    455:     cpu_register_physical_memory(base, 0x400, iomemtype);
                    456: 
1.1.1.2 ! root      457:     s->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
        !           458:                                  mcf_fec_receive, mcf_fec_can_receive, s);
1.1       root      459:     memcpy(s->macaddr, nd->macaddr, 6);
1.1.1.2 ! root      460:     qemu_format_nic_info_str(s->vc, s->macaddr);
1.1       root      461: }

unix.superglobalmegacorp.com

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