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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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