OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [peripheral/] [eth.c] - Blame information for rev 442

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 19 jeremybenn
/* ethernet.c -- Simulation of Ethernet MAC
2
 
3
   Copyright (C) 2001 by Erez Volk, erez@opencores.org
4
                         Ivan Guzvinec, ivang@opencores.org
5
   Copyright (C) 2008 Embecosm Limited
6 437 julius
   Copyright (C) 2010 ORSoC
7 19 jeremybenn
 
8
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
9 437 julius
   Contributor Julius Baxter <julius@orsoc.se>
10 19 jeremybenn
 
11
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
12
 
13
   This program is free software; you can redistribute it and/or modify it
14
   under the terms of the GNU General Public License as published by the Free
15
   Software Foundation; either version 3 of the License, or (at your option)
16
   any later version.
17
 
18
   This program is distributed in the hope that it will be useful, but WITHOUT
19
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
21
   more details.
22
 
23
   You should have received a copy of the GNU General Public License along
24
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
25
 
26
/* This program is commented throughout in a fashion suitable for processing
27
   with Doxygen. */
28
 
29
 
30
/* Autoconf and/or portability configuration */
31
#include "config.h"
32
#include "port.h"
33
 
34
/* System includes */
35
#include <stdlib.h>
36
#include <stdio.h>
37 434 jeremybenn
 
38
#include <sys/socket.h>
39
#include <sys/ioctl.h>
40
#include <sys/stat.h>
41 19 jeremybenn
#include <sys/types.h>
42
#include <fcntl.h>
43 434 jeremybenn
 
44 19 jeremybenn
#include <sys/poll.h>
45
#include <unistd.h>
46
#include <errno.h>
47
 
48 434 jeremybenn
#include <linux/if.h>
49
#include <linux/if_tun.h>
50
 
51 19 jeremybenn
/* Package includes */
52
#include "arch.h"
53
#include "config.h"
54
#include "abstract.h"
55
#include "eth.h"
56
#include "dma.h"
57
#include "sim-config.h"
58
#include "fields.h"
59
#include "crc32.h"
60
#include "vapi.h"
61
#include "pic.h"
62
#include "sched.h"
63
#include "toplevel-support.h"
64
#include "sim-cmd.h"
65
 
66
struct eth_device
67
{
68
  /* Is peripheral enabled */
69
  int enabled;
70
 
71
  /* Base address in memory */
72
  oraddr_t baseaddr;
73
 
74
  /* Which DMA controller is this MAC connected to */
75
  unsigned dma;
76
  unsigned tx_channel;
77
  unsigned rx_channel;
78
 
79
  /* Our address */
80
  unsigned char mac_address[ETHER_ADDR_LEN];
81
 
82 437 julius
  /* interrupt line number */
83 19 jeremybenn
  unsigned long mac_int;
84
 
85 437 julius
  /* interrupt line status */
86
  int int_line_stat;
87
 
88 19 jeremybenn
  /* VAPI ID */
89
  unsigned long base_vapi_id;
90
 
91 428 julius
  /* Ethernet PHY address */
92
  unsigned long phy_addr;
93
 
94 434 jeremybenn
  /* What sort of external I/F: FILE or TAP */
95
  int rtx_type;
96
 
97
  /* RX and TX file names and handles for FILE type connection. */
98 19 jeremybenn
  char *rxfile, *txfile;
99
  int txfd;
100
  int rxfd;
101
  off_t loopback_offset;
102
 
103 434 jeremybenn
  /* Info for TAP type connections */
104
  int   rtx_fd;
105
  char *tap_dev;
106 19 jeremybenn
 
107
  /* Current TX state */
108
  struct
109
  {
110
    unsigned long state;
111
    unsigned long bd_index;
112
    unsigned long bd;
113
    unsigned long bd_addr;
114
    unsigned working, waiting_for_dma, error;
115
    long packet_length;
116
    unsigned minimum_length, maximum_length;
117
    unsigned add_crc;
118
    unsigned crc_dly;
119
    unsigned long crc_value;
120
    long bytes_left, bytes_sent;
121
  } tx;
122
 
123
  /* Current RX state */
124
  struct
125
  {
126
    unsigned long state;
127
    unsigned long bd_index;
128
    unsigned long bd;
129
    unsigned long bd_addr;
130
    int fd;
131
    off_t *offset;
132
    unsigned working, error, waiting_for_dma;
133
    long packet_length, bytes_read, bytes_left;
134
  } rx;
135
 
136
  /* Visible registers */
137
  struct
138
  {
139
    unsigned long moder;
140
    unsigned long int_source;
141
    unsigned long int_mask;
142
    unsigned long ipgt;
143
    unsigned long ipgr1;
144
    unsigned long ipgr2;
145
    unsigned long packetlen;
146
    unsigned long collconf;
147
    unsigned long tx_bd_num;
148
    unsigned long controlmoder;
149
    unsigned long miimoder;
150
    unsigned long miicommand;
151
    unsigned long miiaddress;
152
    unsigned long miitx_data;
153
    unsigned long miirx_data;
154
    unsigned long miistatus;
155
    unsigned long hash0;
156
    unsigned long hash1;
157
 
158
    /* Buffer descriptors */
159
    unsigned long bd_ram[ETH_BD_SPACE / 4];
160
  } regs;
161
 
162
  unsigned char rx_buff[ETH_MAXPL];
163
  unsigned char tx_buff[ETH_MAXPL];
164
  unsigned char lo_buff[ETH_MAXPL];
165
};
166
 
167
 
168
/* simulator interface */
169
static void eth_vapi_read (unsigned long id, unsigned long data, void *dat);
170
/* register interface */
171
static void eth_write32 (oraddr_t addr, uint32_t value, void *dat);
172
static uint32_t eth_read32 (oraddr_t addr, void *dat);
173
/* clock */
174
static void eth_controller_tx_clock (void *);
175
static void eth_controller_rx_clock (void *);
176
/* utility functions */
177
static ssize_t eth_read_rx_file (struct eth_device *, void *, size_t);
178
static void eth_skip_rx_file (struct eth_device *, off_t);
179
static void eth_rx_next_packet (struct eth_device *);
180
static void eth_write_tx_bd_num (struct eth_device *, unsigned long value);
181 428 julius
static void eth_miim_trans (void *dat);
182 434 jeremybenn
 
183 437 julius
#define ETH_DEBUG 0
184 434 jeremybenn
 
185 437 julius
 
186 434 jeremybenn
/* ========================================================================== */
187
/* Dummy socket routines. These are the points where we spoof an Ethernet     */
188
/* network.                                                                   */
189
/* -------------------------------------------------------------------------- */
190
 
191
 
192 19 jeremybenn
/* ========================================================================= */
193
/*  TX LOGIC                                                                 */
194
/*---------------------------------------------------------------------------*/
195
 
196
/*
197
 * TX clock
198
 * Responsible for starting and finishing TX
199
 */
200
static void
201
eth_controller_tx_clock (void *dat)
202
{
203
  struct eth_device *eth = dat;
204
  int bAdvance = 1;
205
  long nwritten = 0;
206
  unsigned long read_word;
207
 
208
  switch (eth->tx.state)
209
    {
210
    case ETH_TXSTATE_IDLE:
211
      eth->tx.state = ETH_TXSTATE_WAIT4BD;
212
      break;
213
    case ETH_TXSTATE_WAIT4BD:
214
      /* Read buffer descriptor */
215
      eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index];
216
      eth->tx.bd_addr = eth->regs.bd_ram[eth->tx.bd_index + 1];
217
 
218
      if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, READY))
219
        {
220
            /*****************/
221
          /* initialize TX */
222
          eth->tx.bytes_left = eth->tx.packet_length =
223
            GET_FIELD (eth->tx.bd, ETH_TX_BD, LENGTH);
224
          eth->tx.bytes_sent = 0;
225
 
226
          /*   Initialize error status bits */
227
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, DEFER);
228
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION);
229
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, RETRANSMIT);
230
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, UNDERRUN);
231
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, NO_CARRIER);
232
          SET_FIELD (eth->tx.bd, ETH_TX_BD, RETRY, 0);
233
 
234
          /* Find out minimum length */
235
          if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, PAD) ||
