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

Subversion Repositories openrisc

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

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 437 julius
  if (eth->tx.state == ETH_TXSTATE_WAIT4BD)
373
    SCHED_ADD (eth_controller_tx_clock, dat, 10);
374
  else
375
    SCHED_ADD (eth_controller_tx_clock, dat, 1);
376 19 jeremybenn
}
377
 
378
/* ========================================================================= */
379
 
380
 
381
/* ========================================================================= */
382
/*  RX LOGIC                                                                 */
383
/*---------------------------------------------------------------------------*/
384
 
385
/*
386
 * RX clock
387
 * Responsible for starting and finishing RX
388
 */
389
static void
390
eth_controller_rx_clock (void *dat)
391
{
392
  struct eth_device *eth = dat;
393 434 jeremybenn
  long               nread = 0;
394
  unsigned long      send_word;
395
  struct pollfd      fds[1];
396
  int                n;
397 19 jeremybenn
 
398
 
399
  switch (eth->rx.state)
400
    {
401
    case ETH_RXSTATE_IDLE:
402
      eth->rx.state = ETH_RXSTATE_WAIT4BD;
403
      break;
404
 
405
    case ETH_RXSTATE_WAIT4BD:
406 434 jeremybenn
 
407
      eth->rx.bd      = eth->regs.bd_ram[eth->rx.bd_index];
408 19 jeremybenn
      eth->rx.bd_addr = eth->regs.bd_ram[eth->rx.bd_index + 1];
409
 
410
      if (TEST_FLAG (eth->rx.bd, ETH_RX_BD, READY))
411
        {
412
            /*****************/
413
          /* Initialize RX */
414
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, MISS);
415
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, INVALID);
416
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, DRIBBLE);
417
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, UVERRUN);
418
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, COLLISION);
419
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
420
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
421
 
422
          /* Setup file to read from */
423
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, LOOPBCK))
424
            {
425
              eth->rx.fd = eth->txfd;
426
              eth->rx.offset = &(eth->loopback_offset);
427
            }
428
          else
429
            {
430
              eth->rx.fd = eth->rxfd;
431
              eth->rx.offset = 0;
432
            }
433
          eth->rx.state = ETH_RXSTATE_RECV;
434 437 julius
 
435 19 jeremybenn
        }
436
      else if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
437
        {
438
          eth->rx.state = ETH_RXSTATE_IDLE;
439
        }
440
      else
441
        {
442 434 jeremybenn
          /* Poll to see if there is data to read */
443
          struct pollfd  fds[1];
444
          int    n;
445
 
446
          fds[0].fd = eth->rtx_fd;
447
          fds[0].events = POLLIN;
448
 
449
          n = poll (fds, 1, 0);
450
          if (n < 0)
451 19 jeremybenn
            {
452 434 jeremybenn
              fprintf (stderr, "Warning: Poll of WAIT4BD failed %s: ignored.\n",
453
                       strerror (errno));
454 19 jeremybenn
            }
455 434 jeremybenn
          else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
456
            {
457 436 julius
              printf ("Reading TAP and all BDs full = BUSY\n");
458 434 jeremybenn
              nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
459
 
460
              if (nread < 0)
461
                {
462
                  fprintf (stderr,
463
                           "Warning: Read of WAIT4BD failed %s: ignored\n",
464
                           strerror (errno));
465
                }
466
              else if (nread > 0)
467
                {
468
                  SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
469
 
470 437 julius
                  if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, BUSY_M) &&
471
                      !eth->int_line_stat)
472 434 jeremybenn
                    {
473 436 julius
                      printf ("ETH_RXSTATE_WAIT4BD BUSY interrupt\n");
474 434 jeremybenn
                      report_interrupt (eth->mac_int);
475 437 julius
                      eth->int_line_stat = 1;
476 434 jeremybenn
                    }
477
                }
478
            }
479 19 jeremybenn
        }
480 434 jeremybenn
 
481 19 jeremybenn
      break;
482
 
483
    case ETH_RXSTATE_RECV:
484 434 jeremybenn
 
485 19 jeremybenn
      switch (eth->rtx_type)
486
        {
487
        case ETH_RTX_FILE:
488
          /* Read packet length */
489
          if (eth_read_rx_file
490
              (eth, &(eth->rx.packet_length),
491
               sizeof (eth->rx.packet_length)) <
492
              sizeof (eth->rx.packet_length))
493
            {
494 434 jeremybenn
              /* TODO: just do what real ethernet would do (some kind of error
495
                 state) */
496 19 jeremybenn
              sim_done ();
497
              break;
498
            }
499
 
500
          /* Packet must be big enough to hold a header */
501
          if (eth->rx.packet_length < ETHER_HDR_LEN)
502
            {
503
              eth_rx_next_packet (eth);
504
 
505
              eth->rx.state = ETH_RXSTATE_WAIT4BD;
506
              break;
507
            }
508
 
509
          eth->rx.bytes_read = 0;
510
          eth->rx.bytes_left = eth->rx.packet_length;
511
 
512
          /* for now Read entire packet into memory */
513
          nread = eth_read_rx_file (eth, eth->rx_buff, eth->rx.bytes_left);
514
          if (nread < eth->rx.bytes_left)
515
            {
516
              eth->rx.error = 1;
517
              break;
518
            }
519
 
520
          eth->rx.packet_length = nread;
521
          eth->rx.bytes_left = nread;
522
          eth->rx.bytes_read = 0;
523
 
524
          eth->rx.state = ETH_RXSTATE_WRITEFIFO;
525
 
526
          break;
527
 
528 434 jeremybenn
        case ETH_RTX_TAP:
529
          /* Poll to see if there is data to read */
530
          fds[0].fd     = eth->rtx_fd;
531
          fds[0].events = POLLIN;
532
 
533
          n = poll (fds, 1, 0);
534
          if (n < 0)
535 19 jeremybenn
            {
536 434 jeremybenn
              fprintf (stderr,
537
                       "Warning: Poll of RXTATE_RECV failed %s: ignored.\n",
538
                       strerror (errno));
539 19 jeremybenn
            }
540 434 jeremybenn
          else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
541 19 jeremybenn
            {
542 437 julius
#if ETH_DEBUG
543
              printf ("Reading TAP. ");
544
#endif
545 434 jeremybenn
              nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
546 437 julius
#if ETH_DEBUG
547
              printf ("%d bytes read.\n",(int) nread);
548
#endif
549 434 jeremybenn
              if (nread < 0)
550 19 jeremybenn
                {
551 434 jeremybenn
                  fprintf (stderr,
552
                           "Warning: Read of RXTATE_RECV failed %s: ignored\n",
553 436 julius
                           strerror (errno));
554 434 jeremybenn
 
555 437 julius
                  SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXE);
556
 
557
                  if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXE_M) &&
558
                      !eth->int_line_stat)
