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

Subversion Repositories openrisc

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

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 443 jeremybenn
   Copyright (C) 2008, 2001 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 443 jeremybenn
 
67
/* Control debug messages */
68 450 jeremybenn
#define ETH_DEBUG 0
69 443 jeremybenn
#ifndef ETH_DEBUG
70
# define ETH_DEBUG  1
71
#endif
72
 
73 451 jeremybenn
/*! Period (clock cycles) for rescheduling Rx and Tx controllers. */
74 457 julius
#define  RTX_RESCHED_PERIOD  10000
75 443 jeremybenn
 
76 450 jeremybenn
/*! MAC address that is always accepted. */
77
static const unsigned char mac_broadcast[ETHER_ADDR_LEN] =
78
  { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
79
 
80 443 jeremybenn
/* -------------------------------------------------------------------------- */
81
/*!Structure describing the Ethernet device                                   */
82
/* -------------------------------------------------------------------------- */
83 19 jeremybenn
struct eth_device
84
{
85 443 jeremybenn
  /* Basic stuff about the device */
86
  int                enabled;           /* Is peripheral enabled */
87
  oraddr_t           baseaddr;          /* Base address in memory */
88
  unsigned long int  base_vapi_id;      /* Start of VAPI ID block */
89 19 jeremybenn
 
90 443 jeremybenn
  /* DMA controller this MAC is connected to, and associated channels */
91 19 jeremybenn
  unsigned dma;
92
  unsigned tx_channel;
93
  unsigned rx_channel;
94
 
95 443 jeremybenn
  /* Details of the hardware */
96
  unsigned char      mac_address[ETHER_ADDR_LEN];  /* Ext HW address */
97
  unsigned long int  phy_addr;          /* Int HW address */
98
  unsigned long int  mac_int;           /* interrupt line number */
99 451 jeremybenn
  int                dummy_crc;         /* Flag indicating if we add CRC */
100 443 jeremybenn
  int                int_line_stat;     /* interrupt line status */
101 19 jeremybenn
 
102 443 jeremybenn
  /* External interface deatils */
103
  int rtx_type;                         /* Type of external i/f: FILE or TAP */
104 19 jeremybenn
 
105 434 jeremybenn
  /* RX and TX file names and handles for FILE type connection. */
106 443 jeremybenn
  char  *rxfile;                        /* Rx filename */
107
  char  *txfile;                        /* Tx filename */
108
  int    txfd;                          /* Rx file handle */
109
  int    rxfd;                          /* Tx file handle */
110 19 jeremybenn
 
111 434 jeremybenn
  /* Info for TAP type connections */
112 443 jeremybenn
  char *tap_dev;                        /* The TAP device */
113
  int   rtx_fd;                         /* TAP device handle */
114 19 jeremybenn
 
115 450 jeremybenn
  /* Indices into the buffer descriptors. */
116
  unsigned long int  tx_bd_index;
117
  unsigned long int  rx_bd_index;
118 19 jeremybenn
 
119
  /* Visible registers */
120
  struct
121
  {
122 443 jeremybenn
    unsigned long int  moder;
123
    unsigned long int  int_source;
124
    unsigned long int  int_mask;
125
    unsigned long int  ipgt;
126
    unsigned long int  ipgr1;
127
    unsigned long int  ipgr2;
128
    unsigned long int  packetlen;
129
    unsigned long int  collconf;
130
    unsigned long int  tx_bd_num;
131
    unsigned long int  controlmoder;
132
    unsigned long int  miimoder;
133
    unsigned long int  miicommand;
134
    unsigned long int  miiaddress;
135
    unsigned long int  miitx_data;
136
    unsigned long int  miirx_data;
137
    unsigned long int  miistatus;
138
    unsigned long int  hash0;
139
    unsigned long int  hash1;
140 19 jeremybenn
 
141
    /* Buffer descriptors */
142 443 jeremybenn
    unsigned long int  bd_ram[ETH_BD_SPACE / 4];
143 19 jeremybenn
  } regs;
144
};
145
 
146
 
147 443 jeremybenn
/* -------------------------------------------------------------------------- */
148 450 jeremybenn
/*!Write an Ethernet packet to a FILE interface.
149 443 jeremybenn
 
150 450 jeremybenn
   This writes a single Ethernet packet to a FILE interface. The format is to
151
   write the length, then the data.
152 443 jeremybenn
 
153 450 jeremybenn
   @param[in] eth     Pointer to the relevant Ethernet data structure.
154
   @param[in] buf     Where to get the data.
155
   @param[in] length  Length of data to write.
156 443 jeremybenn
 
157 450 jeremybenn
   @return  The length if successful, a negative value otherwise.             */
158
/* -------------------------------------------------------------------------- */
159
static ssize_t
160
eth_write_file_packet (struct eth_device *eth,
161
                       unsigned char     *buf,
162
                       unsigned long int  length)
163
{
164
  ssize_t  nwritten;
165 443 jeremybenn
 
166 450 jeremybenn
  /* Write length to file. */
167
  nwritten = write (eth->txfd, &(length), sizeof (length));
168
  if (nwritten != sizeof (length))
169
    {
170
      fprintf (stderr, "ERROR: Failed to write Ethernet packet length: %s.\n",
171
               strerror (errno));
172
      return  -1;
173
    }
174 443 jeremybenn
 
175 450 jeremybenn
  /* write data to file */
176
  nwritten = write (eth->txfd, buf, length);
177
  if (nwritten != length)
178
    {
179
      fprintf (stderr, "ERROR: Failed to write Ethernet packet data: %s.\n",
180
               strerror (errno));
181
      return  -1;
182
    }
183 443 jeremybenn
 
184 450 jeremybenn
  return  nwritten;
185
 
186
}       /* eth_write_file_packet () */
187
 
188
 
189 443 jeremybenn
/* -------------------------------------------------------------------------- */
190 450 jeremybenn
/*!Write an Ethernet packet to a TAP interface.
191
 
192
   This writes a single Ethernet packet to a TAP interface.
193
 
194
   @param[in] eth     Pointer to the relevant Ethernet data structure.
195
   @param[in] buf     Where to get the data.
196
   @param[in] length  Length of data to write.
197
 
198
   @return  The length if successful, a negative value otherwise.             */
199
/* -------------------------------------------------------------------------- */
200
static ssize_t
201
eth_write_tap_packet (struct eth_device *eth,
202
                      unsigned char     *buf,
203
                      unsigned long int  length)
204 443 jeremybenn
{
205 450 jeremybenn
  ssize_t  nwritten;
206 443 jeremybenn
 
207 450 jeremybenn
#if ETH_DEBUG
208
  int  j;
209 443 jeremybenn
 
210 450 jeremybenn
  printf ("Writing TAP\n");
211
  printf ("  packet %d bytes:", (int) length);
212
 
213
  for (j = 0; j < length; j++)
214 443 jeremybenn
    {
215 450 jeremybenn
      if (0 == (j % 16))
216
        {
217
          printf ("\n");
218
        }
219
      else if (0 == (j % 8))
220
        {
221
          printf (" ");
222
        }
223
 
224
      printf ("%.2x ", buf[j]);
225
    }
226
 
227
  printf("\nend packet:\n");
228
#endif    
229 443 jeremybenn
 
230 450 jeremybenn
  /* Write the data to the TAP */
231
  nwritten = write (eth->rtx_fd, buf, length);
232
  if (nwritten != length)
233
    {
234
      fprintf (stderr, "ERROR: Failed to write Ethernet packet data: %s.\n",
235
               strerror (errno));
236
      return  -1;
237
    }
238 443 jeremybenn
 
239 450 jeremybenn
  return  nwritten;
240 443 jeremybenn
 
241 450 jeremybenn
}       /* eth_write_tap_packet () */
242 443 jeremybenn
 
243
 
244 450 jeremybenn
/* -------------------------------------------------------------------------- */
245
/*!Write an Ethernet packet.
246 443 jeremybenn
 
247 450 jeremybenn
   This writes a single Ethernet packet to the outside world from the supplied
248
   buffer. It deals with the different types of external interface.
249 443 jeremybenn
 
250 450 jeremybenn
   @param[in] eth     Pointer to the relevant Ethernet data structure.
251
   @param[in] buf     Where to get the data.
252
   @param[in] length  Length of data to write.
253 443 jeremybenn
 
254 450 jeremybenn
   @return  The length if successful, zero if no packet was available,
255
            a negative value otherwise.                                       */
256
/* -------------------------------------------------------------------------- */
257
static ssize_t
258
eth_write_packet (struct eth_device *eth,
259
                  unsigned char     *buf,
260
                  ssize_t            length)
261
{
262
  /* Send packet according to interface type. */
263
  switch (eth->rtx_type)
264
    {
265
    case ETH_RTX_FILE: return  eth_write_file_packet (eth, buf, length);
266
    case ETH_RTX_TAP:  return  eth_write_tap_packet (eth, buf, length);
267 443 jeremybenn
 
268 450 jeremybenn
    default:
269
      fprintf (stderr, "Unknown Ethernet write interface: ignored.\n");
270
      return  (ssize_t) -1;
271
    }
272
}       /* eth_write_packet () */
273 443 jeremybenn
 
274
 
275 450 jeremybenn
/* -------------------------------------------------------------------------- */
276
/*!Flush a Tx buffer descriptor to the outside world.
277 19 jeremybenn
 
278 450 jeremybenn
   We know the buffer descriptor is full, so write it to the appropriate
279
   outside interface.
280
 
281
   @param[in] eth  The Ethernet data structure.                               */
282
/* -------------------------------------------------------------------------- */
283
static void
284
eth_flush_bd (struct eth_device *eth)
285
{
286
  /* First word of BD is flags and length, second is pointer to buffer */
287
  unsigned long int  bd_info = eth->regs.bd_ram[eth->tx_bd_index];
288
  unsigned long int  bd_addr = eth->regs.bd_ram[eth->tx_bd_index + 1];
289
  unsigned char      buf[ETH_MAXPL];
290
  long int           packet_length;
291
  long int           bytes_sent;
292
 
293
  /* Get the packet length */
294
  packet_length = GET_FIELD (bd_info, ETH_TX_BD, LENGTH);
295
 
296
  /* Clear error status bits and retry count. */
297
  CLEAR_FLAG (bd_info, ETH_TX_BD, DEFER);
298
  CLEAR_FLAG (bd_info, ETH_TX_BD, COLLISION);
299
  CLEAR_FLAG (bd_info, ETH_TX_BD, RETRANSMIT);
300
  CLEAR_FLAG (bd_info, ETH_TX_BD, UNDERRUN);
301
  CLEAR_FLAG (bd_info, ETH_TX_BD, NO_CARRIER);
302
 
303
  SET_FIELD (bd_info, ETH_TX_BD, RETRY, 0);
304
 
305
  /* Copy data from buffer descriptor address into our local buf. */
306
  for (bytes_sent = 0; bytes_sent < packet_length; bytes_sent +=4)
307
    {
308
      unsigned long int  read_word =
309
        eval_direct32 (bytes_sent + bd_addr, 0, 0);
310
 
311
      buf[bytes_sent]     = (unsigned char) (read_word >> 24);
312
      buf[bytes_sent + 1] = (unsigned char) (read_word >> 16);
313
      buf[bytes_sent + 2] = (unsigned char) (read_word >> 8);
314
      buf[bytes_sent + 3] = (unsigned char) (read_word);
315
    }
316
 
317
  /* Send packet according to interface type and set BD status. If we didn't
318
     write the whole packet, then we retry. */
319
  if (eth_write_packet (eth, buf, packet_length) == packet_length)
320
    {
321
      CLEAR_FLAG (bd_info, ETH_TX_BD, READY);
322
      SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
323
    }
324
  else
325
    {
326
      /* Does this retry mechanism really work? */
327
      CLEAR_FLAG (bd_info, ETH_TX_BD, READY);
328
      CLEAR_FLAG (bd_info, ETH_TX_BD, COLLISION);
329
      SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
330 443 jeremybenn
#if ETH_DEBUG
331 450 jeremybenn
      printf ("Transmit retry request.\n");
332 443 jeremybenn
#endif
333 450 jeremybenn
    }
334 19 jeremybenn
 
335 450 jeremybenn
  /* Update the flags in the buffer descriptor */
336
  eth->regs.bd_ram[eth->tx_bd_index] = bd_info;
337 19 jeremybenn
 
338 450 jeremybenn
  /* Generate interrupt to indicate transfer complete, under the
339
     following criteria all being met:
340
     - either INT_MASK flag for Tx (OK or error) is set
341
     - the bugger descriptor has its IRQ flag set
342
     - there is no interrupt in progress.
343 437 julius
 
344 450 jeremybenn
     @todo We ought to warn if we get here and fail to set an IRQ. */
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
      TEST_FLAG (bd_info, ETH_TX_BD, IRQ))
348
    {
349
      if (eth->int_line_stat)
350 19 jeremybenn
        {
351 450 jeremybenn
          fprintf (stderr, "Warning: Interrupt active during Tx.\n");
352
        }
353
      else
354
        {
355 437 julius
#if ETH_DEBUG
356 443 jeremybenn
          printf ("TRANSMIT interrupt\n");
357 437 julius
#endif
358 443 jeremybenn
          report_interrupt (eth->mac_int);
359
          eth->int_line_stat = 1;
360 19 jeremybenn
        }
361 450 jeremybenn
    }
362 19 jeremybenn
 
363 450 jeremybenn
  /* Advance to next BD, wrapping around if appropriate. */
364
  if (TEST_FLAG (bd_info, ETH_TX_BD, WRAP) ||
365
      eth->tx_bd_index >= ((eth->regs.tx_bd_num - 1) * 2))
366
    {
367
      eth->tx_bd_index = 0;
368 19 jeremybenn
    }
369 450 jeremybenn
  else
370
    {
371
      eth->tx_bd_index += 2;
372
    }
373
}       /* eth_flush_bd () */
374 19 jeremybenn
 