236
              TEST_FLAG (eth->regs.moder, ETH_MODER, PAD))
237
            eth->tx.minimum_length =
238
              GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL);
239
          else
240
            eth->tx.minimum_length = eth->tx.packet_length;
241
 
242
          /* Find out maximum length */
243
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, HUGEN))
244
            eth->tx.maximum_length = eth->tx.packet_length;
245
          else
246
            eth->tx.maximum_length =
247
              GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MAXFL);
248
 
249
          /* Do we need CRC on this packet? */
250
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, CRCEN) ||
251
              (TEST_FLAG (eth->tx.bd, ETH_TX_BD, CRC) &&
252
               TEST_FLAG (eth->tx.bd, ETH_TX_BD, LAST)))
253
            eth->tx.add_crc = 1;
254
          else
255
            eth->tx.add_crc = 0;
256
 
257
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, DLYCRCEN))
258
            eth->tx.crc_dly = 1;
259
          else
260
            eth->tx.crc_dly = 0;
261
          /* XXX - For now we skip CRC calculation */
262
 
263
          if (eth->rtx_type == ETH_RTX_FILE)
264
            {
265
              /* write packet length to file */
266
              nwritten =
267
                write (eth->txfd, &(eth->tx.packet_length),
268
                       sizeof (eth->tx.packet_length));
269
            }
270
 
271
            /************************************************/
272
          /* start transmit with reading packet into FIFO */
273
          eth->tx.state = ETH_TXSTATE_READFIFO;
274
        }
275
 
276
      /* stay in this state if (TXEN && !READY) */
277
      break;
278
    case ETH_TXSTATE_READFIFO:
279 436 julius
      //if (eth->tx.bytes_sent < eth->tx.packet_length)
280
      while (eth->tx.bytes_sent < eth->tx.packet_length)
281 19 jeremybenn
        {
282
          read_word =
283
            eval_direct32 (eth->tx.bytes_sent + eth->tx.bd_addr, 0, 0);
284
          eth->tx_buff[eth->tx.bytes_sent] =
285
            (unsigned char) (read_word >> 24);
286
          eth->tx_buff[eth->tx.bytes_sent + 1] =
287
            (unsigned char) (read_word >> 16);
288
          eth->tx_buff[eth->tx.bytes_sent + 2] =
289
            (unsigned char) (read_word >> 8);
290
          eth->tx_buff[eth->tx.bytes_sent + 3] = (unsigned char) (read_word);
291
          eth->tx.bytes_sent += 4;
292
        }
293 436 julius
      //else
294
      //        {
295 19 jeremybenn
          eth->tx.state = ETH_TXSTATE_TRANSMIT;
296 436 julius
          //    }
297 19 jeremybenn
      break;
298
    case ETH_TXSTATE_TRANSMIT:
299
      /* send packet */
300
      switch (eth->rtx_type)
301
        {
302
        case ETH_RTX_FILE:
303
          nwritten = write (eth->txfd, eth->tx_buff, eth->tx.packet_length);
304
          break;
305 434 jeremybenn
        case ETH_RTX_TAP:
306 437 julius
#if ETH_DEBUG
307 434 jeremybenn
          printf ("Writing TAP\n");
308 436 julius
 
309
          printf("packet %d bytes:",(int) eth->tx.packet_length );
310
          int j; for (j=0;j<eth->tx.packet_length;j++)
311
                   { if (j%16==0)printf("\n");
312
                     else if (j%8==0) printf(" ");
313
                     printf("%.2x ", eth->tx_buff[j]);
314
                   }
315
          printf("\nend packet:\n");
316 437 julius
#endif    
317 434 jeremybenn
          nwritten = write (eth->rtx_fd, eth->tx_buff, eth->tx.packet_length);
318
          break;
319 19 jeremybenn
        }
320
 
321
      /* set BD status */
322
      if (nwritten == eth->tx.packet_length)
323
        {
324
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
325
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
326
 
327
          eth->tx.state = ETH_TXSTATE_WAIT4BD;
328
        }
329
      else
330
        {
331
          /* XXX - implement retry mechanism here! */
332
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
333
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION);
334
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
335
 
336
          eth->tx.state = ETH_TXSTATE_WAIT4BD;
337 437 julius
 
338 19 jeremybenn
        }
339
 
340
      eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd;
341
 
342 437 julius
      SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
343
 
344 19 jeremybenn
      /* generate OK interrupt */
345
      if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, TXE_M) ||
346
          TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, TXB_M))
347
        {
348 437 julius
          if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, IRQ) && !eth->int_line_stat)
349 434 jeremybenn
            {
350 437 julius
#if ETH_DEBUG
351
              printf ("ETH_TXSTATE_TRANSMIT interrupt\n");
352
#endif
353 434 jeremybenn
              report_interrupt (eth->mac_int);
354 437 julius
              eth->int_line_stat = 1;
355 434 jeremybenn
            }
356 19 jeremybenn
        }
357
 
358
      /* advance to next BD */
359
      if (bAdvance)
360
        {
361
          if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, WRAP) ||
362
              eth->tx.bd_index >= ETH_BD_COUNT)
363
            eth->tx.bd_index = 0;
364
          else
365
            eth->tx.bd_index += 2;
366
        }
367
 
368
      break;
369
    }
370
 
371
  /* Reschedule */
372 442 julius
  SCHED_ADD (eth_controller_tx_clock, dat, 1);
373 19 jeremybenn
}
374
 
375
/* ========================================================================= */
376
 
377
 
378
/* ========================================================================= */
379
/*  RX LOGIC                                                                 */
380
/*---------------------------------------------------------------------------*/
381
 
382
/*
383
 * RX clock
384
 * Responsible for starting and finishing RX
385
 */
386
static void
387
eth_controller_rx_clock (void *dat)
388
{
389
  struct eth_device *eth = dat;
390 434 jeremybenn
  long               nread = 0;
391
  unsigned long      send_word;
392
  struct pollfd      fds[1];
393
  int                n;
394 19 jeremybenn
 
395
 
396
  switch (eth->rx.state)
397
    {
398
    case ETH_RXSTATE_IDLE:
399
      eth->rx.state = ETH_RXSTATE_WAIT4BD;
400
      break;
401
 
402
    case ETH_RXSTATE_WAIT4BD:
403 434 jeremybenn
 
404
      eth->rx.bd      = eth->regs.bd_ram[eth->rx.bd_index];
405 19 jeremybenn
      eth->rx.bd_addr = eth->regs.bd_ram[eth->rx.bd_index + 1];
406
 
407
      if (TEST_FLAG (eth->rx.bd, ETH_RX_BD, READY))
408
        {
409
            /*****************/
410
          /* Initialize RX */
411
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, MISS);
412
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, INVALID);
413
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, DRIBBLE);
414
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, UVERRUN);
415
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, COLLISION);
416
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
417
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
418
 
419
          /* Setup file to read from */
420
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, LOOPBCK))
421
            {
422
              eth->rx.fd = eth->txfd;
423
              eth->rx.offset = &(eth->loopback_offset);
424
            }
425
          else
426
            {
427
              eth->rx.fd = eth->rxfd;
428
              eth->rx.offset = 0;
429
            }
430
          eth->rx.state = ETH_RXSTATE_RECV;
431 437 julius
 
432 19 jeremybenn
        }
433
      else if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
434
        {
435
          eth->rx.state = ETH_RXSTATE_IDLE;
436
        }
437
      else
438
        {
439 434 jeremybenn
          /* Poll to see if there is data to read */
440
          struct pollfd  fds[1];
441
          int    n;
442
 
443
          fds[0].fd = eth->rtx_fd;
444
          fds[0].events = POLLIN;
445
 
446
          n = poll (fds, 1, 0);
447
          if (n < 0)
448 19 jeremybenn
            {
449 434 jeremybenn
              fprintf (stderr, "Warning: Poll of WAIT4BD failed %s: ignored.\n",
450
                       strerror (errno));
451 19 jeremybenn
            }
452 434 jeremybenn
          else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
453
            {
454 436 julius
              printf ("Reading TAP and all BDs full = BUSY\n");
455 434 jeremybenn
              nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
456
 
457
              if (nread < 0)
458
                {
459
                  fprintf (stderr,
460
                           "Warning: Read of WAIT4BD failed %s: ignored\n",
461
                           strerror (errno));
462
                }
463
              else if (nread > 0)
464
                {
465
                  SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
466
 
467 437 julius
                  if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, BUSY_M) &&
468
                      !eth->int_line_stat)
469 434 jeremybenn
                    {
470 436 julius
                      printf ("ETH_RXSTATE_WAIT4BD BUSY interrupt\n");
471 434 jeremybenn
                      report_interrupt (eth->mac_int);
472 437 julius
                      eth->int_line_stat = 1;
473 434 jeremybenn
                    }
474
                }