559
                    {
560 436 julius
                      printf ("ETH_RXTATE_RECV RXE interrupt\n");
561 434 jeremybenn
                      report_interrupt (eth->mac_int);
562 437 julius
                      eth->int_line_stat = 1;
563 434 jeremybenn
                    }
564
                }
565 436 julius
 
566 19 jeremybenn
            }
567 434 jeremybenn
 
568 19 jeremybenn
          /* If not promiscouos mode, check the destination address */
569 436 julius
          if (!TEST_FLAG (eth->regs.moder, ETH_MODER, PRO) && nread)
570 19 jeremybenn
            {
571
              if (TEST_FLAG (eth->regs.moder, ETH_MODER, IAM)
572
                  && (eth->rx_buff[0] & 1))
573
                {
574
                  /* Nothing for now */
575
                }
576
 
577 436 julius
 
578
              if (((eth->mac_address[5] != eth->rx_buff[0]) &&
579
                   (eth->rx_buff[5] != 0xff) ) ||
580
                  ((eth->mac_address[4] != eth->rx_buff[1]) &&
581
                   (eth->rx_buff[4] != 0xff) ) ||
582
                  ((eth->mac_address[3] != eth->rx_buff[2]) &&
583
                   (eth->rx_buff[3] != 0xff) ) ||
584
                  ((eth->mac_address[2] != eth->rx_buff[3]) &&
585
                   (eth->rx_buff[2] != 0xff) ) ||
586
                  ((eth->mac_address[1] != eth->rx_buff[4]) &&
587
                   (eth->rx_buff[1] != 0xff) ) ||
588
                  ((eth->mac_address[0] != eth->rx_buff[5]) &&
589
                   (eth->rx_buff[0] != 0xff)))
590
 
591
              {
592 437 julius
#if ETH_DEBUG           
593 436 julius
                  printf("ETH_RXSTATE dropping packet for %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
594
                       eth->rx_buff[0],
595
                       eth->rx_buff[1],
596
                       eth->rx_buff[2],
597
                       eth->rx_buff[3],
598
                       eth->rx_buff[4],
599
                       eth->rx_buff[5]);
600 437 julius
#endif
601 19 jeremybenn
                break;
602 436 julius
              }
603 19 jeremybenn
            }
604
 
605
          eth->rx.packet_length = nread;
606
          eth->rx.bytes_left = nread;
607
          eth->rx.bytes_read = 0;
608
 
609 436 julius
          if (nread)
610
            eth->rx.state = ETH_RXSTATE_WRITEFIFO;
611 19 jeremybenn
 
612
          break;
613
        case ETH_RTX_VAPI:
614
          break;
615
        }
616
      break;
617
 
618
    case ETH_RXSTATE_WRITEFIFO:
619 437 julius
#if ETH_DEBUG
620
      printf("ETH_RXSTATE_WRITEFIFO: writing to RXBD%d: %d bytes @ 0x%.8x\n",
621
             (int) eth->rx.bd_index/2,  (int)eth->rx.bytes_left,
622
             (unsigned int)eth->rx.bd_addr);
623
#endif
624 436 julius
      if (eth->rx.bytes_left > 0){
625
        while((int) eth->rx.bytes_left){
626
          send_word = ((unsigned long) eth->rx_buff[eth->rx.bytes_read] << 24) |
627
            ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 1] << 16) |
628
            ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 2] << 8) |
629
            ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 3]);
630
          set_direct32 (eth->rx.bd_addr + eth->rx.bytes_read, send_word, 0, 0);
631
          /* update counters */
632
          if (eth->rx.bytes_left >= 4)
633
            {
634
              eth->rx.bytes_left -= 4;
635
              eth->rx.bytes_read += 4;
636
            }
637
          else
638
            {
639
              eth->rx.bytes_read += eth->rx.bytes_left;
640
              eth->rx.bytes_left = 0;
641
            }
642
        }
643
 
644
      }
645 437 julius
#if ETH_DEBUG
646
      printf("ETH_RXSTATE_WRITEFIFO: bytes read: 0x%.8x\n",
647
             (unsigned int)eth->rx.bytes_read);
648
#endif
649 19 jeremybenn
      if (eth->rx.bytes_left <= 0)
650
        {
651
          /* Write result to bd */
652 437 julius
          SET_FIELD (eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length + 4);
653 19 jeremybenn
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, READY);
654
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
655 436 julius
          /*
656 19 jeremybenn
          if (eth->rx.packet_length <
657
              (GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL) - 4))
658
            SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
659
          if (eth->rx.packet_length >
660
              GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MAXFL))
661
            SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
662 436 julius
          */
663 19 jeremybenn
          eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
664
 
665
          /* advance to next BD */
666
          if (TEST_FLAG (eth->rx.bd, ETH_RX_BD, WRAP)
667
              || eth->rx.bd_index >= ETH_BD_COUNT)
668
            eth->rx.bd_index = eth->regs.tx_bd_num << 1;
669
          else
670
            eth->rx.bd_index += 2;
671
 
672 437 julius
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
673
 
674 19 jeremybenn
          if ((TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXB_M)) &&
675 437 julius
              (TEST_FLAG (eth->rx.bd, ETH_RX_BD, IRQ)) &&
676
              !eth->int_line_stat)
677 19 jeremybenn
            {
678 437 julius
#if ETH_DEBUG
679
              printf ("ETH_RXSTATE_WRITEFIFO interrupt\n");
680
#endif
681 19 jeremybenn
              report_interrupt (eth->mac_int);
682 437 julius
              eth->int_line_stat = 1;
683 19 jeremybenn
            }
684
 
685
          /* ready to receive next packet */
686
          eth->rx.state = ETH_RXSTATE_IDLE;
687
        }
688
      break;
689
    }
690
 
691
  /* Reschedule */
692 437 julius
  if (eth->rx.state == ETH_RXSTATE_RECV)
693
    SCHED_ADD (eth_controller_rx_clock, dat, 10);
694
  else
695
    SCHED_ADD (eth_controller_rx_clock, dat, 1);
696 19 jeremybenn
}
697
 
698
/* ========================================================================= */
699
/* Move to next RX BD */
700
static void
701
eth_rx_next_packet (struct eth_device *eth)
702
{
703
  /* Skip any possible leftovers */
704
  if (eth->rx.bytes_left)
705
    eth_skip_rx_file (eth, eth->rx.bytes_left);
706
}
707
 