375
 
376 443 jeremybenn
/* -------------------------------------------------------------------------- */
377 450 jeremybenn
/*!Tx clock function.
378 443 jeremybenn
 
379 450 jeremybenn
   Responsible for starting and completing any TX actions.
380 443 jeremybenn
 
381
   The original version had 4 states, which allowed modeling the transfer of
382 450 jeremybenn
   data one byte per cycle.  For now we use only the one state for
383
   efficiency. When we find something in a buffer descriptor, we transmit
384
   it.
385 443 jeremybenn
 
386 450 jeremybenn
   We reschedule every cycle. There is no point in trying to do anything if
387
   there is an interrupt still being processed by the core.
388 443 jeremybenn
 
389
   @todo We should eventually reinstate the one byte per cycle transfer.
390
 
391
   @param[in] dat  The Ethernet data structure, passed as a void pointer.    */
392
/* -------------------------------------------------------------------------- */
393 19 jeremybenn
static void
394 450 jeremybenn
eth_controller_tx_clock (void *dat)
395 19 jeremybenn
{
396
  struct eth_device *eth = dat;
397
 
398 450 jeremybenn
  /* Only do anything if there is not an interrupt outstanding. */
399
  if (!eth->int_line_stat)
400 19 jeremybenn
    {
401 450 jeremybenn
      /* First word of BD is flags. If we have a buffer ready, get it and
402
         transmit it. */
403
      if (TEST_FLAG (eth->regs.bd_ram[eth->tx_bd_index], ETH_TX_BD, READY))
404
        {
405
          eth_flush_bd (eth);
406
        }
407
    }
408 19 jeremybenn
 
409 450 jeremybenn
  /* Wake up again after 1 ticks (was 10, changed by Julius). */
410 451 jeremybenn
  SCHED_ADD (eth_controller_tx_clock, dat, RTX_RESCHED_PERIOD);
411 434 jeremybenn
 
412 450 jeremybenn
}       /* eth_controller_tx_clock () */
413 19 jeremybenn
 
414
 
415 450 jeremybenn
/* -------------------------------------------------------------------------- */
416
/*!Read an Ethernet packet from a FILE interface.
417 437 julius
 
418 450 jeremybenn
   This reads a single Ethernet packet from the outside world via a FILE
419
   interface.
420 434 jeremybenn
 
421 450 jeremybenn
   The format is 4 bytes of packet length, followed by the packet data.
422 434 jeremybenn
 
423 450 jeremybenn
   @param[in]  eth  Pointer to the relevant Ethernet data structure
424
   @param[out] buf  Where to put the data
425 434 jeremybenn
 
426 450 jeremybenn
   @return  The length if successful, zero if no packet was available
427
            (i.e. EOF), a negative value otherwise.                           */
428
/* -------------------------------------------------------------------------- */
429
static ssize_t
430
eth_read_file_packet (struct eth_device *eth,
431
                      unsigned char     *buf)
432
{
433
  ssize_t  packet_length;
434
  ssize_t  nread;
435 434 jeremybenn
 
436 450 jeremybenn
  /* Read packet length. We may be at EOF. */
437
  nread = read (eth->rxfd, &(packet_length), sizeof (packet_length));
438 19 jeremybenn
 
439 450 jeremybenn
  if (0 == nread)
440
    {
441
      return  0;                 /* No more packets */
442
    }
443
  else if (nread < sizeof (packet_length))
444
    {
445
      fprintf (stderr, "ERROR: Failed to read length from file.\n");
446
      return  -1;
447
    }
448 457 julius
 
449 450 jeremybenn
  /* Packet must be big enough to hold a header */
450
  if (packet_length < ETHER_HDR_LEN)
451
    {
452
      fprintf (stderr, "Warning: Ethernet packet length %zd too small.\n",
453
               packet_length);
454
      return  -1;
455
    }
456 19 jeremybenn
 
457 450 jeremybenn
  /* Read the packet proper. */
458
  nread = read (eth->rxfd, buf, packet_length);
459 19 jeremybenn
 
460 450 jeremybenn
  if (nread != packet_length)
461
    {
462
      fprintf (stderr, "ERROR: Failed to read packet from file.\n");
463
      return  -1;
464
    }
465 19 jeremybenn
 
466 450 jeremybenn
  return  packet_length;
467 19 jeremybenn
 
468 450 jeremybenn
}       /* eth_read_file_packet () */
469 19 jeremybenn
 
470
 
471 450 jeremybenn
/* -------------------------------------------------------------------------- */
472
/*!Read an Ethernet packet from a FILE interface.
473 19 jeremybenn
 
474 450 jeremybenn
   This reads a single Ethernet packet from the outside world via a TAP
475
   interface.
476 19 jeremybenn
 
477 450 jeremybenn
   A complete packet is always read, so its length (minus CRC) is the amount
478
   read.
479
 
480
   @param[in]  eth  Pointer to the relevant Ethernet data structure
481
   @param[out] buf  Where to put the data
482
 
483
   @return  The length if successful, zero if no packet was available,
484
            a negative value otherwise.                                       */
485
/* -------------------------------------------------------------------------- */
486
static ssize_t
487
eth_read_tap_packet (struct eth_device *eth,
488
                     unsigned char     *buf)
489
{
490
  struct pollfd  fds[1];
491
  int            n;
492
  ssize_t        packet_length;
493
 
494
  /* Poll to see if there is data to read */
495
  fds[0].fd     = eth->rtx_fd;
496
  fds[0].events = POLLIN;
497 434 jeremybenn
 
498 450 jeremybenn
  n = poll (fds, 1, 0);
499
  if (n < 0)
500
    {
501
      fprintf (stderr, "Warning: Poll for TAP receive failed %s: ignored.\n",
502
               strerror (errno));
503
      return  -1;
504
    }
505
  else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
506
    {
507
      /* Data to be read from TAP */
508
      packet_length = read (eth->rtx_fd, buf, ETH_MAXPL);
509 437 julius
#if ETH_DEBUG
510 450 jeremybenn
      printf ("%d bytes read from TAP.\n", (int) packet_length);
511 437 julius
#endif
512 450 jeremybenn
      if (packet_length < 0)
513
        {
514
          fprintf (stderr, "Warning: Read of RXTATE_RECV failed: %s.\n",
515
                   strerror (errno));
516
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXE);
517
 
518
          /* Signal interrupt if enabled, and no interrupt currently in
519
             progress. */
520
          if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXE_M) &&
521
              !eth->int_line_stat)
522
            {
523 437 julius
#if ETH_DEBUG
524 450 jeremybenn
              printf ("Ethernet failed receive interrupt\n");
525 437 julius
#endif
526 450 jeremybenn
              report_interrupt (eth->mac_int);
527
              eth->int_line_stat = 1;
528
            }
529
        }
530
 
531
      return  packet_length;
532
    }
533
  else
534
    {
535
      return  0;                 /* No packet */
536
    }
537
}       /* eth_read_tap_packet () */
538 434 jeremybenn
 
539 437 julius
 