475
            }
476 19 jeremybenn
        }
477 434 jeremybenn
 
478 19 jeremybenn
      break;
479
 
480
    case ETH_RXSTATE_RECV:
481 434 jeremybenn
 
482 19 jeremybenn
      switch (eth->rtx_type)
483
        {
484
        case ETH_RTX_FILE:
485
          /* Read packet length */
486
          if (eth_read_rx_file
487
              (eth, &(eth->rx.packet_length),
488
               sizeof (eth->rx.packet_length)) <
489
              sizeof (eth->rx.packet_length))
490
            {
491 434 jeremybenn
              /* TODO: just do what real ethernet would do (some kind of error
492
                 state) */
493 19 jeremybenn
              sim_done ();
494
              break;
495
            }
496
 
497
          /* Packet must be big enough to hold a header */
498
          if (eth->rx.packet_length < ETHER_HDR_LEN)
499
            {
500
              eth_rx_next_packet (eth);
501
 
502
              eth->rx.state = ETH_RXSTATE_WAIT4BD;
503
              break;
504
            }
505
 
506
          eth->rx.bytes_read = 0;
507
          eth->rx.bytes_left = eth->rx.packet_length;
508
 
509
          /* for now Read entire packet into memory */
510
          nread = eth_read_rx_file (eth, eth->rx_buff, eth->rx.bytes_left);
511
          if (nread < eth->rx.bytes_left)
512
            {
513
              eth->rx.error = 1;
514
              break;
515
            }
516
 
517
          eth->rx.packet_length = nread;
518
          eth->rx.bytes_left = nread;
519
          eth->rx.bytes_read = 0;
520
 
521
          eth->rx.state = ETH_RXSTATE_WRITEFIFO;
522
 
523
          break;
524
 
525 434 jeremybenn
        case ETH_RTX_TAP:
526
          /* Poll to see if there is data to read */
527
          fds[0].fd     = eth->rtx_fd;
528
          fds[0].events = POLLIN;
529
 
530
          n = poll (fds, 1, 0);
531
          if (n < 0)
532 19 jeremybenn
            {
533 434 jeremybenn
              fprintf (stderr,
534
                       "Warning: Poll of RXTATE_RECV failed %s: ignored.\n",
535
                       strerror (errno));
536 19 jeremybenn
            }
537 434 jeremybenn
          else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
538 19 jeremybenn
            {
539 437 julius
#if ETH_DEBUG
540
              printf ("Reading TAP. ");
541
#endif
542 434 jeremybenn
              nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
543 437 julius
#if ETH_DEBUG
544
              printf ("%d bytes read.\n",(int) nread);
545
#endif
546 434 jeremybenn
              if (nread < 0)
547 19 jeremybenn
                {
548 434 jeremybenn
                  fprintf (stderr,
549
                           "Warning: Read of RXTATE_RECV failed %s: ignored\n",
550 436 julius
                           strerror (errno));
551 434 jeremybenn
 
552 437 julius
                  SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXE);
553
 
554
                  if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXE_M) &&
555
                      !eth->int_line_stat)
556
                    {
557 436 julius
                      printf ("ETH_RXTATE_RECV RXE interrupt\n");
558 434 jeremybenn
                      report_interrupt (eth->mac_int);
559 437 julius
                      eth->int_line_stat = 1;
560 434 jeremybenn
                    }
561
                }
562 436 julius
 
563 19 jeremybenn
            }
564 434 jeremybenn
 
565 19 jeremybenn
          /* If not promiscouos mode, check the destination address */
566 436 julius
          if (!TEST_FLAG (eth->regs.moder, ETH_MODER, PRO) && nread)
567 19 jeremybenn
            {
568
              if (TEST_FLAG (eth->regs.moder, ETH_MODER, IAM)
569
                  && (eth->rx_buff[0] & 1))
570
                {
571
                  /* Nothing for now */
572
                }
573
 
574 436 julius
 
575
              if (((eth->mac_address[5] != eth->rx_buff[0]) &&
576
                   (eth->rx_buff[5] != 0xff) ) ||
577
                  ((eth->mac_address[4] != eth->rx_buff[1]) &&
578
                   (eth->rx_buff[4] != 0xff) ) ||
579
                  ((eth->mac_address[3] != eth->rx_buff[2]) &&
580
                   (eth->rx_buff[3] != 0xff) ) ||
581
                  ((eth->mac_address[2] != eth->rx_buff[3]) &&
582
                   (eth->rx_buff[2] != 0xff) ) ||
583
                  ((eth->mac_address[1] != eth->rx_buff[4]) &&
584
                   (eth->rx_buff[1] != 0xff) ) ||
585
                  ((eth->mac_address[0] != eth->rx_buff[5]) &&
586
                   (eth->rx_buff[0] != 0xff)))
587
 
588
              {
589 437 julius
#if ETH_DEBUG           
590 436 julius
                  printf("ETH_RXSTATE dropping packet for %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
591
                       eth->rx_buff[0],
592
                       eth->rx_buff[1],
593
                       eth->rx_buff[2],
594
                       eth->rx_buff[3],
595
                       eth->rx_buff[4],
596
                       eth->rx_buff[5]);
597 437 julius
#endif
598 19 jeremybenn
                break;
599 436 julius
              }
600 19 jeremybenn
            }
601
 
602
          eth->rx.packet_length = nread;
603
          eth->rx.bytes_left = nread;
604
          eth->rx.bytes_read = 0;
605
 
606 436 julius
          if (nread)
607
            eth->rx.state = ETH_RXSTATE_WRITEFIFO;
608 19 jeremybenn
 
609
          break;
610
        case ETH_RTX_VAPI:
611
          break;
612
        }
613
      break;
614
 
615
    case ETH_RXSTATE_WRITEFIFO:
616 437 julius
#if ETH_DEBUG
617
      printf("ETH_RXSTATE_WRITEFIFO: writing to RXBD%d: %d bytes @ 0x%.8x\n",
618
             (int) eth->rx.bd_index/2,  (int)eth->rx.bytes_left,
619
             (unsigned int)eth->rx.bd_addr);
620
#endif
621 436 julius
      if (eth->rx.bytes_left > 0){
622
        while((int) eth->rx.bytes_left){
623
          send_word = ((unsigned long) eth->rx_buff[eth->rx.bytes_read] << 24) |
624
            ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 1] << 16) |
625
            ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 2] << 8) |
626
            ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 3]);
627
          set_direct32 (eth->rx.bd_addr + eth->rx.bytes_read, send_word, 0, 0);
628
          /* update counters */
629
          if (eth->rx.bytes_left >= 4)
630
            {
631
              eth->rx.bytes_left -= 4;
632
              eth->rx.bytes_read += 4;
633
            }
634
          else
635
            {
636
              eth->rx.bytes_read += eth->rx.bytes_left;
637
              eth->rx.bytes_left = 0;
638
            }
639
        }
640
 
641
      }
642 437 julius
#if ETH_DEBUG
643
      printf("ETH_RXSTATE_WRITEFIFO: bytes read: 0x%.8x\n",
644
             (unsigned int)eth->rx.bytes_read);
645
#endif
646 19 jeremybenn
      if (eth->rx.bytes_left <= 0)
647
        {
648
          /* Write result to bd */
649 437 julius
          SET_FIELD (eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length + 4);
650 19 jeremybenn
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, READY);
651
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
652 436 julius
          /*
653 19 jeremybenn
          if (eth->rx.packet_length <
654
              (GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL) - 4))
655
            SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
656
          if (eth->rx.packet_length >
657
              GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MAXFL))
658
            SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
659 436 julius
          */