708
/* "Skip" bytes in RX file */
709
static void
710
eth_skip_rx_file (struct eth_device *eth, off_t count)
711
{
712
  eth->rx.offset += count;
713
}
714
 
715
/*
716
 * Utility function to read from the ethernet RX file
717
 * This function moves the file pointer to the current place in the packet before reading
718
 */
719
static ssize_t
720
eth_read_rx_file (struct eth_device *eth, void *buf, size_t count)
721
{
722
  ssize_t result;
723
 
724
  if (eth->rx.fd <= 0)
725
    {
726
      return 0;
727
    }
728
 
729
  if (eth->rx.offset)
730
    if (lseek (eth->rx.fd, *(eth->rx.offset), SEEK_SET) == (off_t) - 1)
731
      {
732
        return 0;
733
      }
734
 
735
  result = read (eth->rx.fd, buf, count);
736
  if (eth->rx.offset && result >= 0)
737
    *(eth->rx.offset) += result;
738
 
739
  return result;
740
}
741
 
742
/* ========================================================================= */
743
 
744 434 jeremybenn
 
745
/* -------------------------------------------------------------------------- */
746
/*!Reset the Ethernet.
747
 
748
   Open the correct type of simulation interface to the outside world.
749
 
750
   Initialize all registers to default and places devices in memory address
751
   space.
752
 
753
   @param[in] dat  The Ethernet interface data structure.                     */