540 450 jeremybenn
/* -------------------------------------------------------------------------- */
541
/*!Read an Ethernet packet.
542 434 jeremybenn
 
543 450 jeremybenn
   This reads a single Ethernet packet from the outside world into the
544
   supplied buffer. It deals with the different types of external interface.
545 19 jeremybenn
 
546 450 jeremybenn
   @param[in]  eth  Pointer to the relevant Ethernet data structure
547
   @param[out] buf  Where to put the data
548 436 julius
 
549 450 jeremybenn
   @return  The length if successful, zero if no packet was available,
550
            a negative value otherwise.                                       */
551
/* -------------------------------------------------------------------------- */
552
static ssize_t
553
eth_read_packet (struct eth_device *eth,
554
                 unsigned char     *buf)
555
{
556
  switch (eth->rtx_type)
557
    {
558
    case ETH_RTX_FILE: return  eth_read_file_packet (eth, buf);
559
    case ETH_RTX_TAP:  return  eth_read_tap_packet (eth, buf);
560 19 jeremybenn
 
561 450 jeremybenn
    default:
562
      fprintf (stderr, "Unknown Ethernet read interface: ignored.\n");
563
      return  (ssize_t) -1;
564
    }
565
}       /* eth_read_packet () */
566 19 jeremybenn
 
567
 
568 450 jeremybenn
/* -------------------------------------------------------------------------- */
569
/*!Fill a buffer descriptor
570
 
571
   A buffer descriptor is empty. Attempt to fill it from the outside world.
572
 
573
   @param[in] eth  The Ethernet data structure, passed as a void pointer.    */
574
/* -------------------------------------------------------------------------- */
575
static void
576
eth_fill_bd (struct eth_device *eth)
577
{
578
 
579
  /* First word of BD is flags and length, second is pointer to buffer */
580
  unsigned long int  bd_info = eth->regs.bd_ram[eth->rx_bd_index];
581
  unsigned long int  bd_addr = eth->regs.bd_ram[eth->rx_bd_index + 1];
582
 
583
  long int           packet_length;
584
  long int           bytes_read;
585
  unsigned char      buf[ETH_MAXPL];
586
 
587
  /* Clear various status bits */
588
  CLEAR_FLAG (bd_info, ETH_RX_BD, MISS);
589
  CLEAR_FLAG (bd_info, ETH_RX_BD, INVALID);
590
  CLEAR_FLAG (bd_info, ETH_RX_BD, DRIBBLE);
591
  CLEAR_FLAG (bd_info, ETH_RX_BD, UVERRUN);
592
  CLEAR_FLAG (bd_info, ETH_RX_BD, COLLISION);
593
  CLEAR_FLAG (bd_info, ETH_RX_BD, TOOBIG);
594
  CLEAR_FLAG (bd_info, ETH_RX_BD, TOOSHORT);
595
 
596
  /* Loopback is permitted. We believe that Linux never uses it, so we'll
597
     note the attempt and ignore.
598
 
599
     @todo We should support this. */
600
  if (TEST_FLAG (eth->regs.moder, ETH_MODER, LOOPBCK))
601
    {
602
      PRINTF ("Ethernet loopback requested.\n");
603
      fprintf (stderr, "ERROR: Loopback not supported. Ignored.\n");
604
    }
605
 
606
  packet_length = eth_read_packet (eth, buf);
607
  if (packet_length <= 0)
608
    {
609
      /* Empty packet or error. No more to do here. */
610
      return;
611
    }
612
 
613
/* Got a packet successfully. If not promiscuous mode, check the destination
614
   address is meant for us. */
615
  if (!TEST_FLAG (eth->regs.moder, ETH_MODER, PRO))
616
    {
617
      if (TEST_FLAG (eth->regs.moder, ETH_MODER, IAM))
618
        {
619
          /* There is little documentation of how IAM is supposed to work. It
620
             seems that some mapping function (not defined) maps the address
621
             down to a number in the range 0-63. If that bit is set in
622
             HASH0/HASH1 registers, the packet is accepted. */
623
          fprintf (stderr, "Warning: Individual Address Mode ignored.\n");
624 19 jeremybenn
        }
625 450 jeremybenn
 
626
      /* Check for HW address match. */
627
      if ((0 != bcmp (eth->mac_address, buf, ETHER_ADDR_LEN)) &&
628
          (0 != bcmp (mac_broadcast,    buf, ETHER_ADDR_LEN)))
629
        {
630
#if ETH_DEBUG           
631
          printf ("packet for %.2x:%.2x:%.2x:%.2x:%.2x:%.2x ignored.\n",
632
                  buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
633
#endif
634
          /* Not for us. No more to do here. */
635
          return;
636
        }
637
    }
638 19 jeremybenn
 
639 450 jeremybenn
  /* Transfer the buffer into the BD. */
640 437 julius
#if ETH_DEBUG
641 450 jeremybenn
  printf ("writing to Rx BD%d: %d bytes @ 0x%.8x\n",
642
          (int) eth->rx_bd_index / 2,  (int) packet_length,
643
          (unsigned int)bd_addr);
644 437 julius
#endif
645 450 jeremybenn
 
646
  for (bytes_read = 0; bytes_read < packet_length; bytes_read +=4)
647
    {
648
      unsigned long int  send_word =
649
        ((unsigned long) buf[bytes_read]     << 24) |
650
        ((unsigned long) buf[bytes_read + 1] << 16) |
651
        ((unsigned long) buf[bytes_read + 2] <<  8) |
652
        ((unsigned long) buf[bytes_read + 3]      );
653
      set_direct32 (bd_addr + bytes_read, send_word, 0, 0);
654
    }
655
 
656
#if ETH_DEBUG
657
  printf("BD filled with 0x%08lx bytes.\n", bytes_read);
658
#endif
659
 
660
  /* Write result to BD.
661 451 jeremybenn
 
662
     The OpenRISC MAC hardware passes on the CRC (which it should not). The
663
     Linux drivers have been written to expect a value (which they ignore). So
664
     for consistency, we pretend the length is 4 bytes longer.
665
 
666
     This is now controlled by a configuration parameter, dummy_crc. For
667
     backwards compatibility, it defaults to TRUE. */
668
  SET_FIELD (bd_info, ETH_RX_BD, LENGTH,
669
             packet_length + (eth->dummy_crc ? 4 : 0));
670 450 jeremybenn
  CLEAR_FLAG (bd_info, ETH_RX_BD, READY);
671
  SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
672
 
673
  eth->regs.bd_ram[eth->rx_bd_index] = bd_info;
674
 
675
  /* Advance to next BD. The Rx BDs start after the Tx BDs. */
676
  if (TEST_FLAG (bd_info, ETH_RX_BD, WRAP) ||
677
      (eth->rx_bd_index >= ETH_BD_COUNT))
678
    {
679
      eth->rx_bd_index = eth->regs.tx_bd_num * 2;
680
    }
681
  else
682
    {
683
      eth->rx_bd_index += 2;
684
    }
685
 
686
  /* Raise an interrupt if necessary. */
687
  if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXB_M) &&
688
      TEST_FLAG (bd_info, ETH_RX_BD, IRQ))
689
    {
690
      if (eth->int_line_stat)
691
        {
692
          fprintf (stderr, "Warning: Interrupt active during Rx.\n");
693 436 julius
        }
694 450 jeremybenn
      else
695
        {
696 437 julius
#if ETH_DEBUG
697 450 jeremybenn
          printf ("Rx successful receive interrupt\n");
698 437 julius
#endif
699 450 jeremybenn
          report_interrupt (eth->mac_int);
700
          eth->int_line_stat = 1;
701
        }
702
    }
703
}       /* eth_fill_bd () */
704 19 jeremybenn
 
705
 
706 450 jeremybenn
/* -------------------------------------------------------------------------- */
707 451 jeremybenn
/*!Ignore a packet from the TAP interface.
708 437 julius
 
709 450 jeremybenn
   We don't have a BD ready, so any packets waiting should be thrown away.
710
 
711 451 jeremybenn
   @param[in] eth  The Ethernet data structure.
712
 
713
   @return  1 (TRUE) if more or more packets were discarded, zero otherwise.  */
714 450 jeremybenn
/* -------------------------------------------------------------------------- */
715 451 jeremybenn
static int
716
eth_ignore_tap_packets (struct eth_device *eth)
717 450 jeremybenn
{
718 451 jeremybenn
  int  result = 0;
719
  int  n;
720
 
721
  /* Read packets until there are none left. */
722
  do
723
    {
724
      struct pollfd  fds[1];
725 450 jeremybenn
 
726 451 jeremybenn
      /* Poll to see if there is anything to be read. */
727
      fds[0].fd     = eth->rtx_fd;
728
      fds[0].events = POLLIN;
729
 
730
      n = poll (fds, 1, 0);
731
      if (n < 0)
732 450 jeremybenn
        {
733 451 jeremybenn
          /* Give up with a warning if poll fails */
734
          fprintf (stderr,
735
                   "Warning: Poll error while emptying TAP: %s: ignored.\n",
736
                   strerror (errno));
737
          return  result;
738
        }
739
      else if ((n > 0) && ((fds[0].revents & POLLIN) == POLLIN))
740
        {
741
          unsigned char  buf[ETH_MAXPL];
742
          ssize_t        nread = eth_read_packet (eth, buf);
743
 
744
          if (nread < 0)
745 19 jeremybenn
            {
746 451 jeremybenn
              /* Give up with a warning if read fails */
747
              fprintf (stderr,
748
                       "Warning: Read of when Ethernet busy failed %s.\n",
749
                       strerror (errno));
750
              return  result;
751 450 jeremybenn
            }
752 451 jeremybenn
          else if (nread > 0)
753 450 jeremybenn
            {
754 451 jeremybenn
              /* Record that a packet was thrown away. */
755
              result = 1;
756 437 julius
#if ETH_DEBUG
757 451 jeremybenn
              printf ("Ethernet discarding %d bytes from TAP while BD full.\n",
758
                      nread);
759 437 julius
#endif
760 19 jeremybenn
            }
761 450 jeremybenn
        }
762
    }
763 451 jeremybenn
  while (n > 0);
764 19 jeremybenn
 
765 451 jeremybenn
  return  result;
766 450 jeremybenn
 
767 451 jeremybenn
}       /* eth_ignore_tap_packets () */
768
 
769
 