660 19 jeremybenn
          eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
661
 
662
          /* advance to next BD */
663
          if (TEST_FLAG (eth->rx.bd, ETH_RX_BD, WRAP)
664
              || eth->rx.bd_index >= ETH_BD_COUNT)
665
            eth->rx.bd_index = eth->regs.tx_bd_num << 1;
666
          else
667
            eth->rx.bd_index += 2;
668
 
669 437 julius
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
670
 
671 19 jeremybenn
          if ((TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXB_M)) &&
672 437 julius
              (TEST_FLAG (eth->rx.bd, ETH_RX_BD, IRQ)) &&
673
              !eth->int_line_stat)
674 19 jeremybenn
            {
675 437 julius
#if ETH_DEBUG
676
              printf ("ETH_RXSTATE_WRITEFIFO interrupt\n");
677
#endif
678 19 jeremybenn
              report_interrupt (eth->mac_int);
679 437 julius
              eth->int_line_stat = 1;
680 19 jeremybenn
            }
681
 
682
          /* ready to receive next packet */
683
          eth->rx.state = ETH_RXSTATE_IDLE;
684
        }
685
      break;
686
    }
687
 
688
  /* Reschedule */
689 442 julius
  SCHED_ADD (eth_controller_rx_clock, dat, 1);
690 19 jeremybenn
}
691
 
692
/* ========================================================================= */
693
/* Move to next RX BD */
694
static void
695
eth_rx_next_packet (struct eth_device *eth)
696
{
697
  /* Skip any possible leftovers */
698
  if (eth->rx.bytes_left)
699
    eth_skip_rx_file (eth, eth->rx.bytes_left);
700
}
701
 
702
/* "Skip" bytes in RX file */
703
static void
704
eth_skip_rx_file (struct eth_device *eth, off_t count)
705
{
706
  eth->rx.offset += count;
707
}
708
 
709
/*
710
 * Utility function to read from the ethernet RX file
711
 * This function moves the file pointer to the current place in the packet before reading
712
 */
713
static ssize_t
714
eth_read_rx_file (struct eth_device *eth, void *buf, size_t count)
715
{
716
  ssize_t result;
717
 
718
  if (eth->rx.fd <= 0)
719
    {
720
      return 0;
721
    }
722
 
723
  if (eth->rx.offset)
724
    if (lseek (eth->rx.fd, *(eth->rx.offset), SEEK_SET) == (off_t) - 1)
725
      {
726
        return 0;
727
      }
728
 
729
  result = read (eth->rx.fd, buf, count);
730
  if (eth->rx.offset && result >= 0)
731
    *(eth->rx.offset) += result;
732
 
733
  return result;
734
}
735
 
736
/* ========================================================================= */
737
 
738 434 jeremybenn
 
739
/* -------------------------------------------------------------------------- */
740
/*!Reset the Ethernet.
741
 
742
   Open the correct type of simulation interface to the outside world.
743
 
744
   Initialize all registers to default and places devices in memory address
745
   space.
746
 
747
   @param[in] dat  The Ethernet interface data structure.                     */