754
/* -------------------------------------------------------------------------- */
755 19 jeremybenn
static void
756
eth_reset (void *dat)
757
{
758
  struct eth_device *eth = dat;
759 434 jeremybenn
  struct ifreq       ifr;
760 19 jeremybenn
 
761 437 julius
#if ETH_DEBUG
762 434 jeremybenn
  printf ("Resetting Ethernet\n");
763 437 julius
#endif
764 434 jeremybenn
  /* Nothing to do if we do not have a base address set.
765
 
766
     TODO: Surely this should test for being enabled? */
767
  if (0 == eth->baseaddr)
768 19 jeremybenn
    {
769 434 jeremybenn
      return;
770
    }
771
 
772
  switch (eth->rtx_type)
773
    {
774
    case ETH_RTX_FILE:
775
 
776
      /* (Re-)open TX/RX files */
777
      if (eth->rxfd >= 0)
778 19 jeremybenn
        {
779 434 jeremybenn
          close (eth->rxfd);
780
        }
781 19 jeremybenn
 
782 434 jeremybenn
      if (eth->txfd >= 0)
783
        {
784
          close (eth->txfd);
785
        }
786 19 jeremybenn
 
787 434 jeremybenn
      eth->rxfd = -1;
788
      eth->txfd = -1;
789 19 jeremybenn
 
790 434 jeremybenn
      eth->rxfd = open (eth->rxfile, O_RDONLY);
791
      if (eth->rxfd < 0)
792
        {
793
          fprintf (stderr, "Warning: Cannot open Ethernet RX file \"%s\": %s\n",
794
                   eth->rxfile, strerror (errno));
795
        }
796 19 jeremybenn
 
797 434 jeremybenn
      eth->txfd = open (eth->txfile,
798
#if defined(O_SYNC)             /* BSD/MacOS X doesn't know about O_SYNC */
799
                        O_SYNC |
800
#endif
801
                        O_RDWR | O_CREAT | O_APPEND,
802
                        S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
803
      if (eth->txfd < 0)
804
        {
805
          fprintf (stderr, "Warning: Cannot open Ethernet TX file \"%s\": %s\n",
806
                   eth->txfile, strerror (errno));
807
        }
808 19 jeremybenn
 
809 434 jeremybenn
      eth->loopback_offset = lseek (eth->txfd, 0, SEEK_END);
810
      break;
811 19 jeremybenn
 
812 434 jeremybenn
    case ETH_RTX_TAP:
813 19 jeremybenn
 
814 434 jeremybenn
      /* (Re-)open TAP interface if necessary */
815
      if (eth->rtx_fd != 0)
816
        {
817 19 jeremybenn
          break;
818
        }
819
 
820 434 jeremybenn
      /* Open the TUN/TAP device */
821
      eth->rtx_fd = open ("/dev/net/tun", O_RDWR);
822
      if( eth->rtx_fd < 0 )
823
        {
824
          fprintf (stderr, "Warning: Failed to open TUN/TAP device: %s\n",
825
                   strerror (errno));
826
          eth->rtx_fd = 0;
827
          return;
828
        }
829 19 jeremybenn
 
830 434 jeremybenn
      /* Turn it into a specific TAP device. If we haven't specified a
831
         specific (persistent) device, one will be created, but that requires
832
         superuser, or at least CAP_NET_ADMIN capabilities. */
833
      memset (&ifr, 0, sizeof(ifr));
834 436 julius
      ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
835 434 jeremybenn
      strncpy (ifr.ifr_name, eth->tap_dev, IFNAMSIZ);
836 19 jeremybenn
 
837 434 jeremybenn
      if (ioctl (eth->rtx_fd, TUNSETIFF, (void *) &ifr) < 0)
838 19 jeremybenn
        {
839 434 jeremybenn
          fprintf (stderr, "Warning: Failed to set TAP device: %s\n",
840
                   strerror (errno));
841
          close (eth->rtx_fd);
842
          eth->rtx_fd = 0;
843
          return;
844 19 jeremybenn
        }
845 437 julius
#if ETH_DEBUG
846 434 jeremybenn
      PRINTF ("Opened TAP %s\n", ifr.ifr_name);
847 437 julius
#endif
848 434 jeremybenn
      /* Do we need to flush any packets? */
849
      break;
850 19 jeremybenn
    }
851
 
852 434 jeremybenn
  /* Set registers to default values */
853
  memset (&(eth->regs), 0, sizeof (eth->regs));
854 19 jeremybenn
 
855 434 jeremybenn
  eth->regs.moder     = 0x0000A000;
856
  eth->regs.ipgt      = 0x00000012;
857
  eth->regs.ipgr1     = 0x0000000C;
858
  eth->regs.ipgr2     = 0x00000012;
859
  eth->regs.packetlen = 0x003C0600;
860
  eth->regs.collconf  = 0x000F003F;
861
  eth->regs.miimoder  = 0x00000064;
862
  eth->regs.tx_bd_num = 0x00000040;
863 19 jeremybenn
 
864 434 jeremybenn
  /* Clear TX/RX status and initialize buffer descriptor index. */
865
  memset (&(eth->tx), 0, sizeof (eth->tx));
866
  memset (&(eth->rx), 0, sizeof (eth->rx));
867
 
868 436 julius
  /* Reset TX/RX BD indexes */
869
  eth->tx.bd_index = 0;
870 434 jeremybenn
  eth->rx.bd_index = eth->regs.tx_bd_num << 1;
871
 
872 437 julius
  /* Reset IRQ line status */
873
  eth->int_line_stat = 0;
874
 
875 434 jeremybenn
  /* Initialize VAPI */
876
  if (eth->base_vapi_id)
877
    {
878
      vapi_install_multi_handler (eth->base_vapi_id, ETH_NUM_VAPI_IDS,
879
                                  eth_vapi_read, dat);
880
    }
881
}       /* eth_reset () */
882
 
883
 
884 19 jeremybenn
/*
885
  Print register values on stdout
886
*/
887
static void
888
eth_status (void *dat)
889
{
890
  struct eth_device *eth = dat;
891
 
892
  PRINTF ("\nEthernet MAC at 0x%" PRIxADDR ":\n", eth->baseaddr);
893
  PRINTF ("MODER        : 0x%08lX\n", eth->regs.moder);
894
  PRINTF ("INT_SOURCE   : 0x%08lX\n", eth->regs.int_source);
895
  PRINTF ("INT_MASK     : 0x%08lX\n", eth->regs.int_mask);
896
  PRINTF ("IPGT         : 0x%08lX\n", eth->regs.ipgt);
897
  PRINTF ("IPGR1        : 0x%08lX\n", eth->regs.ipgr1);
898
  PRINTF ("IPGR2        : 0x%08lX\n", eth->regs.ipgr2);
899
  PRINTF ("PACKETLEN    : 0x%08lX\n", eth->regs.packetlen);
900
  PRINTF ("COLLCONF     : 0x%08lX\n", eth->regs.collconf);
901
  PRINTF ("TX_BD_NUM    : 0x%08lX\n", eth->regs.tx_bd_num);
902
  PRINTF ("CTRLMODER    : 0x%08lX\n", eth->regs.controlmoder);
903
  PRINTF ("MIIMODER     : 0x%08lX\n", eth->regs.miimoder);
904
  PRINTF ("MIICOMMAND   : 0x%08lX\n", eth->regs.miicommand);
905
  PRINTF ("MIIADDRESS   : 0x%08lX\n", eth->regs.miiaddress);
906
  PRINTF ("MIITX_DATA   : 0x%08lX\n", eth->regs.miitx_data);
907
  PRINTF ("MIIRX_DATA   : 0x%08lX\n", eth->regs.miirx_data);
908
  PRINTF ("MIISTATUS    : 0x%08lX\n", eth->regs.miistatus);
909
  PRINTF ("MAC Address  : %02X:%02X:%02X:%02X:%02X:%02X\n",
910
          eth->mac_address[0], eth->mac_address[1], eth->mac_address[2],
911
          eth->mac_address[3], eth->mac_address[4], eth->mac_address[5]);
912
  PRINTF ("HASH0        : 0x%08lX\n", eth->regs.hash0);
913
  PRINTF ("HASH1        : 0x%08lX\n", eth->regs.hash1);
914
}
915
 
916
/* ========================================================================= */
917
 
918
 
919
/*
920
  Read a register
921
*/
922
static uint32_t
923
eth_read32 (oraddr_t addr, void *dat)
924
{
925
  struct eth_device *eth = dat;
926
 
927
  switch (addr)
928
    {
929
    case ETH_MODER:
930
      return eth->regs.moder;
931
    case ETH_INT_SOURCE:
932
      return eth->regs.int_source;
933
    case ETH_INT_MASK:
934
      return eth->regs.int_mask;
935
    case ETH_IPGT:
936
      return eth->regs.ipgt;
937
    case ETH_IPGR1:
938
      return eth->regs.ipgr1;
939
    case ETH_IPGR2:
940
      return eth->regs.ipgr2;
941
    case ETH_PACKETLEN:
942
      return eth->regs.packetlen;
943
    case ETH_COLLCONF:
944
      return eth->regs.collconf;
945
    case ETH_TX_BD_NUM:
946
      return eth->regs.tx_bd_num;
947
    case ETH_CTRLMODER:
948
      return eth->regs.controlmoder;
949
    case ETH_MIIMODER:
950
      return eth->regs.miimoder;
951
    case ETH_MIICOMMAND:
952
      return eth->regs.miicommand;
953
    case ETH_MIIADDRESS:
954
      return eth->regs.miiaddress;
955
    case ETH_MIITX_DATA:
956
      return eth->regs.miitx_data;
957
    case ETH_MIIRX_DATA:
958 428 julius
      /*printf("or1ksim: read MIIM RX: 0x%x\n",(int)eth->regs.miirx_data);*/
959 19 jeremybenn
      return eth->regs.miirx_data;
960
    case ETH_MIISTATUS:
961
      return eth->regs.miistatus;
962
    case ETH_MAC_ADDR0:
963
      return (((unsigned long) eth->mac_address[3]) << 24) |
964
        (((unsigned long) eth->mac_address[2]) << 16) |
965
        (((unsigned long) eth->mac_address[1]) << 8) |
966
        (unsigned long) eth->mac_address[0];
967
    case ETH_MAC_ADDR1:
968
      return (((unsigned long) eth->mac_address[5]) << 8) |
969
        (unsigned long) eth->mac_address[4];
970
    case ETH_HASH0:
971
      return eth->regs.hash0;
972
    case ETH_HASH1:
973
      return eth->regs.hash1;
974
      /*case ETH_DMA_RX_TX: return eth_rx( eth ); */
975
    }
976
 
977
  if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
978
    return eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4];
979
 
980
  PRINTF ("eth_read32( 0x%" PRIxADDR " ): Illegal address\n",
981
          addr + eth->baseaddr);
982
  return 0;
983
}
984
 
985
/* ========================================================================= */
986
 
987
 
988
/*
989
  Write a register
990
*/
991
static void
992
eth_write32 (oraddr_t addr, uint32_t value, void *dat)
993
{
994
  struct eth_device *eth = dat;
995
 
996
  switch (addr)
997
    {
998
    case ETH_MODER:
999 437 julius
#if ETH_DEBUG
1000
      printf("eth_write32: MODER 0x%x\n",value);
1001
#endif
1002 19 jeremybenn
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN) &&
1003
          TEST_FLAG (value, ETH_MODER, RXEN))