770 450 jeremybenn
/* -------------------------------------------------------------------------- */
771
/*!Rx clock function.
772
 
773
   Responsible for starting and completing any RX actions.
774
 
775
   The original version had 4 states, which allowed modeling the transfer of
776
   data one byte per cycle.  For now we use only the one state for
777
   efficiency. When the buffer is empty, we fill it from the external world.
778
 
779
   We schedule to wake up again each cycle. This means we will get called when
780
   the core is still processing the previous interrupt. To avoid races, we do
781
   nothing until the interrupt is cleared.
782
 
783
   @todo We should eventually reinstate the one byte per cycle transfer.
784
 
785
   @param[in] dat  The Ethernet data structure, passed as a void pointer.    */
786
/* -------------------------------------------------------------------------- */
787
static void
788
eth_controller_rx_clock (void *dat)
789
{
790
  struct eth_device *eth = dat;
791
 
792
  /* Only do anything if there is not an interrupt outstanding. */
793
  if (!eth->int_line_stat)
794
    {
795
      /* First word of the BD is flags, where we can test if it's ready. */
796
      if (TEST_FLAG (eth->regs.bd_ram[eth->rx_bd_index], ETH_RX_BD, READY))
797
        {
798
          /* The BD is empty, so we try to fill it with data from the outside
799
             world. */
800
          eth_fill_bd (eth);    /* BD ready to be filled. */
801 19 jeremybenn
        }
802 450 jeremybenn
      else if ((TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN)) &&
803
               (ETH_RTX_FILE == eth->rtx_type))
804
        {
805
          /* The BD is full, Rx is enabled and we are reading from an external
806
             TAP interface. We can't take any more, so we'll throw oustanding
807
             input packets on the floor.
808
 
809
             @note We don't do this for file I/O, since it would discard
810
             everything immediately! */
811 451 jeremybenn
          if (eth_ignore_tap_packets (eth))
812
            {
813
              /* A packet has been thrown away, so mark the INT_SOURCE
814
                 register accordingly. */
815
              SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
816
 
817
              /* Raise an interrupt if necessary. */
818
              if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, BUSY_M))
819
                {
820
                  if (eth->int_line_stat)
821
                    {
822
                      fprintf (stderr,
823
                               "Warning: Interrupt active during ignore.\n");
824
                    }
825
                  else
826
                    {
827
#if ETH_DEBUG
828
                      printf ("Ethernet Rx BUSY interrupt\n");
829
#endif
830
                      report_interrupt (eth->mac_int);
831
                      eth->int_line_stat = 1;
832
                    }
833
                }
834
            }
835 450 jeremybenn
        }
836 19 jeremybenn
    }
837
 
838 450 jeremybenn
  /* Whatever happens, we reschedule a wake up in the future. This used to be
839
     every 10 ticks, but now it is very 1 tick. */
840 451 jeremybenn
  SCHED_ADD (eth_controller_rx_clock, dat, RTX_RESCHED_PERIOD);
841 19 jeremybenn
 
842 450 jeremybenn
}       /* eth_controller_rx_clock () */
843
 
844
 
845 451 jeremybenn
/* -------------------------------------------------------------------------- */
846
/*!VAPI connection to outside.
847 19 jeremybenn
 
848 451 jeremybenn
   Used for remote testing of the interface. Currently does nothing.
849 19 jeremybenn
 
850 451 jeremybenn
   @param[in] id  The VAPI ID to use.
851
   @param[in] data  Any data associated (unused here).
852
   @param[in] dat   The Ethernet data structure, cast to a void pointer.      */
853
/* -------------------------------------------------------------------------- */
854 443 jeremybenn
static void
855 451 jeremybenn
eth_vapi_read (unsigned long int  id,
856
               unsigned long int  data,
857
               void              *dat)
858 19 jeremybenn
{
859 451 jeremybenn
  unsigned long int  which;
860 443 jeremybenn
  struct eth_device *eth = dat;
861 19 jeremybenn
 
862 443 jeremybenn
  which = id - eth->base_vapi_id;
863
 
864
  if (!eth)
865 19 jeremybenn
    {
866 443 jeremybenn
      return;
867 19 jeremybenn
    }
868
 
869 443 jeremybenn
  switch (which)
870
    {
871
    case ETH_VAPI_DATA:
872
      break;
873
    case ETH_VAPI_CTRL:
874
      break;
875
    }
876 19 jeremybenn
}
877
 
878 451 jeremybenn
 
879 434 jeremybenn
/* -------------------------------------------------------------------------- */
880 451 jeremybenn
/*!Print register values on stdout
881 434 jeremybenn
 
882
   @param[in] dat  The Ethernet interface data structure.                     */
883
/* -------------------------------------------------------------------------- */
884 19 jeremybenn
static void
885 451 jeremybenn
eth_status (void *dat)
886 19 jeremybenn
{
887
  struct eth_device *eth = dat;
888
 
889 451 jeremybenn
  PRINTF ("\nEthernet MAC at 0x%" PRIxADDR ":\n", eth->baseaddr);
890
  PRINTF ("MODER        : 0x%08lX\n", eth->regs.moder);
891
  PRINTF ("INT_SOURCE   : 0x%08lX\n", eth->regs.int_source);
892
  PRINTF ("INT_MASK     : 0x%08lX\n", eth->regs.int_mask);
893
  PRINTF ("IPGT         : 0x%08lX\n", eth->regs.ipgt);
894
  PRINTF ("IPGR1        : 0x%08lX\n", eth->regs.ipgr1);
895
  PRINTF ("IPGR2        : 0x%08lX\n", eth->regs.ipgr2);
896
  PRINTF ("PACKETLEN    : 0x%08lX\n", eth->regs.packetlen);
897
  PRINTF ("COLLCONF     : 0x%08lX\n", eth->regs.collconf);
898
  PRINTF ("TX_BD_NUM    : 0x%08lX\n", eth->regs.tx_bd_num);
899
  PRINTF ("CTRLMODER    : 0x%08lX\n", eth->regs.controlmoder);
900
  PRINTF ("MIIMODER     : 0x%08lX\n", eth->regs.miimoder);
901
  PRINTF ("MIICOMMAND   : 0x%08lX\n", eth->regs.miicommand);
902
  PRINTF ("MIIADDRESS   : 0x%08lX\n", eth->regs.miiaddress);
903
  PRINTF ("MIITX_DATA   : 0x%08lX\n", eth->regs.miitx_data);
904
  PRINTF ("MIIRX_DATA   : 0x%08lX\n", eth->regs.miirx_data);
905
  PRINTF ("MIISTATUS    : 0x%08lX\n", eth->regs.miistatus);
906
  PRINTF ("MAC Address  : %02X:%02X:%02X:%02X:%02X:%02X\n",
907
          eth->mac_address[5], eth->mac_address[4], eth->mac_address[3],
908
          eth->mac_address[2], eth->mac_address[1], eth->mac_address[0]);
909
  PRINTF ("HASH0        : 0x%08lX\n", eth->regs.hash0);
910
  PRINTF ("HASH1        : 0x%08lX\n", eth->regs.hash1);
911
 
912
}       /* eth_status () */
913
 
914
 
915
/* -------------------------------------------------------------------------- */
916
/*!Open the external file interface to the Ethernet
917
 
918
   The data is represented by an input and an output file.
919
 
920
   @param[in] eth  The Ethernet interface data structure.                     */