748
/* -------------------------------------------------------------------------- */
749 19 jeremybenn
static void
750
eth_reset (void *dat)
751
{
752
  struct eth_device *eth = dat;
753 434 jeremybenn
  struct ifreq       ifr;
754 19 jeremybenn
 
755 437 julius
#if ETH_DEBUG
756 434 jeremybenn
  printf ("Resetting Ethernet\n");
757 437 julius
#endif
758 434 jeremybenn
  /* Nothing to do if we do not have a base address set.
759
 
760
     TODO: Surely this should test for being enabled? */
761
  if (0 == eth->baseaddr)
762 19 jeremybenn
    {
763 434 jeremybenn
      return;
764
    }
765
 
766
  switch (eth->rtx_type)
767
    {
768
    case ETH_RTX_FILE:
769
 
770
      /* (Re-)open TX/RX files */
771
      if (eth->rxfd >= 0)
772 19 jeremybenn
        {
773 434 jeremybenn
          close (eth->rxfd);
774
        }
775 19 jeremybenn
 
776 434 jeremybenn
      if (eth->txfd >= 0)
777
        {
778
          close (eth->txfd);
779
        }
780 19 jeremybenn
 
781 434 jeremybenn
      eth->rxfd = -1;
782
      eth->txfd = -1;
783 19 jeremybenn
 
784 434 jeremybenn
      eth->rxfd = open (eth->rxfile, O_RDONLY);
785
      if (eth->rxfd < 0)
786
        {
787
          fprintf (stderr, "Warning: Cannot open Ethernet RX file \"%s\": %s\n",
788
                   eth->rxfile, strerror (errno));
789
        }
790 19 jeremybenn
 
791 434 jeremybenn
      eth->txfd = open (eth->txfile,
792
#if defined(O_SYNC)             /* BSD/MacOS X doesn't know about O_SYNC */
793
                        O_SYNC |
794
#endif
795
                        O_RDWR | O_CREAT | O_APPEND,
796
                        S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
797
      if (eth->txfd < 0)
798
        {
799
          fprintf (stderr, "Warning: Cannot open Ethernet TX file \"%s\": %s\n",
800
                   eth->txfile, strerror (errno));
801
        }
802 19 jeremybenn
 
803 434 jeremybenn
      eth->loopback_offset = lseek (eth->txfd, 0, SEEK_END);
804
      break;
805 19 jeremybenn
 
806 434 jeremybenn
    case ETH_RTX_TAP:
807 19 jeremybenn
 
808 434 jeremybenn
      /* (Re-)open TAP interface if necessary */
809
      if (eth->rtx_fd != 0)
810
        {
811 19 jeremybenn
          break;
812
        }
813
 
814 434 jeremybenn
      /* Open the TUN/TAP device */
815
      eth->rtx_fd = open ("/dev/net/tun", O_RDWR);
816
      if( eth->rtx_fd < 0 )
817
        {
818
          fprintf (stderr, "Warning: Failed to open TUN/TAP device: %s\n",
819
                   strerror (errno));
820
          eth->rtx_fd = 0;
821
          return;
822
        }
823 19 jeremybenn
 
824 434 jeremybenn
      /* Turn it into a specific TAP device. If we haven't specified a
825
         specific (persistent) device, one will be created, but that requires
826
         superuser, or at least CAP_NET_ADMIN capabilities. */
827
      memset (&ifr, 0, sizeof(ifr));
828 436 julius
      ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
829 434 jeremybenn
      strncpy (ifr.ifr_name, eth->tap_dev, IFNAMSIZ);
830 19 jeremybenn
 
831 434 jeremybenn
      if (ioctl (eth->rtx_fd, TUNSETIFF, (void *) &ifr) < 0)
832 19 jeremybenn
        {
833 434 jeremybenn
          fprintf (stderr, "Warning: Failed to set TAP device: %s\n",
834
                   strerror (errno));
835
          close (eth->rtx_fd);
836
          eth->rtx_fd = 0;
837
          return;
838 19 jeremybenn
        }
839 437 julius
#if ETH_DEBUG
840 434 jeremybenn
      PRINTF ("Opened TAP %s\n", ifr.ifr_name);
841 437 julius
#endif
842 434 jeremybenn
      /* Do we need to flush any packets? */
843
      break;
844 19 jeremybenn
    }
845
 
846 434 jeremybenn
  /* Set registers to default values */
847
  memset (&(eth->regs), 0, sizeof (eth->regs));
848 19 jeremybenn
 
849 434 jeremybenn
  eth->regs.moder     = 0x0000A000;
850
  eth->regs.ipgt      = 0x00000012;
851
  eth->regs.ipgr1     = 0x0000000C;
852
  eth->regs.ipgr2     = 0x00000012;
853
  eth->regs.packetlen = 0x003C0600;
854
  eth->regs.collconf  = 0x000F003F;
855
  eth->regs.miimoder  = 0x00000064;
856
  eth->regs.tx_bd_num = 0x00000040;
857 19 jeremybenn
 
858 434 jeremybenn
  /* Clear TX/RX status and initialize buffer descriptor index. */
859
  memset (&(eth->tx), 0, sizeof (eth->tx));
860
  memset (&(eth->rx), 0, sizeof (eth->rx));
861
 
862 436 julius
  /* Reset TX/RX BD indexes */
863
  eth->tx.bd_index = 0;
864 434 jeremybenn
  eth->rx.bd_index = eth->regs.tx_bd_num << 1;
865
 
866 437 julius
  /* Reset IRQ line status */
867
  eth->int_line_stat = 0;
868
 
869 434 jeremybenn
  /* Initialize VAPI */
870
  if (eth->base_vapi_id)
871
    {
872
      vapi_install_multi_handler (eth->base_vapi_id, ETH_NUM_VAPI_IDS,
873
                                  eth_vapi_read, dat);
874
    }
875
}       /* eth_reset () */
876
 
877
 
878 19 jeremybenn
/*
879
  Print register values on stdout
880
*/
881
static void
882
eth_status (void *dat)
883
{
884
  struct eth_device *eth = dat;
885
 
886
  PRINTF ("\nEthernet MAC at 0x%" PRIxADDR ":\n", eth->baseaddr);
887
  PRINTF ("MODER        : 0x%08lX\n", eth->regs.moder);
888
  PRINTF ("INT_SOURCE   : 0x%08lX\n", eth->regs.int_source);
889
  PRINTF ("INT_MASK     : 0x%08lX\n", eth->regs.int_mask);
890
  PRINTF ("IPGT         : 0x%08lX\n", eth->regs.ipgt);
891
  PRINTF ("IPGR1        : 0x%08lX\n", eth->regs.ipgr1);
892
  PRINTF ("IPGR2        : 0x%08lX\n", eth->regs.ipgr2);
893
  PRINTF ("PACKETLEN    : 0x%08lX\n", eth->regs.packetlen);
894
  PRINTF ("COLLCONF     : 0x%08lX\n", eth->regs.collconf);
895
  PRINTF ("TX_BD_NUM    : 0x%08lX\n", eth->regs.tx_bd_num);
896
  PRINTF ("CTRLMODER    : 0x%08lX\n", eth->regs.controlmoder);
897
  PRINTF ("MIIMODER     : 0x%08lX\n", eth->regs.miimoder);
898
  PRINTF ("MIICOMMAND   : 0x%08lX\n", eth->regs.miicommand);
899
  PRINTF ("MIIADDRESS   : 0x%08lX\n", eth->regs.miiaddress);
900
  PRINTF ("MIITX_DATA   : 0x%08lX\n", eth->regs.miitx_data);
901
  PRINTF ("MIIRX_DATA   : 0x%08lX\n", eth->regs.miirx_data);
902
  PRINTF ("MIISTATUS    : 0x%08lX\n", eth->regs.miistatus);
903
  PRINTF ("MAC Address  : %02X:%02X:%02X:%02X:%02X:%02X\n",
904
          eth->mac_address[0], eth->mac_address[1], eth->mac_address[2],
905
          eth->mac_address[3], eth->mac_address[4], eth->mac_address[5]);
906
  PRINTF ("HASH0        : 0x%08lX\n", eth->regs.hash0);
907
  PRINTF ("HASH1        : 0x%08lX\n", eth->regs.hash1);
908
}
909
 
910
/* ========================================================================= */
911
 
912
 
913
/*
914
  Read a register
915
*/
916
static uint32_t
917
eth_read32 (oraddr_t addr, void *dat)
918
{
919
  struct eth_device *eth = dat;
920
 
921
  switch (addr)
922
    {
923
    case ETH_MODER:
924
      return eth->regs.moder;
925
    case ETH_INT_SOURCE:
926
      return eth->regs.int_source;
927
    case ETH_INT_MASK:
928
      return eth->regs.int_mask;
929
    case ETH_IPGT:
930
      return eth->regs.ipgt;
931
    case ETH_IPGR1:
932
      return eth->regs.ipgr1;
933
    case ETH_IPGR2:
934
      return eth->regs.ipgr2;
935
    case ETH_PACKETLEN:
936
      return eth->regs.packetlen;
937
    case ETH_COLLCONF:
938
      return eth->regs.collconf;
939
    case ETH_TX_BD_NUM:
940
      return eth->regs.tx_bd_num;
941
    case ETH_CTRLMODER:
942
      return eth->regs.controlmoder;
943
    case ETH_MIIMODER:
944
      return eth->regs.miimoder;
945
    case ETH_MIICOMMAND:
946
      return eth->regs.miicommand;
947
    case ETH_MIIADDRESS:
948
      return eth->regs.miiaddress;
949
    case ETH_MIITX_DATA:
950
      return eth->regs.miitx_data;
951
    case ETH_MIIRX_DATA:
952 428 julius
      /*printf("or1ksim: read MIIM RX: 0x%x\n",(int)eth->regs.miirx_data);*/
953 19 jeremybenn
      return eth->regs.miirx_data;
954
    case ETH_MIISTATUS:
955
      return eth->regs.miistatus;
956
    case ETH_MAC_ADDR0:
957
      return (((unsigned long) eth->mac_address[3]) << 24) |
958
        (((unsigned long) eth->mac_address[2]) << 16) |
959
        (((unsigned long) eth->mac_address[1]) << 8) |
960
        (unsigned long) eth->mac_address[0];
961
    case ETH_MAC_ADDR1:
962
      return (((unsigned long) eth->mac_address[5]) << 8) |
963
        (unsigned long) eth->mac_address[4];
964
    case ETH_HASH0:
965
      return eth->regs.hash0;
966
    case ETH_HASH1:
967
      return eth->regs.hash1;
968
      /*case ETH_DMA_RX_TX: return eth_rx( eth ); */
969
    }
970
 
971
  if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
972
    return eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4];
973
 
974
  PRINTF ("eth_read32( 0x%" PRIxADDR " ): Illegal address\n",
975
          addr + eth->baseaddr);
976
  return 0;
977
}
978
 
979
/* ========================================================================= */
980
 
981
 
982
/*
983
  Write a register
984
*/
985
static void
986
eth_write32 (oraddr_t addr, uint32_t value, void *dat)
987
{
988
  struct eth_device *eth = dat;
989
 
990
  switch (addr)
991
    {
992
    case ETH_MODER:
993 437 julius
#if ETH_DEBUG
994
      printf("eth_write32: MODER 0x%x\n",value);
995
#endif
996 19 jeremybenn
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN) &&
997
          TEST_FLAG (value, ETH_MODER, RXEN))
998 436 julius
        {
999
          // Reset RX BD index
1000
          eth->rx.bd_index = eth->regs.tx_bd_num << 1;
1001 437 julius
 
1002
          // Clear TAP
1003
          {
1004
            /* Poll to see if there is data to read */
1005
            struct pollfd  fds[1];
1006
            int    n;
1007
            int nread;
1008
 
1009
            fds[0].fd = eth->rtx_fd;
1010
            fds[0].events = POLLIN;
1011
 
1012
            do {
1013
              n = poll (fds, 1, 0);
1014
              if (n < 0)
1015
                {
1016
                  fprintf (stderr, "Warning: Poll in while emptying TAP: %s: ignored.\n",
1017
                           strerror (errno));
1018
                }
1019
              else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
1020
                {
1021
                  nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
1022
 
1023
                  if (nread < 0)
1024
                    {
1025
                      fprintf (stderr,
1026
                               "Warning: Read failed %s: ignored\n",
1027
                               strerror (errno));
1028
                    }
1029
                }
1030
            } while (n > 0);
1031
          }
1032
 
1033 436 julius
          SCHED_ADD (eth_controller_rx_clock, dat, 1);
1034
        }
1035 437 julius
      else if (!TEST_FLAG (value, ETH_MODER, RXEN) &&
1036
               TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
1037 19 jeremybenn
        SCHED_FIND_REMOVE (eth_controller_rx_clock, dat);
1038
 
1039
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN) &&
1040
          TEST_FLAG (value, ETH_MODER, TXEN))
1041 436 julius
        {
1042
          eth->tx.bd_index = 0;
1043
          SCHED_ADD (eth_controller_tx_clock, dat, 1);
1044
        }
1045 437 julius
      else if (!TEST_FLAG (value, ETH_MODER, TXEN) &&
1046
               TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN))
1047 19 jeremybenn
        SCHED_FIND_REMOVE (eth_controller_tx_clock, dat);