1004 436 julius
        {
1005
          // Reset RX BD index
1006
          eth->rx.bd_index = eth->regs.tx_bd_num << 1;
1007 437 julius
 
1008
          // Clear TAP
1009
          {
1010
            /* Poll to see if there is data to read */
1011
            struct pollfd  fds[1];
1012
            int    n;
1013
            int nread;
1014
 
1015
            fds[0].fd = eth->rtx_fd;
1016
            fds[0].events = POLLIN;
1017
 
1018
            do {
1019
              n = poll (fds, 1, 0);
1020
              if (n < 0)
1021
                {
1022
                  fprintf (stderr, "Warning: Poll in while emptying TAP: %s: ignored.\n",
1023
                           strerror (errno));
1024
                }
1025
              else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
1026
                {
1027
                  nread = read (eth->rtx_fd, eth->rx_buff, ETH_MAXPL);
1028
 
1029
                  if (nread < 0)
1030
                    {
1031
                      fprintf (stderr,
1032
                               "Warning: Read failed %s: ignored\n",
1033
                               strerror (errno));
1034
                    }
1035
                }
1036
            } while (n > 0);
1037
          }
1038
 
1039 436 julius
          SCHED_ADD (eth_controller_rx_clock, dat, 1);
1040
        }
1041 437 julius
      else if (!TEST_FLAG (value, ETH_MODER, RXEN) &&
1042
               TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
1043 19 jeremybenn
        SCHED_FIND_REMOVE (eth_controller_rx_clock, dat);
1044
 
1045
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN) &&
1046
          TEST_FLAG (value, ETH_MODER, TXEN))
1047 436 julius
        {
1048
          eth->tx.bd_index = 0;
1049
          SCHED_ADD (eth_controller_tx_clock, dat, 1);
1050
        }
1051 437 julius
      else if (!TEST_FLAG (value, ETH_MODER, TXEN) &&
1052
               TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN))
1053 19 jeremybenn
        SCHED_FIND_REMOVE (eth_controller_tx_clock, dat);
1054
 
1055
      eth->regs.moder = value;
1056
 
1057
      if (TEST_FLAG (value, ETH_MODER, RST))
1058
        eth_reset (dat);
1059
      return;
1060
    case ETH_INT_SOURCE:
1061 437 julius
#if ETH_DEBUG
1062
      printf("eth_write32: INT_SOURCE 0x%x\n",value);
1063
#endif
1064
      eth->regs.int_source &= ~value;
1065 436 julius
 
1066 437 julius
      // Clear IRQ line if all interrupt sources have been dealt with
1067
      if (!(eth->regs.int_source & eth->regs.int_mask) && eth->int_line_stat)
1068
        {
1069
          clear_interrupt (eth->mac_int);
1070
          eth->int_line_stat = 0;
1071
        }
1072
 
1073 19 jeremybenn
      return;
1074
    case ETH_INT_MASK:
1075 437 julius
#if ETH_DEBUG
1076
      printf("eth_write32: INT_MASK 0x%x\n",value);
1077
#endif
1078 19 jeremybenn
      eth->regs.int_mask = value;
1079 437 julius
      if ((eth->regs.int_source & eth->regs.int_mask) && !eth->int_line_stat)
1080 436 julius
        report_interrupt (eth->mac_int);
1081
      else
1082 437 julius
        if (eth->int_line_stat)
1083
          {
1084
            clear_interrupt (eth->mac_int);
1085
            eth->int_line_stat = 0;
1086
          }
1087 19 jeremybenn
      return;
1088
    case ETH_IPGT:
1089
      eth->regs.ipgt = value;
1090
      return;
1091
    case ETH_IPGR1:
1092
      eth->regs.ipgr1 = value;
1093
      return;
1094
    case ETH_IPGR2:
1095
      eth->regs.ipgr2 = value;
1096
      return;
1097
    case ETH_PACKETLEN:
1098
      eth->regs.packetlen = value;
1099
      return;
1100
    case ETH_COLLCONF:
1101
      eth->regs.collconf = value;
1102
      return;
1103
    case ETH_TX_BD_NUM:
1104
      eth_write_tx_bd_num (eth, value);
1105
      return;
1106
    case ETH_CTRLMODER:
1107
      eth->regs.controlmoder = value;
1108
      return;
1109
    case ETH_MIIMODER:
1110
      eth->regs.miimoder = value;
1111
      return;
1112
    case ETH_MIICOMMAND:
1113
      eth->regs.miicommand = value;
1114 428 julius
      /* Perform MIIM transaction, if required */
1115
      eth_miim_trans(dat);
1116 19 jeremybenn
      return;
1117
    case ETH_MIIADDRESS:
1118
      eth->regs.miiaddress = value;
1119
      return;
1120
    case ETH_MIITX_DATA:
1121
      eth->regs.miitx_data = value;
1122
      return;
1123
    case ETH_MIIRX_DATA:
1124 428 julius
      /* Register is R/O
1125 19 jeremybenn
      eth->regs.miirx_data = value;
1126 428 julius
      */
1127 19 jeremybenn
      return;
1128
    case ETH_MIISTATUS:
1129 428 julius
      /* Register is R/O
1130 19 jeremybenn
      eth->regs.miistatus = value;
1131 428 julius
      */
1132 19 jeremybenn
      return;
1133 428 julius
 
1134 19 jeremybenn
    case ETH_MAC_ADDR0:
1135
      eth->mac_address[0] = value & 0xFF;
1136
      eth->mac_address[1] = (value >> 8) & 0xFF;
1137
      eth->mac_address[2] = (value >> 16) & 0xFF;
1138
      eth->mac_address[3] = (value >> 24) & 0xFF;
1139
      return;
1140
    case ETH_MAC_ADDR1:
1141
      eth->mac_address[4] = value & 0xFF;
1142
      eth->mac_address[5] = (value >> 8) & 0xFF;
1143
      return;
1144
    case ETH_HASH0:
1145
      eth->regs.hash0 = value;
1146
      return;
1147
    case ETH_HASH1:
1148
      eth->regs.hash1 = value;
1149
      return;
1150
 
1151
      /*case ETH_DMA_RX_TX: eth_tx( eth, value ); return; */
1152
    }
1153
 
1154
  if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
1155
    {
1156
      eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value;
1157
      return;
1158
    }
1159
 
1160
  PRINTF ("eth_write32( 0x%" PRIxADDR " ): Illegal address\n",
1161
          addr + eth->baseaddr);
1162
  return;
1163
}
1164
 
1165
/* ========================================================================= */
1166
 
1167
 
1168
/*
1169
 *   VAPI connection to outside
1170
 */