921
/* -------------------------------------------------------------------------- */
922
static void
923
eth_open_file_if (struct eth_device *eth)
924
{
925
  /* (Re-)open TX/RX files */
926
  if (eth->rxfd >= 0)
927
    {
928
      close (eth->rxfd);
929
    }
930
 
931
  if (eth->txfd >= 0)
932
    {
933
      close (eth->txfd);
934
    }
935
 
936
  eth->rxfd = -1;
937
  eth->txfd = -1;
938
 
939
  eth->rxfd = open (eth->rxfile, O_RDONLY);
940
  if (eth->rxfd < 0)
941
    {
942
      fprintf (stderr, "Warning: Cannot open Ethernet RX file \"%s\": %s\n",
943
               eth->rxfile, strerror (errno));
944
    }
945
 
946
  eth->txfd = open (eth->txfile,
947
#if defined(O_SYNC)             /* BSD/MacOS X doesn't know about O_SYNC */
948
                    O_SYNC |
949 437 julius
#endif
950 451 jeremybenn
                    O_RDWR | O_CREAT | O_APPEND,
951
                    S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
952
  if (eth->txfd < 0)
953
    {
954
      fprintf (stderr, "Warning: Cannot open Ethernet TX file \"%s\": %s\n",
955
               eth->txfile, strerror (errno));
956
    }
957
}       /* eth_open_file_if () */
958 434 jeremybenn
 
959 451 jeremybenn
 
960
/* -------------------------------------------------------------------------- */
961
/*!Open the external TAP interface to the Ethernet
962
 
963
   Packets are transferred over a TAP/TUN interface. We assume a persistent
964
   tap interface has been set up and is owned by the user, so they can open
965
   and manipulate it. See the User Guide for details of setting this up.
966
 
967
   @todo We don't flush the TAP interface. Should we?
968
 
969
   @param[in] eth  The Ethernet interface data structure.                     */
970
/* -------------------------------------------------------------------------- */
971
static void
972
eth_open_tap_if (struct eth_device *eth)
973
{
974
  struct ifreq       ifr;
975
 
976
  /* We don't support re-opening. If it's open, it stays open. */
977
  if (eth->rtx_fd >= 0)
978 19 jeremybenn
    {
979 434 jeremybenn
      return;
980
    }
981
 
982 451 jeremybenn
  /* Open the TUN/TAP device */
983
  eth->rtx_fd = open ("/dev/net/tun", O_RDWR);
984
  if( eth->rtx_fd < 0 )
985 434 jeremybenn
    {
986 451 jeremybenn
      fprintf (stderr, "Warning: Failed to open TUN/TAP device: %s\n",
987
               strerror (errno));
988
      eth->rtx_fd = -1;
989
      return;
990
    }
991 434 jeremybenn
 
992 451 jeremybenn
  /* Turn it into a specific TAP device. If we haven't specified a specific
993
     (persistent) device, one will be created, but that requires superuser, or
994
     at least CAP_NET_ADMIN capabilities. */
995
  memset (&ifr, 0, sizeof(ifr));
996
  ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
997
  strncpy (ifr.ifr_name, eth->tap_dev, IFNAMSIZ);
998 19 jeremybenn
 
999 451 jeremybenn
  if (ioctl (eth->rtx_fd, TUNSETIFF, (void *) &ifr) < 0)
1000
    {
1001
      fprintf (stderr, "Warning: Failed to set TAP device: %s\n",
1002
               strerror (errno));
1003
      close (eth->rtx_fd);
1004
      eth->rtx_fd = -1;
1005
      return;
1006
    }
1007
#if ETH_DEBUG
1008
      PRINTF ("Opened TAP %s\n", ifr.ifr_name);
1009
#endif
1010
}       /* eth_open_tap_if () */
1011 19 jeremybenn
 
1012
 
1013 451 jeremybenn
/* -------------------------------------------------------------------------- */
1014
/*!Open the external interface to the Ethernet
1015 19 jeremybenn
 
1016 451 jeremybenn
   Calls the appropriate function for the interface type.
1017 19 jeremybenn
 
1018 451 jeremybenn
   @param[in] eth  The Ethernet interface data structure.                     */
1019
/* -------------------------------------------------------------------------- */
1020
static void
1021
eth_open_if (struct eth_device *eth)
1022
{
1023
  switch (eth->rtx_type)
1024
    {
1025
    case ETH_RTX_FILE: eth_open_file_if (eth); break;
1026
    case ETH_RTX_TAP:  eth_open_tap_if (eth);  break;
1027
 
1028
    default:
1029
      fprintf (stderr, "Unknown Ethernet interface: ignored.\n");
1030 434 jeremybenn
      break;
1031 451 jeremybenn
    }
1032
}       /* eth_open_if () */
1033 19 jeremybenn
 
1034
 
1035 451 jeremybenn
/* -------------------------------------------------------------------------- */
1036
/*!Reset the Ethernet.
1037 19 jeremybenn
 
1038 451 jeremybenn
   Open the correct type of simulation interface to the outside world.
1039 19 jeremybenn
 
1040 451 jeremybenn
   Initialize all registers to default and places devices in memory address
1041
   space.
1042 19 jeremybenn
 
1043 451 jeremybenn
   @param[in] dat  The Ethernet interface data structure.                     */
1044
/* -------------------------------------------------------------------------- */
1045
static void
1046
eth_reset (void *dat)
1047
{
1048
  struct eth_device *eth = dat;
1049
 
1050 437 julius
#if ETH_DEBUG
1051 451 jeremybenn
  printf ("Resetting Ethernet\n");
1052 437 julius
#endif
1053 451 jeremybenn
 
1054
  /* Nothing to do if we do not have a base address set, or we are not
1055
     enabled. */
1056
  if (!eth->enabled || (0 == eth->baseaddr))
1057
    {
1058
      return;
1059 19 jeremybenn
    }
1060
 
1061 451 jeremybenn
  eth_open_if (eth);
1062
 
1063 434 jeremybenn
  /* Set registers to default values */
1064
  memset (&(eth->regs), 0, sizeof (eth->regs));
1065 19 jeremybenn
 
1066 451 jeremybenn
  eth->regs.moder     = 0x0000A000;     /* Padding & CRC enabled */
1067
  eth->regs.ipgt      = 0x00000012;     /* Half duplex (matches MODER) */
1068
  eth->regs.ipgr1     = 0x0000000C;     /* Recommended value */
1069
  eth->regs.ipgr2     = 0x00000012;     /* Recommended value */
1070
  eth->regs.packetlen = 0x003C0600;     /* MINFL 60, MAXFL 1,536 bytes */
1071
  eth->regs.collconf  = 0x000F003F;     /* MAXRET 15, COLLVALID 63 */
1072
  eth->regs.tx_bd_num = 0x00000040;     /* Max Tx BD */
1073
  eth->regs.miimoder  = 0x00000064;     /* Send preamble, CLKDIV 100 */
1074 19 jeremybenn
 
1075 450 jeremybenn
  /* Reset TX/RX BD indexes. The Rx BD indexes start after the Tx BD indexes. */
1076
  eth->tx_bd_index = 0;
1077
  eth->rx_bd_index = eth->regs.tx_bd_num * 2;
1078 434 jeremybenn
 
1079 437 julius
  /* Reset IRQ line status */
1080
  eth->int_line_stat = 0;
1081
 
1082 434 jeremybenn
  /* Initialize VAPI */
1083
  if (eth->base_vapi_id)
1084
    {
1085
      vapi_install_multi_handler (eth->base_vapi_id, ETH_NUM_VAPI_IDS,
1086
                                  eth_vapi_read, dat);
1087
    }
1088
}       /* eth_reset () */
1089
 
1090
 
1091 451 jeremybenn
#if ETH_DEBUG
1092
/* -------------------------------------------------------------------------- */
1093
/*!Map a register address to its name
1094
 
1095
   @param[in[ addr  The address of the register to name (offset from base).
1096
 
1097
   @return  The name of the register.                                         */
1098
/* -------------------------------------------------------------------------- */
1099
static char *
1100
eth_regname (oraddr_t  addr)
1101 19 jeremybenn
{
1102 451 jeremybenn
  static char  bdstr[8];                /* For "BD[nnn]" */
1103 19 jeremybenn
 
1104 451 jeremybenn
  switch (addr)
1105
    {
1106
    case ETH_MODER:      return  "MODER";
1107
    case ETH_INT_SOURCE: return  "INT_SOURCE";
1108
    case ETH_INT_MASK:   return  "INT_MASK";
1109
    case ETH_IPGT:       return  "IPGT";
1110
    case ETH_IPGR1:      return  "IPGR1";
1111
    case ETH_IPGR2:      return  "IPGR2";
1112
    case ETH_PACKETLEN:  return  "PACKETLEN";
1113
    case ETH_COLLCONF:   return  "COLLCONF";
1114
    case ETH_TX_BD_NUM:  return  "TX_BD_NUM";
1115
    case ETH_CTRLMODER:  return  "CTRLMODER";
1116
    case ETH_MIIMODER:   return  "MIIMODER";
1117
    case ETH_MIICOMMAND: return  "MIICOMMAND";
1118
    case ETH_MIIADDRESS: return  "MIIADDRESS";
1119
    case ETH_MIITX_DATA: return  "MIITX_DATA";
1120
    case ETH_MIIRX_DATA: return  "MIIRX_DATA";
1121
    case ETH_MIISTATUS:  return  "MIISTATUS";
1122
    case ETH_MAC_ADDR0:  return  "MAC_ADDR0";
1123
    case ETH_MAC_ADDR1:  return  "MAC_ADDR1";
1124
    case ETH_HASH0:      return  "HASH0";
1125
    case ETH_HASH1:      return  "HASH1";
1126 19 jeremybenn
 
1127 451 jeremybenn
    default:
1128
      /* Buffer descriptors are a special case. */
1129
      if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
1130
        {
1131
          sprintf (bdstr, "BD[%.3d]", (addr - ETH_BD_BASE) / 4);
1132
          return  bdstr;
1133
        }
1134
      else
1135
        {
1136
          return  "INVALID";
1137
        }
1138
    }
1139
}       /* eth_regname () */
1140
#endif
1141 19 jeremybenn
 
1142
 
1143 451 jeremybenn
/* -------------------------------------------------------------------------- */
1144
/*!Read a register
1145
 
1146
   @param[in] addr  The address of the register to read (offset from base).
1147
   @param[in] dat   The Ethernet interface data structure, cast to a void
1148
                    pointer.
1149
 
1150
   @return  The value read.                                                   */
1151
/* -------------------------------------------------------------------------- */
1152 19 jeremybenn
static uint32_t
1153 451 jeremybenn
eth_read32 (oraddr_t  addr,
1154
            void     *dat)
1155 19 jeremybenn
{
1156
  struct eth_device *eth = dat;
1157 451 jeremybenn
  uint32_t           res;
1158 19 jeremybenn
 
1159
  switch (addr)
1160
    {
1161 451 jeremybenn
    case ETH_MODER:      res = eth->regs.moder;        break;
1162
    case ETH_INT_SOURCE: res = eth->regs.int_source;   break;
1163
    case ETH_INT_MASK:   res = eth->regs.int_mask;     break;
1164
    case ETH_IPGT:       res = eth->regs.ipgt;         break;
1165
    case ETH_IPGR1:      res = eth->regs.ipgr1;        break;
1166
    case ETH_IPGR2:      res = eth->regs.ipgr2;        break;
1167
    case ETH_PACKETLEN:  res = eth->regs.packetlen;    break;
1168
    case ETH_COLLCONF:   res = eth->regs.collconf;     break;
1169
    case ETH_TX_BD_NUM:  res = eth->regs.tx_bd_num;    break;
1170
    case ETH_CTRLMODER:  res = eth->regs.controlmoder; break;
1171
    case ETH_MIIMODER:   res = eth->regs.miimoder;     break;
1172
    case ETH_MIICOMMAND: res = eth->regs.miicommand;   break;
1173
    case ETH_MIIADDRESS: res = eth->regs.miiaddress;   break;
1174
    case ETH_MIITX_DATA: res = eth->regs.miitx_data;   break;
1175
    case ETH_MIIRX_DATA: res = eth->regs.miirx_data;   break;
1176
    case ETH_MIISTATUS:  res = eth->regs.miistatus;    break;
1177
    case ETH_MAC_ADDR0:
1178
      res =
1179
        (((unsigned long) eth->mac_address[2]) << 24) |
1180
        (((unsigned long) eth->mac_address[3]) << 16) |
1181
        (((unsigned long) eth->mac_address[4]) <<  8) |
1182
          (unsigned long) eth->mac_address[5];
1183
      break;
1184
    case ETH_MAC_ADDR1:
1185
      res =
1186
        (((unsigned long) eth->mac_address[0]) <<  8) |
1187
          (unsigned long) eth->mac_address[1];
1188
      break;
1189
    case ETH_HASH0:      res = eth->regs.hash0;        break;
1190
    case ETH_HASH1:      res = eth->regs.hash1;        break;
1191
 
1192
    default:
1193
      /* Buffer descriptors are a special case. */
1194
      if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
1195
        {
1196
          res = eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4];
1197
          break;
1198
        }
1199
      else
1200
        {
1201
          fprintf (stderr,
1202
                   "Warning: eth_read32( 0x%" PRIxADDR " ): Illegal address\n",
1203
                   addr + eth->baseaddr);
1204
          res = 0;
1205
        }
1206
    }
1207
 
1208
#if ETH_DEBUG
1209
  /* Only trace registers of particular interest */
1210
  switch (addr)
1211
    {
1212 19 jeremybenn
    case ETH_MODER:
1213
    case ETH_INT_SOURCE:
1214
    case ETH_INT_MASK:
1215
    case ETH_IPGT:
1216
    case ETH_IPGR1:
1217
    case ETH_IPGR2:
1218
    case ETH_PACKETLEN:
1219
    case ETH_COLLCONF:
1220
    case ETH_TX_BD_NUM:
1221
    case ETH_CTRLMODER:
1222
    case ETH_MAC_ADDR0:
1223
    case ETH_MAC_ADDR1:
1224 451 jeremybenn
      printf ("eth_read32: %s = 0x%08lx\n", eth_regname (addr),
1225
              (unsigned long int) res);
1226 19 jeremybenn
    }
1227 451 jeremybenn
#endif
1228 19 jeremybenn
 
1229 451 jeremybenn
  return  res;
1230 19 jeremybenn
 
1231 451 jeremybenn
}       /* eth_read32 () */
1232 19 jeremybenn
 