1048
 
1049
      eth->regs.moder = value;
1050
 
1051
      if (TEST_FLAG (value, ETH_MODER, RST))
1052
        eth_reset (dat);
1053
      return;
1054
    case ETH_INT_SOURCE:
1055 437 julius
#if ETH_DEBUG
1056
      printf("eth_write32: INT_SOURCE 0x%x\n",value);
1057
#endif
1058
      eth->regs.int_source &= ~value;
1059 436 julius
 
1060 437 julius
      // Clear IRQ line if all interrupt sources have been dealt with
1061
      if (!(eth->regs.int_source & eth->regs.int_mask) && eth->int_line_stat)
1062
        {
1063
          clear_interrupt (eth->mac_int);
1064
          eth->int_line_stat = 0;
1065
        }
1066
 
1067 19 jeremybenn
      return;
1068
    case ETH_INT_MASK:
1069 437 julius
#if ETH_DEBUG
1070
      printf("eth_write32: INT_MASK 0x%x\n",value);
1071
#endif
1072 19 jeremybenn
      eth->regs.int_mask = value;
1073 437 julius
      if ((eth->regs.int_source & eth->regs.int_mask) && !eth->int_line_stat)
1074 436 julius
        report_interrupt (eth->mac_int);
1075
      else
1076 437 julius
        if (eth->int_line_stat)
1077
          {
1078
            clear_interrupt (eth->mac_int);
1079
            eth->int_line_stat = 0;
1080
          }
1081 19 jeremybenn
      return;
1082
    case ETH_IPGT:
1083
      eth->regs.ipgt = value;
1084
      return;
1085
    case ETH_IPGR1:
1086
      eth->regs.ipgr1 = value;
1087
      return;
1088
    case ETH_IPGR2:
1089
      eth->regs.ipgr2 = value;
1090
      return;
1091
    case ETH_PACKETLEN:
1092
      eth->regs.packetlen = value;
1093
      return;
1094
    case ETH_COLLCONF:
1095
      eth->regs.collconf = value;
1096
      return;
1097
    case ETH_TX_BD_NUM:
1098
      eth_write_tx_bd_num (eth, value);
1099
      return;
1100
    case ETH_CTRLMODER:
1101
      eth->regs.controlmoder = value;
1102
      return;
1103
    case ETH_MIIMODER:
1104
      eth->regs.miimoder = value;
1105
      return;
1106
    case ETH_MIICOMMAND:
1107
      eth->regs.miicommand = value;
1108 428 julius
      /* Perform MIIM transaction, if required */
1109
      eth_miim_trans(dat);
1110 19 jeremybenn
      return;
1111
    case ETH_MIIADDRESS:
1112
      eth->regs.miiaddress = value;
1113
      return;
1114
    case ETH_MIITX_DATA:
1115
      eth->regs.miitx_data = value;
1116
      return;
1117
    case ETH_MIIRX_DATA:
1118 428 julius
      /* Register is R/O
1119 19 jeremybenn
      eth->regs.miirx_data = value;
1120 428 julius
      */
1121 19 jeremybenn
      return;
1122
    case ETH_MIISTATUS:
1123 428 julius
      /* Register is R/O
1124 19 jeremybenn
      eth->regs.miistatus = value;
1125 428 julius
      */
1126 19 jeremybenn
      return;
1127 428 julius
 
1128 19 jeremybenn
    case ETH_MAC_ADDR0:
1129
      eth->mac_address[0] = value & 0xFF;
1130
      eth->mac_address[1] = (value >> 8) & 0xFF;
1131
      eth->mac_address[2] = (value >> 16) & 0xFF;
1132
      eth->mac_address[3] = (value >> 24) & 0xFF;
1133
      return;
1134
    case ETH_MAC_ADDR1:
1135
      eth->mac_address[4] = value & 0xFF;
1136
      eth->mac_address[5] = (value >> 8) & 0xFF;
1137
      return;
1138
    case ETH_HASH0:
1139
      eth->regs.hash0 = value;
1140
      return;
1141
    case ETH_HASH1:
1142
      eth->regs.hash1 = value;
1143
      return;
1144
 
1145
      /*case ETH_DMA_RX_TX: eth_tx( eth, value ); return; */
1146
    }
1147
 
1148
  if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
1149
    {
1150
      eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value;
1151
      return;
1152
    }
1153
 
1154
  PRINTF ("eth_write32( 0x%" PRIxADDR " ): Illegal address\n",
1155
          addr + eth->baseaddr);
1156
  return;
1157
}
1158
 
1159
/* ========================================================================= */
1160
 
1161
 
1162
/*
1163
 *   VAPI connection to outside
1164
 */
1165
static void
1166
eth_vapi_read (unsigned long id, unsigned long data, void *dat)
1167
{
1168
  unsigned long which;
1169
  struct eth_device *eth = dat;
1170
 
1171
  which = id - eth->base_vapi_id;
1172
 
1173
  if (!eth)
1174
    {
1175
      return;
1176
    }
1177
 
1178
  switch (which)
1179
    {
1180
    case ETH_VAPI_DATA:
1181
      break;
1182
    case ETH_VAPI_CTRL:
1183
      break;
1184
    }
1185
}
1186
 
1187
/* ========================================================================= */
1188
 
1189
 
1190
/* When TX_BD_NUM is written, also reset current RX BD index */
1191
static void
1192
eth_write_tx_bd_num (struct eth_device *eth, unsigned long value)
1193
{
1194
  eth->regs.tx_bd_num = value & 0xFF;
1195
  eth->rx.bd_index = eth->regs.tx_bd_num << 1;
1196
}
1197
 
1198
/* ========================================================================= */
1199
 
1200
/*-----------------------------------------------[ Ethernet configuration ]---*/
1201
 
1202
 
1203
/*---------------------------------------------------------------------------*/
1204
/*!Enable or disable the Ethernet interface
1205
 
1206
   @param[in] val  The value to use
1207
   @param[in] dat  The config data structure                                 */
1208
/*---------------------------------------------------------------------------*/
1209
static void
1210
eth_enabled (union param_val  val,
1211
             void            *dat)
1212
{
1213
  struct eth_device *eth = dat;
1214
 
1215
  eth->enabled = val.int_val;
1216
 
1217
}       /* eth_enabled() */
1218
 
1219
 
1220
/*---------------------------------------------------------------------------*/
1221
/*!Set the Ethernet interface base address
1222
 
1223
   @param[in] val  The value to use
1224
   @param[in] dat  The config data structure                                 */
1225
/*---------------------------------------------------------------------------*/
1226
static void
1227
eth_baseaddr (union param_val  val,
1228
              void            *dat)
1229
{
1230
  struct eth_device *eth = dat;
1231
 
1232
  eth->baseaddr = val.addr_val;
1233
 
1234
}       /* eth_baseaddr() */
1235
 
1236
 
1237
/*---------------------------------------------------------------------------*/
1238
/*!Set the Ethernet DMA port
1239
 
1240
   This is not currently supported, so a warning message is printed.
1241
 
1242
   @param[in] val  The value to use
1243
   @param[in] dat  The config data structure                                 */
1244
/*---------------------------------------------------------------------------*/
1245
static void
1246
eth_dma (union param_val  val,
1247
         void            *dat)
1248
{
1249
  struct eth_device *eth = dat;
1250
 
1251
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported\n");
1252
  eth->dma = val.addr_val;
1253
 
1254
}       /* eth_dma() */
1255
 
1256
 
1257
/*---------------------------------------------------------------------------*/
1258
/*!Set the Ethernet IRQ
1259
 
1260
   @param[in] val  The value to use
1261
   @param[in] dat  The config data structure                                 */
1262
/*---------------------------------------------------------------------------*/
1263
static void
1264
eth_irq (union param_val  val,
1265
         void            *dat)
1266
{
1267
  struct eth_device *eth = dat;
1268
 
1269
  eth->mac_int = val.int_val;
1270
 
1271
}       /* eth_irq() */
1272
 
1273
 
1274
/*---------------------------------------------------------------------------*/
1275
/*!Set the Ethernet interface type
1276
 
1277 434 jeremybenn
   Currently two types are supported, file and tap.
1278 19 jeremybenn
 
1279 434 jeremybenn
   @param[in] val  The value to use. Currently "file" and "tap" are supported.
1280 19 jeremybenn
   @param[in] dat  The config data structure                                 */