1171
static void
1172
eth_vapi_read (unsigned long id, unsigned long data, void *dat)
1173
{
1174
  unsigned long which;
1175
  struct eth_device *eth = dat;
1176
 
1177
  which = id - eth->base_vapi_id;
1178
 
1179
  if (!eth)
1180
    {
1181
      return;
1182
    }
1183
 
1184
  switch (which)
1185
    {
1186
    case ETH_VAPI_DATA:
1187
      break;
1188
    case ETH_VAPI_CTRL:
1189
      break;
1190
    }
1191
}
1192
 
1193
/* ========================================================================= */
1194
 
1195
 
1196
/* When TX_BD_NUM is written, also reset current RX BD index */
1197
static void
1198
eth_write_tx_bd_num (struct eth_device *eth, unsigned long value)
1199
{
1200
  eth->regs.tx_bd_num = value & 0xFF;
1201
  eth->rx.bd_index = eth->regs.tx_bd_num << 1;
1202
}
1203
 
1204
/* ========================================================================= */
1205
 
1206
/*-----------------------------------------------[ Ethernet configuration ]---*/
1207
 
1208
 
1209
/*---------------------------------------------------------------------------*/
1210
/*!Enable or disable the Ethernet interface
1211
 
1212
   @param[in] val  The value to use
1213
   @param[in] dat  The config data structure                                 */
1214
/*---------------------------------------------------------------------------*/
1215
static void
1216
eth_enabled (union param_val  val,
1217
             void            *dat)
1218
{
1219
  struct eth_device *eth = dat;
1220
 
1221
  eth->enabled = val.int_val;
1222
 
1223
}       /* eth_enabled() */
1224
 
1225
 
1226
/*---------------------------------------------------------------------------*/
1227
/*!Set the Ethernet interface base address
1228
 
1229
   @param[in] val  The value to use
1230
   @param[in] dat  The config data structure                                 */
1231
/*---------------------------------------------------------------------------*/
1232
static void
1233
eth_baseaddr (union param_val  val,
1234
              void            *dat)
1235
{
1236
  struct eth_device *eth = dat;
1237
 
1238
  eth->baseaddr = val.addr_val;
1239
 
1240
}       /* eth_baseaddr() */
1241
 
1242
 
1243
/*---------------------------------------------------------------------------*/
1244
/*!Set the Ethernet DMA port
1245
 
1246
   This is not currently supported, so a warning message is printed.
1247
 
1248
   @param[in] val  The value to use
1249
   @param[in] dat  The config data structure                                 */
1250
/*---------------------------------------------------------------------------*/
1251
static void
1252
eth_dma (union param_val  val,
1253
         void            *dat)
1254
{
1255
  struct eth_device *eth = dat;
1256
 
1257
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported\n");
1258
  eth->dma = val.addr_val;
1259
 
1260
}       /* eth_dma() */
1261
 
1262
 
1263
/*---------------------------------------------------------------------------*/
1264
/*!Set the Ethernet IRQ
1265
 
1266
   @param[in] val  The value to use
1267
   @param[in] dat  The config data structure                                 */
1268
/*---------------------------------------------------------------------------*/
1269
static void
1270
eth_irq (union param_val  val,
1271
         void            *dat)
1272
{
1273
  struct eth_device *eth = dat;
1274
 
1275
  eth->mac_int = val.int_val;
1276
 
1277
}       /* eth_irq() */
1278
 
1279
 
1280
/*---------------------------------------------------------------------------*/
1281
/*!Set the Ethernet interface type
1282
 
1283 434 jeremybenn
   Currently two types are supported, file and tap.
1284 19 jeremybenn
 
1285 434 jeremybenn
   @param[in] val  The value to use. Currently "file" and "tap" are supported.
1286 19 jeremybenn
   @param[in] dat  The config data structure                                 */
1287
/*---------------------------------------------------------------------------*/
1288
static void
1289
eth_rtx_type (union param_val  val,
1290
              void            *dat)
1291
{
1292
  struct eth_device *eth = dat;
1293
 
1294 434 jeremybenn
  if (0 == strcasecmp ("file", val.str_val))
1295 19 jeremybenn
    {
1296 434 jeremybenn
      printf ("Ethernet FILE type\n");
1297
      eth->rtx_type = ETH_RTX_FILE;
1298 19 jeremybenn
    }
1299 434 jeremybenn
  else if (0 == strcasecmp ("tap", val.str_val))
1300
    {
1301
      printf ("Ethernet TAP type\n");
1302
      eth->rtx_type = ETH_RTX_TAP;
1303
    }
1304
  else
1305
    {
1306
      fprintf (stderr, "Warning: Unknown Ethernet type: file assumed.\n");
1307
      eth->rtx_type = ETH_RTX_FILE;
1308
    }
1309 19 jeremybenn
}       /* eth_rtx_type() */
1310
 
1311
 
1312
/*---------------------------------------------------------------------------*/
1313
/*!Set the Ethernet DMA Rx channel
1314
 
1315
   External DMA is not currently supported, so a warning message is printed.
1316
 
1317
   @param[in] val  The value to use
1318
   @param[in] dat  The config data structure                                 */
1319
/*---------------------------------------------------------------------------*/
1320
static void
1321
eth_rx_channel (union param_val  val,
1322
                void            *dat)
1323
{
1324
  struct eth_device *eth = dat;
1325
 
1326
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1327
           "Rx channel ignored\n");
1328
  eth->rx_channel = val.int_val;
1329
 
1330
}       /* eth_rx_channel() */
1331
 
1332
 
1333
/*---------------------------------------------------------------------------*/
1334
/*!Set the Ethernet DMA Tx channel
1335
 
1336
   External DMA is not currently supported, so a warning message is printed.
1337
 
1338
   @param[in] val  The value to use
1339
   @param[in] dat  The config data structure                                 */
1340
/*---------------------------------------------------------------------------*/
1341
static void
1342
eth_tx_channel (union param_val  val,
1343
                void            *dat)
1344
{
1345
  struct eth_device *eth = dat;
1346
 
1347
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1348
           "Tx channel ignored\n");
1349
  eth->tx_channel = val.int_val;
1350
 
1351
}       /* eth_tx_channel() */
1352
 
1353
 
1354
/*---------------------------------------------------------------------------*/
1355
/*!Set the Ethernet DMA Rx file
1356
 
1357
   Free any previously allocated value.
1358
 
1359
   @param[in] val  The value to use
1360
   @param[in] dat  The config data structure                                 */
1361
/*---------------------------------------------------------------------------*/
1362
static void
1363
eth_rxfile (union param_val  val,
1364
            void            *dat)
1365
{
1366
  struct eth_device *eth = dat;
1367
 
1368
  if (NULL != eth->rxfile)
1369
    {
1370
      free (eth->rxfile);
1371
      eth->rxfile = NULL;
1372
    }
1373
 
1374
  if (!(eth->rxfile = strdup (val.str_val)))
1375
    {
1376
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1377
      exit (-1);
1378
    }
1379
}       /* eth_rxfile() */
1380
 