1233
 
1234 451 jeremybenn
/* -------------------------------------------------------------------------- */
1235
/*!Emulate MIIM transaction to ethernet PHY
1236 19 jeremybenn
 
1237 451 jeremybenn
   @param[in] eth  Ethernet device datastruture.                              */
1238
/* -------------------------------------------------------------------------- */
1239 19 jeremybenn
static void
1240 451 jeremybenn
eth_miim_trans (struct eth_device *eth)
1241
{
1242
  switch (eth->regs.miicommand)
1243
    {
1244
    case ((1 << ETH_MIICOMM_WCDATA_OFFSET)):
1245
      /* Perhaps something to emulate here later, but for now do nothing */
1246
      break;
1247
 
1248
    case ((1 << ETH_MIICOMM_RSTAT_OFFSET)):
1249
      /*First check if it's the correct PHY to address */
1250
      if (((eth->regs.miiaddress >> ETH_MIIADDR_FIAD_OFFSET)&
1251
           ETH_MIIADDR_FIAD_MASK) == eth->phy_addr)
1252
        {
1253
          /* Correct PHY - now switch based on the register address in the PHY*/
1254
          switch ((eth->regs.miiaddress >> ETH_MIIADDR_RGAD_OFFSET)&
1255
                  ETH_MIIADDR_RGAD_MASK)
1256
            {
1257
            case MII_BMCR:
1258
              eth->regs.miirx_data = BMCR_FULLDPLX;
1259
              break;
1260
            case MII_BMSR:
1261
              eth->regs.miirx_data = BMSR_LSTATUS | BMSR_ANEGCOMPLETE |
1262
                BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | BMSR_100FULL;
1263
              break;
1264
            case MII_PHYSID1:
1265
              eth->regs.miirx_data = 0x22; /* Micrel PHYID */
1266
              break;
1267
            case MII_PHYSID2:
1268
              eth->regs.miirx_data = 0x1613; /* Micrel PHYID */
1269
              break;
1270
            case MII_ADVERTISE:
1271
              eth->regs.miirx_data = ADVERTISE_FULL;
1272
              break;
1273
            case MII_LPA:
1274
              eth->regs.miirx_data = LPA_DUPLEX | LPA_100;
1275
              break;
1276
            case MII_EXPANSION:
1277
              eth->regs.miirx_data = 0;
1278
              break;
1279
            case MII_CTRL1000:
1280
              eth->regs.miirx_data = 0;
1281
              break;
1282
            case MII_STAT1000:
1283
              eth->regs.miirx_data = 0;
1284
              break;
1285
            case MII_ESTATUS:
1286
              eth->regs.miirx_data = 0;
1287
              break;
1288
            case MII_DCOUNTER:
1289
              eth->regs.miirx_data = 0;
1290
              break;
1291
            case MII_FCSCOUNTER:
1292
              eth->regs.miirx_data = 0;
1293
              break;
1294
            case MII_NWAYTEST:
1295
              eth->regs.miirx_data = 0;
1296
              break;
1297
            case MII_RERRCOUNTER:
1298
              eth->regs.miirx_data = 0;
1299
              break;
1300
            case MII_SREVISION:
1301
              eth->regs.miirx_data = 0;
1302
              break;
1303
            case MII_RESV1:
1304
              eth->regs.miirx_data = 0;
1305
              break;
1306
            case MII_LBRERROR:
1307
              eth->regs.miirx_data = 0;
1308
              break;
1309
            case MII_PHYADDR:
1310
              eth->regs.miirx_data = eth->phy_addr;
1311
              break;
1312
            case MII_RESV2:
1313
              eth->regs.miirx_data = 0;
1314
              break;
1315
            case MII_TPISTATUS:
1316
              eth->regs.miirx_data = 0;
1317
              break;
1318
            case MII_NCONFIG:
1319
              eth->regs.miirx_data = 0;
1320
              break;
1321
            default:
1322
              eth->regs.miirx_data = 0xffff;
1323
              break;
1324
            }
1325
        }
1326
      else
1327
        {
1328
          eth->regs.miirx_data = 0xffff; /* PHY doesn't exist, read all 1's */
1329
        }
1330
 
1331
      break;
1332
 
1333
    case ((1 << ETH_MIICOMM_SCANS_OFFSET)):
1334
      /* From MAC's datasheet:
1335
         A host initiates the Scan Status Operation by asserting the SCANSTAT
1336
         signal. The MIIM performs a continuous read operation of the PHY
1337
         Status register. The PHY is selected by the FIAD[4:0] signals. The
1338
         link status LinkFail signal is asserted/deasserted by the MIIM module
1339
         and reflects the link status bit of the PHY Status register. The
1340
         signal NVALID is used for qualifying the validity of the LinkFail
1341
         signals and the status data PRSD[15:0]. These signals are invalid
1342
         until the first scan status operation ends. During the scan status
1343
         operation, the BUSY signal is asserted until the last read is
1344
         performed (the scan status operation is stopped).
1345
 
1346
         So for now - do nothing, leave link status indicator as permanently
1347
         with link.
1348
      */
1349
 
1350
      break;
1351
 
1352
    default:
1353
      break;
1354
    }
1355
}       /* eth_miim_trans () */
1356
 
1357
 
1358
 
1359
/* -------------------------------------------------------------------------- */
1360
/*!Write a register
1361
 
1362
   @param[in] addr   The address of the register to read (offset from base).
1363
   @param[in] value  The value to write.
1364
   @param[in] dat    The Ethernet interface data structure, cast to a void
1365
                     pointer.                                                 */
1366
/* -------------------------------------------------------------------------- */
1367
static void
1368 19 jeremybenn
eth_write32 (oraddr_t addr, uint32_t value, void *dat)
1369
{
1370
  struct eth_device *eth = dat;
1371
 
1372 451 jeremybenn
#if ETH_DEBUG
1373
  /* Only trace registers of particular interest */
1374 457 julius
 
1375 19 jeremybenn
  switch (addr)
1376 457 julius
  {
1377
  case ETH_MODER:
1378
  case ETH_INT_SOURCE:
1379
  case ETH_INT_MASK:
1380
  case ETH_IPGT:
1381
  case ETH_IPGR1:
1382
  case ETH_IPGR2:
1383
  case ETH_PACKETLEN:
1384
  case ETH_COLLCONF:
1385
  case ETH_TX_BD_NUM:
1386
  case ETH_CTRLMODER:
1387
  case ETH_MAC_ADDR0:
1388
  case ETH_MAC_ADDR1:
1389
          printf ("eth_write32: 0x%08lx to %s ", (unsigned long) value,
1390
                  eth_regname (addr));
1391
 
1392
  }
1393
 
1394
  /* Detail register transitions on MODER, INT_SOURCE AND INT_MASK */
1395
 
1396
  switch (addr)
1397
  {
1398
  case ETH_MODER:
1399
          printf("0x%08lx -> ", (unsigned long) eth->regs.moder);
1400
          break;
1401
  case ETH_INT_SOURCE:
1402
          printf("0x%08lx -> ", (unsigned long) eth->regs.int_source);
1403
          break;
1404
  case ETH_INT_MASK:
1405
          printf("0x%08lx -> ", (unsigned long) eth->regs.int_mask);
1406
          break;
1407
  }
1408
 
1409
 
1410
 
1411 437 julius
#endif
1412 451 jeremybenn
 
1413
  switch (addr)
1414
    {
1415
    case ETH_MODER:
1416 19 jeremybenn
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN) &&
1417
          TEST_FLAG (value, ETH_MODER, RXEN))
1418 436 julius
        {
1419 451 jeremybenn
          /* Enabling receive, flush any oustanding input (TAP only), reset
1420
             the BDs and schedule the Rx controller on the next clock
1421
             cycle. */
1422
          if (ETH_RTX_TAP == eth->rtx_type)
1423
            {
1424
              (void) eth_ignore_tap_packets (eth);
1425
            }
1426
 
1427
          eth->rx_bd_index = eth->regs.tx_bd_num * 2;
1428 436 julius
          SCHED_ADD (eth_controller_rx_clock, dat, 1);
1429
        }
1430 437 julius
      else if (!TEST_FLAG (value, ETH_MODER, RXEN) &&
1431
               TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
1432 451 jeremybenn
        {
1433
          /* Disabling Rx, so stop scheduling the Rx controller. */
1434
          SCHED_FIND_REMOVE (eth_controller_rx_clock, dat);
1435
        }
1436 19 jeremybenn
 
1437
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN) &&
1438
          TEST_FLAG (value, ETH_MODER, TXEN))
1439 436 julius
        {
1440 451 jeremybenn
          /* Enabling transmit, reset the BD and schedule the Tx controller on
1441
             the next clock cycle. */
1442 450 jeremybenn
          eth->tx_bd_index = 0;
1443 436 julius
          SCHED_ADD (eth_controller_tx_clock, dat, 1);
1444
        }
1445 437 julius
      else if (!TEST_FLAG (value, ETH_MODER, TXEN) &&
1446
               TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN))
1447 451 jeremybenn
        {
1448
          /* Disabling Tx, so stop scheduling the Tx controller. */
1449
          SCHED_FIND_REMOVE (eth_controller_tx_clock, dat);
1450
        }
1451 19 jeremybenn
 
1452 451 jeremybenn
      /* Reset the interface if so requested. */
1453
      if (TEST_FLAG (value, ETH_MODER, RST))
1454
        {
1455
          eth_reset (dat);
1456
        }
1457 19 jeremybenn
 
1458 451 jeremybenn
      eth->regs.moder = value;          /* Update the register */
1459
      break;
1460
 
1461 19 jeremybenn
    case ETH_INT_SOURCE:
1462 437 julius
      eth->regs.int_source &= ~value;
1463 436 julius
 
1464 451 jeremybenn
      /* Clear IRQ line if all interrupt sources have been dealt with
1465
 
1466
         @todo  Is this really right? */