1281
/*---------------------------------------------------------------------------*/
1282
static void
1283
eth_rtx_type (union param_val  val,
1284
              void            *dat)
1285
{
1286
  struct eth_device *eth = dat;
1287
 
1288 434 jeremybenn
  if (0 == strcasecmp ("file", val.str_val))
1289 19 jeremybenn
    {
1290 434 jeremybenn
      printf ("Ethernet FILE type\n");
1291
      eth->rtx_type = ETH_RTX_FILE;
1292 19 jeremybenn
    }
1293 434 jeremybenn
  else if (0 == strcasecmp ("tap", val.str_val))
1294
    {
1295
      printf ("Ethernet TAP type\n");
1296
      eth->rtx_type = ETH_RTX_TAP;
1297
    }
1298
  else
1299
    {
1300
      fprintf (stderr, "Warning: Unknown Ethernet type: file assumed.\n");
1301
      eth->rtx_type = ETH_RTX_FILE;
1302
    }
1303 19 jeremybenn
}       /* eth_rtx_type() */
1304
 
1305
 
1306
/*---------------------------------------------------------------------------*/
1307
/*!Set the Ethernet DMA Rx channel
1308
 
1309
   External DMA is not currently supported, so a warning message is printed.
1310
 
1311
   @param[in] val  The value to use
1312
   @param[in] dat  The config data structure                                 */
1313
/*---------------------------------------------------------------------------*/
1314
static void
1315
eth_rx_channel (union param_val  val,
1316
                void            *dat)
1317
{
1318
  struct eth_device *eth = dat;
1319
 
1320
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1321
           "Rx channel ignored\n");
1322
  eth->rx_channel = val.int_val;
1323
 
1324
}       /* eth_rx_channel() */
1325
 
1326
 
1327
/*---------------------------------------------------------------------------*/
1328
/*!Set the Ethernet DMA Tx channel
1329
 
1330
   External DMA is not currently supported, so a warning message is printed.
1331
 
1332
   @param[in] val  The value to use
1333
   @param[in] dat  The config data structure                                 */
1334
/*---------------------------------------------------------------------------*/
1335
static void
1336
eth_tx_channel (union param_val  val,
1337
                void            *dat)
1338
{
1339
  struct eth_device *eth = dat;
1340
 
1341
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1342
           "Tx channel ignored\n");
1343
  eth->tx_channel = val.int_val;
1344
 
1345
}       /* eth_tx_channel() */
1346
 
1347
 
1348
/*---------------------------------------------------------------------------*/
1349
/*!Set the Ethernet DMA Rx file
1350
 
1351
   Free any previously allocated value.
1352
 
1353
   @param[in] val  The value to use
1354
   @param[in] dat  The config data structure                                 */
1355
/*---------------------------------------------------------------------------*/
1356
static void
1357
eth_rxfile (union param_val  val,
1358
            void            *dat)
1359
{
1360
  struct eth_device *eth = dat;
1361
 
1362
  if (NULL != eth->rxfile)
1363
    {
1364
      free (eth->rxfile);
1365
      eth->rxfile = NULL;
1366
    }
1367
 
1368
  if (!(eth->rxfile = strdup (val.str_val)))
1369
    {
1370
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1371
      exit (-1);
1372
    }
1373
}       /* eth_rxfile() */
1374
 
1375
 
1376
/*---------------------------------------------------------------------------*/
1377
/*!Set the Ethernet DMA Tx file
1378
 
1379
   Free any previously allocated value.
1380
 
1381
   @param[in] val  The value to use
1382
   @param[in] dat  The config data structure                                 */
1383
/*---------------------------------------------------------------------------*/
1384
static void
1385
eth_txfile (union param_val  val,
1386
            void            *dat)
1387
{
1388
  struct eth_device *eth = dat;
1389
 
1390
  if (NULL != eth->txfile)
1391
    {
1392
      free (eth->txfile);
1393
      eth->txfile = NULL;
1394
    }
1395
 
1396
  if (!(eth->txfile = strdup (val.str_val)))
1397
    {
1398
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1399
      exit (-1);
1400
    }
1401
}       /* eth_txfile() */
1402
 
1403
 
1404
/*---------------------------------------------------------------------------*/
1405 434 jeremybenn
/*!Set the Ethernet TAP device.
1406 19 jeremybenn
 
1407 434 jeremybenn
   If we are not superuser (or do not have CAP_NET_ADMIN priviledges), then we
1408
   must work with a persistent TAP device that is already set up. This option
1409
   specifies the device to user.
1410 19 jeremybenn
 
1411 434 jeremybenn
   @param[in] val  The value to use.
1412 19 jeremybenn
   @param[in] dat  The config data structure                                 */
1413
/*---------------------------------------------------------------------------*/
1414
static void
1415 434 jeremybenn
eth_tap_dev (union param_val  val,
1416
              void            *dat)
1417 19 jeremybenn
{
1418
  struct eth_device *eth = dat;
1419
 
1420 434 jeremybenn
  if (NULL != eth->tap_dev)
1421 19 jeremybenn
    {
1422 434 jeremybenn
      free (eth->tap_dev);
1423
      eth->tap_dev = NULL;
1424 19 jeremybenn
    }
1425
 
1426 434 jeremybenn
  eth->tap_dev = strdup (val.str_val);
1427
 
1428
  if (NULL == eth->tap_dev)
1429 19 jeremybenn
    {
1430 434 jeremybenn
      fprintf (stderr, "ERROR: Peripheral Ethernet: Run out of memory\n");
1431 19 jeremybenn
      exit (-1);
1432
    }
1433 434 jeremybenn
}       /* eth_tap_dev() */
1434 19 jeremybenn
 
1435
 
1436
static void
1437
eth_vapi_id (union param_val  val,
1438
             void            *dat)
1439
{
1440
  struct eth_device *eth = dat;
1441
  eth->base_vapi_id = val.int_val;
1442
}
1443
 
1444 428 julius
 
1445
static void
1446
eth_phy_addr (union param_val  val,
1447
              void            *dat)
1448
{
1449
  struct eth_device *eth = dat;
1450
  eth->phy_addr = val.int_val & ETH_MIIADDR_FIAD_MASK;
1451
}
1452
 
1453
 
1454 19 jeremybenn
/*---------------------------------------------------------------------------*/
1455 428 julius
/*!Emulate MIIM transaction to ethernet PHY
1456
 
1457
   @param[in] dat  The config data structure                                 */