1381
 
1382
/*---------------------------------------------------------------------------*/
1383
/*!Set the Ethernet DMA Tx file
1384
 
1385
   Free any previously allocated value.
1386
 
1387
   @param[in] val  The value to use
1388
   @param[in] dat  The config data structure                                 */
1389
/*---------------------------------------------------------------------------*/
1390
static void
1391
eth_txfile (union param_val  val,
1392
            void            *dat)
1393
{
1394
  struct eth_device *eth = dat;
1395
 
1396
  if (NULL != eth->txfile)
1397
    {
1398
      free (eth->txfile);
1399
      eth->txfile = NULL;
1400
    }
1401
 
1402
  if (!(eth->txfile = strdup (val.str_val)))
1403
    {
1404
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1405
      exit (-1);
1406
    }
1407
}       /* eth_txfile() */
1408
 
1409
 
1410
/*---------------------------------------------------------------------------*/
1411 434 jeremybenn
/*!Set the Ethernet TAP device.
1412 19 jeremybenn
 
1413 434 jeremybenn
   If we are not superuser (or do not have CAP_NET_ADMIN priviledges), then we
1414
   must work with a persistent TAP device that is already set up. This option
1415
   specifies the device to user.
1416 19 jeremybenn
 
1417 434 jeremybenn
   @param[in] val  The value to use.
1418 19 jeremybenn
   @param[in] dat  The config data structure                                 */
1419
/*---------------------------------------------------------------------------*/
1420
static void
1421 434 jeremybenn
eth_tap_dev (union param_val  val,
1422
              void            *dat)
1423 19 jeremybenn
{
1424
  struct eth_device *eth = dat;
1425
 
1426 434 jeremybenn
  if (NULL != eth->tap_dev)
1427 19 jeremybenn
    {
1428 434 jeremybenn
      free (eth->tap_dev);
1429
      eth->tap_dev = NULL;
1430 19 jeremybenn
    }
1431
 
1432 434 jeremybenn
  eth->tap_dev = strdup (val.str_val);
1433
 
1434
  if (NULL == eth->tap_dev)
1435 19 jeremybenn
    {
1436 434 jeremybenn
      fprintf (stderr, "ERROR: Peripheral Ethernet: Run out of memory\n");
1437 19 jeremybenn
      exit (-1);
1438
    }
1439 434 jeremybenn
}       /* eth_tap_dev() */
1440 19 jeremybenn
 
1441
 
1442
static void
1443
eth_vapi_id (union param_val  val,
1444
             void            *dat)
1445
{
1446
  struct eth_device *eth = dat;
1447
  eth->base_vapi_id = val.int_val;
1448
}
1449
 
1450 428 julius
 
1451
static void
1452
eth_phy_addr (union param_val  val,
1453
              void            *dat)
1454
{
1455
  struct eth_device *eth = dat;
1456
  eth->phy_addr = val.int_val & ETH_MIIADDR_FIAD_MASK;
1457
}
1458
 
1459
 
1460 19 jeremybenn
/*---------------------------------------------------------------------------*/
1461 428 julius
/*!Emulate MIIM transaction to ethernet PHY
1462
 
1463
   @param[in] dat  The config data structure                                 */
1464
/*---------------------------------------------------------------------------*/
1465
static void
1466
eth_miim_trans (void *dat)
1467
{
1468
  struct eth_device *eth = dat;
1469
  switch (eth->regs.miicommand)
1470
    {
1471
    case ((1 << ETH_MIICOMM_WCDATA_OFFSET)):
1472
      /* Perhaps something to emulate here later, but for now do nothing */
1473
      break;
1474
 
1475
    case ((1 << ETH_MIICOMM_RSTAT_OFFSET)):
1476 429 julius
      /*
1477 428 julius
      printf("or1ksim: eth_miim_trans: phy %d\n",(int)
1478
             ((eth->regs.miiaddress >> ETH_MIIADDR_FIAD_OFFSET)&
1479
              ETH_MIIADDR_FIAD_MASK));
1480
      printf("or1ksim: eth_miim_trans: reg %d\n",(int)
1481
             ((eth->regs.miiaddress >> ETH_MIIADDR_RGAD_OFFSET)&
1482
              ETH_MIIADDR_RGAD_MASK));
1483 429 julius
      */
1484 428 julius
      /*First check if it's the correct PHY to address */
1485
      if (((eth->regs.miiaddress >> ETH_MIIADDR_FIAD_OFFSET)&
1486
           ETH_MIIADDR_FIAD_MASK) == eth->phy_addr)
1487
        {
1488
          /* Correct PHY - now switch based on the register address in the PHY*/
1489
          switch ((eth->regs.miiaddress >> ETH_MIIADDR_RGAD_OFFSET)&
1490
                  ETH_MIIADDR_RGAD_MASK)
1491
            {
1492
            case MII_BMCR:
1493
              eth->regs.miirx_data = BMCR_FULLDPLX;
1494
              break;
1495
            case MII_BMSR:
1496
              eth->regs.miirx_data = BMSR_LSTATUS | BMSR_ANEGCOMPLETE |
1497
                BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL;
1498
              break;
1499
            case MII_PHYSID1:
1500
              eth->regs.miirx_data = 0x22; /* Micrel PHYID */
1501
              break;
1502
            case MII_PHYSID2:
1503
              eth->regs.miirx_data = 0x1613; /* Micrel PHYID */
1504
              break;
1505
            case MII_ADVERTISE:
1506 436 julius
              eth->regs.miirx_data = ADVERTISE_FULL;
1507 428 julius
              break;
1508
            case MII_LPA:
1509
              eth->regs.miirx_data = LPA_DUPLEX | LPA_100;
1510
              break;
1511
            case MII_EXPANSION:
1512
              eth->regs.miirx_data = 0;
1513
              break;
1514
            case MII_CTRL1000:
1515
              eth->regs.miirx_data = 0;
1516
              break;
1517
            case MII_STAT1000:
1518
              eth->regs.miirx_data = 0;
1519
              break;
1520
            case MII_ESTATUS:
1521
              eth->regs.miirx_data = 0;
1522
              break;
1523
            case MII_DCOUNTER:
1524
              eth->regs.miirx_data = 0;
1525
              break;
1526
            case MII_FCSCOUNTER:
1527
              eth->regs.miirx_data = 0;
1528
              break;
1529
            case MII_NWAYTEST:
1530
              eth->regs.miirx_data = 0;
1531
              break;
1532
            case MII_RERRCOUNTER:
1533
              eth->regs.miirx_data = 0;
1534
              break;
1535
            case MII_SREVISION:
1536
              eth->regs.miirx_data = 0;
1537
              break;
1538
            case MII_RESV1:
1539
              eth->regs.miirx_data = 0;
1540
              break;
1541
            case MII_LBRERROR:
1542
              eth->regs.miirx_data = 0;
1543
              break;
1544
            case MII_PHYADDR:
1545
              eth->regs.miirx_data = eth->phy_addr;
1546
              break;
1547
            case MII_RESV2:
1548
              eth->regs.miirx_data = 0;
1549
              break;
1550
            case MII_TPISTATUS:
1551
              eth->regs.miirx_data = 0;
1552
              break;
1553
            case MII_NCONFIG:
1554
              eth->regs.miirx_data = 0;
1555
              break;
1556
            default:
1557
              eth->regs.miirx_data = 0xffff;
1558
              break;
1559
            }
1560
        }
1561
      else
1562
        eth->regs.miirx_data = 0xffff; /* PHY doesn't exist, read all 1's */
1563
      break;
1564
 
1565
    case ((1 << ETH_MIICOMM_SCANS_OFFSET)):
1566
      /* From MAC's datasheet:
1567
         A host initiates the Scan Status Operation by asserting the SCANSTAT
1568
         signal. The MIIM performs a continuous read operation of the PHY
1569
         Status register. The PHY is selected by the FIAD[4:0] signals. The
1570
         link status LinkFail signal is asserted/deasserted by the MIIM module
1571
         and reflects the link status bit of the PHY Status register. The
1572
         signal NVALID is used for qualifying the validity of the LinkFail
1573
         signals and the status data PRSD[15:0]. These signals are invalid
1574
         until the first scan status operation ends. During the scan status
1575
         operation, the BUSY signal is asserted until the last read is
1576
         performed (the scan status operation is stopped).
1577
 
1578
         So for now - do nothing, leave link status indicator as permanently
1579
         with link.
1580
      */
1581
 
1582
      break;
1583
 
1584
    default:
1585
      break;
1586
    }
1587
 
1588
}
1589
 