1467 437 julius
      if (!(eth->regs.int_source & eth->regs.int_mask) && eth->int_line_stat)
1468
        {
1469
          clear_interrupt (eth->mac_int);
1470
          eth->int_line_stat = 0;
1471
        }
1472 451 jeremybenn
      break;
1473
 
1474 19 jeremybenn
    case ETH_INT_MASK:
1475
      eth->regs.int_mask = value;
1476 451 jeremybenn
 
1477
      /* If we enable interrupts, the core is not currently processing an
1478
         interrupt, and there is an interrupt pending, then report that
1479
         interrupt.
1480
 
1481
         Otherwise clear down the interrupt.
1482
 
1483
         @todo  Is this really right. */
1484 437 julius
      if ((eth->regs.int_source & eth->regs.int_mask) && !eth->int_line_stat)
1485 451 jeremybenn
        {
1486
          report_interrupt (eth->mac_int);
1487
        }
1488
      else if (eth->int_line_stat)
1489
        {
1490
          clear_interrupt (eth->mac_int);
1491
          eth->int_line_stat = 0;
1492
        }
1493
      break;
1494
 
1495
    case ETH_IPGT:       eth->regs.ipgt         = value; break;
1496
    case ETH_IPGR1:      eth->regs.ipgr1        = value; break;
1497
    case ETH_IPGR2:      eth->regs.ipgr2        = value; break;
1498
    case ETH_PACKETLEN:  eth->regs.packetlen    = value; break;
1499
    case ETH_COLLCONF:   eth->regs.collconf     = value; break;
1500
 
1501 19 jeremybenn
    case ETH_TX_BD_NUM:
1502 443 jeremybenn
      /* When TX_BD_NUM is written, also reset current RX BD index */
1503
      eth->regs.tx_bd_num = value & 0xFF;
1504 451 jeremybenn
      eth->rx_bd_index = eth->regs.tx_bd_num * 2;
1505
      break;
1506
 
1507
    case ETH_CTRLMODER:  eth->regs.controlmoder = value; break;
1508
    case ETH_MIIMODER:   eth->regs.miimoder     = value; break;
1509
 
1510 19 jeremybenn
    case ETH_MIICOMMAND:
1511
      eth->regs.miicommand = value;
1512 428 julius
      /* Perform MIIM transaction, if required */
1513 443 jeremybenn
      eth_miim_trans (eth);
1514 451 jeremybenn
      break;
1515 428 julius
 
1516 451 jeremybenn
    case ETH_MIIADDRESS: eth->regs.miiaddress   = value; break;
1517
    case ETH_MIITX_DATA: eth->regs.miitx_data   = value; break;
1518
    case ETH_MIIRX_DATA: /* Register is R/O */           break;
1519
    case ETH_MIISTATUS:  /* Register is R/O */           break;
1520
 
1521 19 jeremybenn
    case ETH_MAC_ADDR0:
1522 451 jeremybenn
      eth->mac_address[5] =  value        & 0xFF;
1523
      eth->mac_address[4] = (value >>  8) & 0xFF;
1524 450 jeremybenn
      eth->mac_address[3] = (value >> 16) & 0xFF;
1525
      eth->mac_address[2] = (value >> 24) & 0xFF;
1526 451 jeremybenn
      break;
1527
 
1528 19 jeremybenn
    case ETH_MAC_ADDR1:
1529 451 jeremybenn
      eth->mac_address[1] =  value        & 0xFF;
1530
      eth->mac_address[0] = (value >>  8) & 0xFF;
1531
      break;
1532 19 jeremybenn
 
1533 451 jeremybenn
    case ETH_HASH0:      eth->regs.hash0 = value;        break;
1534
    case ETH_HASH1:      eth->regs.hash1 = value;        break;
1535 19 jeremybenn
 
1536 451 jeremybenn
    default:
1537
      if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
1538
        {
1539
          eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value;
1540
        }
1541
      else
1542
        {
1543
          fprintf (stderr,
1544
                   "Warning: eth_write32( 0x%" PRIxADDR " ): Illegal address\n",
1545
                   addr + eth->baseaddr);
1546
        }
1547
      break;
1548 19 jeremybenn
    }
1549 457 julius
 
1550
#if ETH_DEBUG
1551
 
1552
  switch (addr)
1553
  {
1554
  case ETH_MODER:
1555
          printf("0x%08lx", (unsigned long) eth->regs.moder);
1556
          break;
1557
  case ETH_INT_SOURCE:
1558
          printf("0x%08lx", (unsigned long) eth->regs.int_source);
1559
          break;
1560
  case ETH_INT_MASK:
1561
          printf("0x%08lx", (unsigned long) eth->regs.int_mask);
1562
          break;
1563
  case ETH_IPGT:
1564
  case ETH_IPGR1:
1565
  case ETH_IPGR2:
1566
  case ETH_PACKETLEN:
1567
  case ETH_COLLCONF:
1568
  case ETH_TX_BD_NUM:
1569
  case ETH_CTRLMODER:
1570
  case ETH_MAC_ADDR0:
1571
  case ETH_MAC_ADDR1:
1572
          break;
1573
  }
1574
 
1575
  printf("\n");
1576
#endif
1577
 
1578
 
1579 451 jeremybenn
}       /* eth_write32 () */
1580 19 jeremybenn
 
1581
 
1582
/*---------------------------------------------------------------------------*/
1583
/*!Enable or disable the Ethernet interface
1584
 
1585
   @param[in] val  The value to use
1586
   @param[in] dat  The config data structure                                 */
1587
/*---------------------------------------------------------------------------*/
1588
static void
1589
eth_enabled (union param_val  val,
1590
             void            *dat)
1591
{
1592
  struct eth_device *eth = dat;
1593
 
1594
  eth->enabled = val.int_val;
1595
 
1596
}       /* eth_enabled() */
1597
 
1598
 
1599
/*---------------------------------------------------------------------------*/
1600
/*!Set the Ethernet interface base address
1601
 
1602
   @param[in] val  The value to use
1603
   @param[in] dat  The config data structure                                 */
1604
/*---------------------------------------------------------------------------*/
1605
static void
1606
eth_baseaddr (union param_val  val,
1607
              void            *dat)
1608
{
1609
  struct eth_device *eth = dat;
1610
 
1611
  eth->baseaddr = val.addr_val;
1612
 
1613
}       /* eth_baseaddr() */
1614
 
1615
 
1616
/*---------------------------------------------------------------------------*/
1617
/*!Set the Ethernet DMA port
1618
 
1619
   This is not currently supported, so a warning message is printed.
1620
 
1621
   @param[in] val  The value to use
1622
   @param[in] dat  The config data structure                                 */
1623
/*---------------------------------------------------------------------------*/
1624
static void
1625
eth_dma (union param_val  val,
1626
         void            *dat)
1627
{
1628
  struct eth_device *eth = dat;
1629
 
1630
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported\n");
1631
  eth->dma = val.addr_val;
1632
 
1633
}       /* eth_dma() */
1634
 
1635
 
1636
/*---------------------------------------------------------------------------*/
1637
/*!Set the Ethernet IRQ
1638
 
1639
   @param[in] val  The value to use
1640
   @param[in] dat  The config data structure                                 */
1641
/*---------------------------------------------------------------------------*/
1642
static void
1643
eth_irq (union param_val  val,
1644
         void            *dat)
1645
{
1646
  struct eth_device *eth = dat;
1647
 
1648
  eth->mac_int = val.int_val;
1649
 
1650
}       /* eth_irq() */
1651
 
1652
 
1653
/*---------------------------------------------------------------------------*/
1654
/*!Set the Ethernet interface type
1655
 
1656 434 jeremybenn
   Currently two types are supported, file and tap.
1657 19 jeremybenn
 
1658 434 jeremybenn
   @param[in] val  The value to use. Currently "file" and "tap" are supported.
1659 19 jeremybenn
   @param[in] dat  The config data structure                                 */
1660
/*---------------------------------------------------------------------------*/
1661
static void
1662
eth_rtx_type (union param_val  val,
1663
              void            *dat)
1664
{
1665
  struct eth_device *eth = dat;
1666
 
1667 434 jeremybenn
  if (0 == strcasecmp ("file", val.str_val))
1668 19 jeremybenn
    {
1669 434 jeremybenn
      printf ("Ethernet FILE type\n");
1670
      eth->rtx_type = ETH_RTX_FILE;
1671 19 jeremybenn
    }
1672 434 jeremybenn
  else if (0 == strcasecmp ("tap", val.str_val))
1673
    {
1674
      printf ("Ethernet TAP type\n");
1675
      eth->rtx_type = ETH_RTX_TAP;
1676
    }
1677
  else
1678
    {
1679
      fprintf (stderr, "Warning: Unknown Ethernet type: file assumed.\n");
1680
      eth->rtx_type = ETH_RTX_FILE;
1681
    }
1682 19 jeremybenn
}       /* eth_rtx_type() */
1683
 
1684
 
1685
/*---------------------------------------------------------------------------*/
1686
/*!Set the Ethernet DMA Rx channel
1687
 
1688
   External DMA is not currently supported, so a warning message is printed.
1689
 
1690
   @param[in] val  The value to use
1691
   @param[in] dat  The config data structure                                 */
1692
/*---------------------------------------------------------------------------*/
1693
static void
1694
eth_rx_channel (union param_val  val,
1695
                void            *dat)
1696
{
1697
  struct eth_device *eth = dat;
1698
 
1699
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1700
           "Rx channel ignored\n");
1701
  eth->rx_channel = val.int_val;
1702
 
1703
}       /* eth_rx_channel() */
1704
 
1705
 
1706
/*---------------------------------------------------------------------------*/
1707
/*!Set the Ethernet DMA Tx channel
1708
 
1709
   External DMA is not currently supported, so a warning message is printed.
1710
 
1711
   @param[in] val  The value to use
1712
   @param[in] dat  The config data structure                                 */
1713
/*---------------------------------------------------------------------------*/
1714
static void
1715
eth_tx_channel (union param_val  val,
1716
                void            *dat)
1717
{
1718
  struct eth_device *eth = dat;
1719
 
1720
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1721
           "Tx channel ignored\n");
1722
  eth->tx_channel = val.int_val;
1723
 
1724
}       /* eth_tx_channel() */
1725
 
1726
 
1727
/*---------------------------------------------------------------------------*/
1728
/*!Set the Ethernet DMA Rx file
1729
 
1730
   Free any previously allocated value.
1731
 
1732
   @param[in] val  The value to use
1733
   @param[in] dat  The config data structure                                 */