1458
/*---------------------------------------------------------------------------*/
1459
static void
1460
eth_miim_trans (void *dat)
1461
{
1462
  struct eth_device *eth = dat;
1463
  switch (eth->regs.miicommand)
1464
    {
1465
    case ((1 << ETH_MIICOMM_WCDATA_OFFSET)):
1466
      /* Perhaps something to emulate here later, but for now do nothing */
1467
      break;
1468
 
1469
    case ((1 << ETH_MIICOMM_RSTAT_OFFSET)):
1470 429 julius
      /*
1471 428 julius
      printf("or1ksim: eth_miim_trans: phy %d\n",(int)
1472
             ((eth->regs.miiaddress >> ETH_MIIADDR_FIAD_OFFSET)&
1473
              ETH_MIIADDR_FIAD_MASK));
1474
      printf("or1ksim: eth_miim_trans: reg %d\n",(int)
1475
             ((eth->regs.miiaddress >> ETH_MIIADDR_RGAD_OFFSET)&
1476
              ETH_MIIADDR_RGAD_MASK));
1477 429 julius
      */
1478 428 julius
      /*First check if it's the correct PHY to address */
1479
      if (((eth->regs.miiaddress >> ETH_MIIADDR_FIAD_OFFSET)&
1480
           ETH_MIIADDR_FIAD_MASK) == eth->phy_addr)
1481
        {
1482
          /* Correct PHY - now switch based on the register address in the PHY*/
1483
          switch ((eth->regs.miiaddress >> ETH_MIIADDR_RGAD_OFFSET)&
1484
                  ETH_MIIADDR_RGAD_MASK)
1485
            {
1486
            case MII_BMCR:
1487
              eth->regs.miirx_data = BMCR_FULLDPLX;
1488
              break;
1489
            case MII_BMSR:
1490
              eth->regs.miirx_data = BMSR_LSTATUS | BMSR_ANEGCOMPLETE |
1491
                BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL;
1492
              break;
1493
            case MII_PHYSID1:
1494
              eth->regs.miirx_data = 0x22; /* Micrel PHYID */
1495
              break;
1496
            case MII_PHYSID2:
1497
              eth->regs.miirx_data = 0x1613; /* Micrel PHYID */
1498
              break;
1499
            case MII_ADVERTISE:
1500 436 julius
              eth->regs.miirx_data = ADVERTISE_FULL;
1501 428 julius
              break;
1502
            case MII_LPA:
1503
              eth->regs.miirx_data = LPA_DUPLEX | LPA_100;
1504
              break;
1505
            case MII_EXPANSION:
1506
              eth->regs.miirx_data = 0;
1507
              break;
1508
            case MII_CTRL1000:
1509
              eth->regs.miirx_data = 0;
1510
              break;
1511
            case MII_STAT1000:
1512
              eth->regs.miirx_data = 0;
1513
              break;
1514
            case MII_ESTATUS:
1515
              eth->regs.miirx_data = 0;
1516
              break;
1517
            case MII_DCOUNTER:
1518
              eth->regs.miirx_data = 0;
1519
              break;
1520
            case MII_FCSCOUNTER:
1521
              eth->regs.miirx_data = 0;
1522
              break;
1523
            case MII_NWAYTEST:
1524
              eth->regs.miirx_data = 0;
1525
              break;
1526
            case MII_RERRCOUNTER:
1527
              eth->regs.miirx_data = 0;
1528
              break;
1529
            case MII_SREVISION:
1530
              eth->regs.miirx_data = 0;
1531
              break;
1532
            case MII_RESV1:
1533
              eth->regs.miirx_data = 0;
1534
              break;
1535
            case MII_LBRERROR:
1536
              eth->regs.miirx_data = 0;
1537
              break;
1538
            case MII_PHYADDR:
1539
              eth->regs.miirx_data = eth->phy_addr;
1540
              break;
1541
            case MII_RESV2:
1542
              eth->regs.miirx_data = 0;
1543
              break;
1544
            case MII_TPISTATUS:
1545
              eth->regs.miirx_data = 0;
1546
              break;
1547
            case MII_NCONFIG:
1548
              eth->regs.miirx_data = 0;
1549
              break;
1550
            default:
1551
              eth->regs.miirx_data = 0xffff;
1552
              break;
1553
            }
1554
        }
1555
      else
1556
        eth->regs.miirx_data = 0xffff; /* PHY doesn't exist, read all 1's */
1557
      break;
1558
 
1559
    case ((1 << ETH_MIICOMM_SCANS_OFFSET)):
1560
      /* From MAC's datasheet:
1561
         A host initiates the Scan Status Operation by asserting the SCANSTAT
1562
         signal. The MIIM performs a continuous read operation of the PHY
1563
         Status register. The PHY is selected by the FIAD[4:0] signals. The
1564
         link status LinkFail signal is asserted/deasserted by the MIIM module
1565
         and reflects the link status bit of the PHY Status register. The
1566
         signal NVALID is used for qualifying the validity of the LinkFail
1567
         signals and the status data PRSD[15:0]. These signals are invalid
1568
         until the first scan status operation ends. During the scan status
1569
         operation, the BUSY signal is asserted until the last read is
1570
         performed (the scan status operation is stopped).
1571
 
1572
         So for now - do nothing, leave link status indicator as permanently
1573
         with link.
1574
      */
1575
 
1576
      break;
1577
 
1578
    default:
1579
      break;
1580
    }
1581
 
1582
}
1583
 
1584
/*---------------------------------------------------------------------------*/
1585 19 jeremybenn
/*!Initialize a new Ethernet configuration
1586
 
1587
   ALL parameters are set explicitly to default values.                      */
1588
/*---------------------------------------------------------------------------*/
1589
static void *
1590
eth_sec_start (void)
1591
{
1592
  struct eth_device *new = malloc (sizeof (struct eth_device));
1593
 
1594
  if (!new)
1595
    {
1596
      fprintf (stderr, "Peripheral Eth: Run out of memory\n");
1597
      exit (-1);
1598
    }
1599
 
1600
  memset (new, 0, sizeof (struct eth_device));
1601
 
1602
  new->enabled      = 1;
1603
  new->baseaddr     = 0;
1604
  new->dma          = 0;
1605
  new->mac_int      = 0;
1606 437 julius
  new->int_line_stat= 0;
1607 434 jeremybenn
  new->rtx_type     = ETH_RTX_FILE;
1608 19 jeremybenn
  new->rx_channel   = 0;
1609
  new->tx_channel   = 0;
1610 436 julius
  new->rtx_fd       = 0;
1611 19 jeremybenn
  new->rxfile       = strdup ("eth_rx");
1612
  new->txfile       = strdup ("eth_tx");
1613 434 jeremybenn
  new->tap_dev      = strdup ("");
1614 19 jeremybenn
  new->base_vapi_id = 0;
1615 428 julius
  new->phy_addr     = 0;
1616 19 jeremybenn
 
1617
  return new;
1618
}
1619
 
1620
static void
1621
eth_sec_end (void *dat)
1622
{
1623
  struct eth_device *eth = dat;
1624
  struct mem_ops ops;
1625
 
1626
  if (!eth->enabled)
1627
    {
1628
      free (eth->rxfile);
1629
      free (eth->txfile);
1630 434 jeremybenn
      free (eth->tap_dev);
1631 19 jeremybenn
      free (eth);
1632
      return;
1633
    }
1634
 
1635
  memset (&ops, 0, sizeof (struct mem_ops));
1636
 
1637
  ops.readfunc32 = eth_read32;
1638
  ops.writefunc32 = eth_write32;
1639
  ops.read_dat32 = dat;
1640
  ops.write_dat32 = dat;
1641
 
1642
  /* FIXME: Correct delay? */
1643
  ops.delayr = 2;
1644
  ops.delayw = 2;
1645
  reg_mem_area (eth->baseaddr, ETH_ADDR_SPACE, 0, &ops);
1646
  reg_sim_stat (eth_status, dat);
1647
  reg_sim_reset (eth_reset, dat);
1648
}
1649
 
1650
 
1651
/*---------------------------------------------------------------------------*/
1652
/*!Register a new Ethernet configuration                                     */
1653
/*---------------------------------------------------------------------------*/
1654
void
1655
reg_ethernet_sec ()
1656
{
1657
  struct config_section *sec =
1658
    reg_config_sec ("ethernet", eth_sec_start, eth_sec_end);
1659
 
1660 224 jeremybenn
  reg_config_param (sec, "enabled",    PARAMT_INT,  eth_enabled);
1661
  reg_config_param (sec, "baseaddr",   PARAMT_ADDR, eth_baseaddr);
1662
  reg_config_param (sec, "dma",        PARAMT_INT,  eth_dma);
1663
  reg_config_param (sec, "irq",        PARAMT_INT,  eth_irq);
1664 434 jeremybenn
  reg_config_param (sec, "rtx_type",   PARAMT_STR,  eth_rtx_type);
1665 224 jeremybenn
  reg_config_param (sec, "rx_channel", PARAMT_INT,  eth_rx_channel);
1666
  reg_config_param (sec, "tx_channel", PARAMT_INT,  eth_tx_channel);
1667
  reg_config_param (sec, "rxfile",     PARAMT_STR,  eth_rxfile);
1668
  reg_config_param (sec, "txfile",     PARAMT_STR,  eth_txfile);
1669 434 jeremybenn
  reg_config_param (sec, "tap_dev",    PARAMT_STR,  eth_tap_dev);
1670 224 jeremybenn
  reg_config_param (sec, "vapi_id",    PARAMT_INT,  eth_vapi_id);
1671 428 julius
  reg_config_param (sec, "phy_addr",   PARAMT_INT,  eth_phy_addr);
1672 19 jeremybenn
 
1673
}       /* reg_ethernet_sec() */
1674
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.