Commit 7e049b8a19e934a8b4a8807d5d2452e0749eac6c

Authored by pbrook
1 parent d0bdf2a2

ColdFire Ethernet support.


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