1590
/*---------------------------------------------------------------------------*/
1591 19 jeremybenn
/*!Initialize a new Ethernet configuration
1592
 
1593
   ALL parameters are set explicitly to default values.                      */
1594
/*---------------------------------------------------------------------------*/
1595
static void *
1596
eth_sec_start (void)
1597
{
1598
  struct eth_device *new = malloc (sizeof (struct eth_device));
1599
 
1600
  if (!new)
1601
    {
1602
      fprintf (stderr, "Peripheral Eth: Run out of memory\n");
1603
      exit (-1);
1604
    }
1605
 
1606
  memset (new, 0, sizeof (struct eth_device));
1607
 
1608
  new->enabled      = 1;
1609
  new->baseaddr     = 0;
1610
  new->dma          = 0;
1611
  new->mac_int      = 0;
1612 437 julius
  new->int_line_stat= 0;
1613 434 jeremybenn
  new->rtx_type     = ETH_RTX_FILE;
1614 19 jeremybenn
  new->rx_channel   = 0;
1615
  new->tx_channel   = 0;
1616 436 julius
  new->rtx_fd       = 0;
1617 19 jeremybenn
  new->rxfile       = strdup ("eth_rx");
1618
  new->txfile       = strdup ("eth_tx");
1619 434 jeremybenn
  new->tap_dev      = strdup ("");
1620 19 jeremybenn
  new->base_vapi_id = 0;
1621 428 julius
  new->phy_addr     = 0;
1622 19 jeremybenn
 
1623
  return new;
1624
}
1625
 
1626
static void
1627
eth_sec_end (void *dat)
1628
{
1629
  struct eth_device *eth = dat;
1630
  struct mem_ops ops;
1631
 
1632
  if (!eth->enabled)
1633
    {
1634
      free (eth->rxfile);
1635
      free (eth->txfile);
1636 434 jeremybenn
      free (eth->tap_dev);
1637 19 jeremybenn
      free (eth);
1638
      return;
1639
    }
1640
 
1641
  memset (&ops, 0, sizeof (struct mem_ops));
1642
 
1643
  ops.readfunc32 = eth_read32;
1644
  ops.writefunc32 = eth_write32;
1645
  ops.read_dat32 = dat;
1646
  ops.write_dat32 = dat;
1647
 
1648
  /* FIXME: Correct delay? */
1649
  ops.delayr = 2;
1650
  ops.delayw = 2;
1651
  reg_mem_area (eth->baseaddr, ETH_ADDR_SPACE, 0, &ops);
1652
  reg_sim_stat (eth_status, dat);
1653
  reg_sim_reset (eth_reset, dat);
1654
}
1655
 
1656
 
1657
/*---------------------------------------------------------------------------*/
1658
/*!Register a new Ethernet configuration                                     */
1659
/*---------------------------------------------------------------------------*/
1660
void
1661
reg_ethernet_sec ()
1662
{
1663
  struct config_section *sec =
1664
    reg_config_sec ("ethernet", eth_sec_start, eth_sec_end);
1665
 
1666 224 jeremybenn
  reg_config_param (sec, "enabled",    PARAMT_INT,  eth_enabled);
1667
  reg_config_param (sec, "baseaddr",   PARAMT_ADDR, eth_baseaddr);
1668
  reg_config_param (sec, "dma",        PARAMT_INT,  eth_dma);
1669
  reg_config_param (sec, "irq",        PARAMT_INT,  eth_irq);
1670 434 jeremybenn
  reg_config_param (sec, "rtx_type",   PARAMT_STR,  eth_rtx_type);
1671 224 jeremybenn
  reg_config_param (sec, "rx_channel", PARAMT_INT,  eth_rx_channel);
1672
  reg_config_param (sec, "tx_channel", PARAMT_INT,  eth_tx_channel);
1673
  reg_config_param (sec, "rxfile",     PARAMT_STR,  eth_rxfile);
1674
  reg_config_param (sec, "txfile",     PARAMT_STR,  eth_txfile);
1675 434 jeremybenn
  reg_config_param (sec, "tap_dev",    PARAMT_STR,  eth_tap_dev);
1676 224 jeremybenn
  reg_config_param (sec, "vapi_id",    PARAMT_INT,  eth_vapi_id);
1677 428 julius
  reg_config_param (sec, "phy_addr",   PARAMT_INT,  eth_phy_addr);
1678 19 jeremybenn
 
1679
}       /* reg_ethernet_sec() */
1680
 

powered by: WebSVN 2.1.0

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