1734
/*---------------------------------------------------------------------------*/
1735
static void
1736
eth_rxfile (union param_val  val,
1737
            void            *dat)
1738
{
1739
  struct eth_device *eth = dat;
1740
 
1741
  if (NULL != eth->rxfile)
1742
    {
1743
      free (eth->rxfile);
1744
      eth->rxfile = NULL;
1745
    }
1746
 
1747
  if (!(eth->rxfile = strdup (val.str_val)))
1748
    {
1749
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1750
      exit (-1);
1751
    }
1752
}       /* eth_rxfile() */
1753
 
1754
 
1755
/*---------------------------------------------------------------------------*/
1756
/*!Set the Ethernet DMA Tx file
1757
 
1758
   Free any previously allocated value.
1759
 
1760
   @param[in] val  The value to use
1761
   @param[in] dat  The config data structure                                 */
1762
/*---------------------------------------------------------------------------*/
1763
static void
1764
eth_txfile (union param_val  val,
1765
            void            *dat)
1766
{
1767
  struct eth_device *eth = dat;
1768
 
1769
  if (NULL != eth->txfile)
1770
    {
1771
      free (eth->txfile);
1772
      eth->txfile = NULL;
1773
    }
1774
 
1775
  if (!(eth->txfile = strdup (val.str_val)))
1776
    {
1777
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1778
      exit (-1);
1779
    }
1780
}       /* eth_txfile() */
1781
 
1782
 
1783
/*---------------------------------------------------------------------------*/
1784 434 jeremybenn
/*!Set the Ethernet TAP device.
1785 19 jeremybenn
 
1786 434 jeremybenn
   If we are not superuser (or do not have CAP_NET_ADMIN priviledges), then we
1787
   must work with a persistent TAP device that is already set up. This option
1788
   specifies the device to user.
1789 19 jeremybenn
 
1790 434 jeremybenn
   @param[in] val  The value to use.
1791 19 jeremybenn
   @param[in] dat  The config data structure                                 */
1792
/*---------------------------------------------------------------------------*/
1793
static void
1794 434 jeremybenn
eth_tap_dev (union param_val  val,
1795
              void            *dat)
1796 19 jeremybenn
{
1797
  struct eth_device *eth = dat;
1798
 
1799 434 jeremybenn
  if (NULL != eth->tap_dev)
1800 19 jeremybenn
    {
1801 434 jeremybenn
      free (eth->tap_dev);
1802
      eth->tap_dev = NULL;
1803 19 jeremybenn
    }
1804
 
1805 434 jeremybenn
  eth->tap_dev = strdup (val.str_val);
1806
 
1807
  if (NULL == eth->tap_dev)
1808 19 jeremybenn
    {
1809 434 jeremybenn
      fprintf (stderr, "ERROR: Peripheral Ethernet: Run out of memory\n");
1810 19 jeremybenn
      exit (-1);
1811
    }
1812 434 jeremybenn
}       /* eth_tap_dev() */
1813 19 jeremybenn
 
1814
 
1815 451 jeremybenn
/*---------------------------------------------------------------------------*/
1816
/*!Set the PHY address
1817
 
1818
   Used to identify different physical interfaces (important for MII).
1819
 
1820
   @param[in] val  The value to use.
1821
   @param[in] dat  The config data structure                                 */
1822
/*---------------------------------------------------------------------------*/
1823 19 jeremybenn
static void
1824 451 jeremybenn
eth_phy_addr (union param_val  val,
1825
              void            *dat)
1826
{
1827
  struct eth_device *eth = dat;
1828
  eth->phy_addr = val.int_val & ETH_MIIADDR_FIAD_MASK;
1829
 
1830
}       /* eth_phy_addr () */
1831
 
1832
 
1833
/*---------------------------------------------------------------------------*/
1834
/*!Enable or disable a dummy CRC
1835
 
1836
   The MAC should not report anything about the CRC back to the core. However
1837
   the hardware implementation of the OpenRISC MAC does, and the Linux drivers
1838
   have been written to expect the value (which they ignore).
1839
 
1840
   Setting this parameter causes a dummy CRC to be added. For consistency with
1841
   the hardware, its default setting is TRUE.
1842
 
1843
   @param[in] val  The value to use
1844
   @param[in] dat  The config data structure                                 */
1845
/*---------------------------------------------------------------------------*/
1846
static void
1847
eth_dummy_crc (union param_val  val,
1848 19 jeremybenn
             void            *dat)
1849
{
1850
  struct eth_device *eth = dat;
1851
 
1852 451 jeremybenn
  eth->dummy_crc = val.int_val;
1853 428 julius
 
1854 451 jeremybenn
}       /* eth_dummy_crc() */
1855
 
1856
 
1857
/*---------------------------------------------------------------------------*/
1858
/*!Set the VAPI id
1859
 
1860
   Used for remote testing of the interface.
1861
 
1862
   @param[in] val  The value to use.
1863
   @param[in] dat  The config data structure                                 */
1864
/*---------------------------------------------------------------------------*/
1865 428 julius
static void
1866 451 jeremybenn
eth_vapi_id (union param_val  val,
1867
             void            *dat)
1868 428 julius
{
1869
  struct eth_device *eth = dat;
1870 451 jeremybenn
  eth->base_vapi_id = val.int_val;
1871 428 julius
 
1872 451 jeremybenn
}       /* eth_vapi_id () */
1873 428 julius
 
1874 451 jeremybenn
 
1875 19 jeremybenn
/*---------------------------------------------------------------------------*/
1876 451 jeremybenn
/*!Start the initialization of a new Ethernet configuration
1877 19 jeremybenn
 
1878
   ALL parameters are set explicitly to default values.                      */
1879
/*---------------------------------------------------------------------------*/
1880
static void *
1881
eth_sec_start (void)
1882
{
1883
  struct eth_device *new = malloc (sizeof (struct eth_device));
1884
 
1885
  if (!new)
1886
    {
1887
      fprintf (stderr, "Peripheral Eth: Run out of memory\n");
1888
      exit (-1);
1889
    }
1890
 
1891
  memset (new, 0, sizeof (struct eth_device));
1892
 
1893
  new->enabled      = 1;
1894
  new->baseaddr     = 0;
1895
  new->dma          = 0;
1896
  new->mac_int      = 0;
1897 437 julius
  new->int_line_stat= 0;
1898 434 jeremybenn
  new->rtx_type     = ETH_RTX_FILE;
1899 19 jeremybenn
  new->rx_channel   = 0;
1900
  new->tx_channel   = 0;
1901 451 jeremybenn
  new->rtx_fd       = -1;
1902 19 jeremybenn
  new->rxfile       = strdup ("eth_rx");
1903
  new->txfile       = strdup ("eth_tx");
1904 434 jeremybenn
  new->tap_dev      = strdup ("");
1905 451 jeremybenn
  new->phy_addr     = 0;
1906
  new->dummy_crc    = 1;
1907 19 jeremybenn
  new->base_vapi_id = 0;
1908
 
1909
  return new;
1910
 
1911 451 jeremybenn
}       /* eth_sec_start () */
1912
 
1913
 
1914
/*---------------------------------------------------------------------------*/
1915
/*!Complete the initialization of a new Ethernet configuration
1916
 
1917
   ALL parameters are set explicitly to default values.                      */
1918
/*---------------------------------------------------------------------------*/
1919 19 jeremybenn
static void
1920
eth_sec_end (void *dat)
1921
{
1922
  struct eth_device *eth = dat;
1923
  struct mem_ops ops;
1924
 
1925
  if (!eth->enabled)
1926
    {
1927
      free (eth->rxfile);
1928
      free (eth->txfile);
1929 434 jeremybenn
      free (eth->tap_dev);
1930 19 jeremybenn
      free (eth);
1931
      return;
1932
    }
1933
 
1934
  memset (&ops, 0, sizeof (struct mem_ops));
1935
 
1936
  ops.readfunc32 = eth_read32;
1937
  ops.writefunc32 = eth_write32;
1938
  ops.read_dat32 = dat;
1939
  ops.write_dat32 = dat;
1940
 
1941
  /* FIXME: Correct delay? */
1942
  ops.delayr = 2;
1943
  ops.delayw = 2;
1944
  reg_mem_area (eth->baseaddr, ETH_ADDR_SPACE, 0, &ops);
1945
  reg_sim_stat (eth_status, dat);
1946
  reg_sim_reset (eth_reset, dat);
1947
 
1948 451 jeremybenn
}       /* eth_sec_end () */
1949 19 jeremybenn
 
1950 451 jeremybenn
 
1951 19 jeremybenn
/*---------------------------------------------------------------------------*/
1952
/*!Register a new Ethernet configuration                                     */
1953
/*---------------------------------------------------------------------------*/
1954
void
1955
reg_ethernet_sec ()
1956
{
1957
  struct config_section *sec =
1958
    reg_config_sec ("ethernet", eth_sec_start, eth_sec_end);
1959
 
1960 224 jeremybenn
  reg_config_param (sec, "enabled",    PARAMT_INT,  eth_enabled);
1961
  reg_config_param (sec, "baseaddr",   PARAMT_ADDR, eth_baseaddr);
1962
  reg_config_param (sec, "dma",        PARAMT_INT,  eth_dma);
1963
  reg_config_param (sec, "irq",        PARAMT_INT,  eth_irq);
1964 434 jeremybenn
  reg_config_param (sec, "rtx_type",   PARAMT_STR,  eth_rtx_type);
1965 224 jeremybenn
  reg_config_param (sec, "rx_channel", PARAMT_INT,  eth_rx_channel);
1966
  reg_config_param (sec, "tx_channel", PARAMT_INT,  eth_tx_channel);
1967
  reg_config_param (sec, "rxfile",     PARAMT_STR,  eth_rxfile);
1968
  reg_config_param (sec, "txfile",     PARAMT_STR,  eth_txfile);
1969 434 jeremybenn
  reg_config_param (sec, "tap_dev",    PARAMT_STR,  eth_tap_dev);
1970 451 jeremybenn
  reg_config_param (sec, "phy_addr",   PARAMT_INT,  eth_phy_addr);
1971
  reg_config_param (sec, "dummy_crc",  PARAMT_INT,  eth_dummy_crc);
1972 224 jeremybenn
  reg_config_param (sec, "vapi_id",    PARAMT_INT,  eth_vapi_id);
1973 19 jeremybenn
 
1974
}       /* reg_ethernet_sec() */

powered by: WebSVN 2.1.0

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