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

Subversion Repositories openrisc

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

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
#define  RTX_RESCHED_PERIOD  1
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 434 jeremybenn
 
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 19 jeremybenn
  switch (addr)
1375
    {
1376
    case ETH_MODER:
1377 451 jeremybenn
    case ETH_INT_SOURCE:
1378
    case ETH_INT_MASK:
1379
    case ETH_IPGT:
1380
    case ETH_IPGR1:
1381
    case ETH_IPGR2:
1382
    case ETH_PACKETLEN:
1383
    case ETH_COLLCONF:
1384
    case ETH_TX_BD_NUM:
1385
    case ETH_CTRLMODER:
1386
    case ETH_MAC_ADDR0:
1387
    case ETH_MAC_ADDR1:
1388
      printf ("eth_write32: %s = 0x%08lx\n", eth_regname (addr),
1389
              (unsigned long int) value);
1390
    }
1391 437 julius
#endif
1392 451 jeremybenn
 
1393
  switch (addr)
1394
    {
1395
    case ETH_MODER:
1396 19 jeremybenn
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN) &&
1397
          TEST_FLAG (value, ETH_MODER, RXEN))
1398 436 julius
        {
1399 451 jeremybenn
          /* Enabling receive, flush any oustanding input (TAP only), reset
1400
             the BDs and schedule the Rx controller on the next clock
1401
             cycle. */
1402
          if (ETH_RTX_TAP == eth->rtx_type)
1403
            {
1404
              (void) eth_ignore_tap_packets (eth);
1405
            }
1406
 
1407
          eth->rx_bd_index = eth->regs.tx_bd_num * 2;
1408 436 julius
          SCHED_ADD (eth_controller_rx_clock, dat, 1);
1409
        }
1410 437 julius
      else if (!TEST_FLAG (value, ETH_MODER, RXEN) &&
1411
               TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
1412 451 jeremybenn
        {
1413
          /* Disabling Rx, so stop scheduling the Rx controller. */
1414
          SCHED_FIND_REMOVE (eth_controller_rx_clock, dat);
1415
        }
1416 19 jeremybenn
 
1417
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN) &&
1418
          TEST_FLAG (value, ETH_MODER, TXEN))
1419 436 julius
        {
1420 451 jeremybenn
          /* Enabling transmit, reset the BD and schedule the Tx controller on
1421
             the next clock cycle. */
1422 450 jeremybenn
          eth->tx_bd_index = 0;
1423 436 julius
          SCHED_ADD (eth_controller_tx_clock, dat, 1);
1424
        }
1425 437 julius
      else if (!TEST_FLAG (value, ETH_MODER, TXEN) &&
1426
               TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN))
1427 451 jeremybenn
        {
1428
          /* Disabling Tx, so stop scheduling the Tx controller. */
1429
          SCHED_FIND_REMOVE (eth_controller_tx_clock, dat);
1430
        }
1431 19 jeremybenn
 
1432 451 jeremybenn
      /* Reset the interface if so requested. */
1433
      if (TEST_FLAG (value, ETH_MODER, RST))
1434
        {
1435
          eth_reset (dat);
1436
        }
1437 19 jeremybenn
 
1438 451 jeremybenn
      eth->regs.moder = value;          /* Update the register */
1439
      break;
1440
 
1441 19 jeremybenn
    case ETH_INT_SOURCE:
1442 437 julius
      eth->regs.int_source &= ~value;
1443 436 julius
 
1444 451 jeremybenn
      /* Clear IRQ line if all interrupt sources have been dealt with
1445
 
1446
         @todo  Is this really right? */
1447 437 julius
      if (!(eth->regs.int_source & eth->regs.int_mask) && eth->int_line_stat)
1448
        {
1449
          clear_interrupt (eth->mac_int);
1450
          eth->int_line_stat = 0;
1451
        }
1452 451 jeremybenn
      break;
1453
 
1454 19 jeremybenn
    case ETH_INT_MASK:
1455
      eth->regs.int_mask = value;
1456 451 jeremybenn
 
1457
      /* If we enable interrupts, the core is not currently processing an
1458
         interrupt, and there is an interrupt pending, then report that
1459
         interrupt.
1460
 
1461
         Otherwise clear down the interrupt.
1462
 
1463
         @todo  Is this really right. */
1464 437 julius
      if ((eth->regs.int_source & eth->regs.int_mask) && !eth->int_line_stat)
1465 451 jeremybenn
        {
1466
          report_interrupt (eth->mac_int);
1467
        }
1468
      else if (eth->int_line_stat)
1469
        {
1470
          clear_interrupt (eth->mac_int);
1471
          eth->int_line_stat = 0;
1472
        }
1473
      break;
1474
 
1475
    case ETH_IPGT:       eth->regs.ipgt         = value; break;
1476
    case ETH_IPGR1:      eth->regs.ipgr1        = value; break;
1477
    case ETH_IPGR2:      eth->regs.ipgr2        = value; break;
1478
    case ETH_PACKETLEN:  eth->regs.packetlen    = value; break;
1479
    case ETH_COLLCONF:   eth->regs.collconf     = value; break;
1480
 
1481 19 jeremybenn
    case ETH_TX_BD_NUM:
1482 443 jeremybenn
      /* When TX_BD_NUM is written, also reset current RX BD index */
1483
      eth->regs.tx_bd_num = value & 0xFF;
1484 451 jeremybenn
      eth->rx_bd_index = eth->regs.tx_bd_num * 2;
1485
      break;
1486
 
1487
    case ETH_CTRLMODER:  eth->regs.controlmoder = value; break;
1488
    case ETH_MIIMODER:   eth->regs.miimoder     = value; break;
1489
 
1490 19 jeremybenn
    case ETH_MIICOMMAND:
1491
      eth->regs.miicommand = value;
1492 428 julius
      /* Perform MIIM transaction, if required */
1493 443 jeremybenn
      eth_miim_trans (eth);
1494 451 jeremybenn
      break;
1495 428 julius
 
1496 451 jeremybenn
    case ETH_MIIADDRESS: eth->regs.miiaddress   = value; break;
1497
    case ETH_MIITX_DATA: eth->regs.miitx_data   = value; break;
1498
    case ETH_MIIRX_DATA: /* Register is R/O */           break;
1499
    case ETH_MIISTATUS:  /* Register is R/O */           break;
1500
 
1501 19 jeremybenn
    case ETH_MAC_ADDR0:
1502 451 jeremybenn
      eth->mac_address[5] =  value        & 0xFF;
1503
      eth->mac_address[4] = (value >>  8) & 0xFF;
1504 450 jeremybenn
      eth->mac_address[3] = (value >> 16) & 0xFF;
1505
      eth->mac_address[2] = (value >> 24) & 0xFF;
1506 451 jeremybenn
      break;
1507
 
1508 19 jeremybenn
    case ETH_MAC_ADDR1:
1509 451 jeremybenn
      eth->mac_address[1] =  value        & 0xFF;
1510
      eth->mac_address[0] = (value >>  8) & 0xFF;
1511
      break;
1512 19 jeremybenn
 
1513 451 jeremybenn
    case ETH_HASH0:      eth->regs.hash0 = value;        break;
1514
    case ETH_HASH1:      eth->regs.hash1 = value;        break;
1515 19 jeremybenn
 
1516 451 jeremybenn
    default:
1517
      if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
1518
        {
1519
          eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value;
1520
        }
1521
      else
1522
        {
1523
          fprintf (stderr,
1524
                   "Warning: eth_write32( 0x%" PRIxADDR " ): Illegal address\n",
1525
                   addr + eth->baseaddr);
1526
        }
1527
      break;
1528 19 jeremybenn
    }
1529 451 jeremybenn
}       /* eth_write32 () */
1530 19 jeremybenn
 
1531
 
1532
/*---------------------------------------------------------------------------*/
1533
/*!Enable or disable the Ethernet interface
1534
 
1535
   @param[in] val  The value to use
1536
   @param[in] dat  The config data structure                                 */
1537
/*---------------------------------------------------------------------------*/
1538
static void
1539
eth_enabled (union param_val  val,
1540
             void            *dat)
1541
{
1542
  struct eth_device *eth = dat;
1543
 
1544
  eth->enabled = val.int_val;
1545
 
1546
}       /* eth_enabled() */
1547
 
1548
 
1549
/*---------------------------------------------------------------------------*/
1550
/*!Set the Ethernet interface base address
1551
 
1552
   @param[in] val  The value to use
1553
   @param[in] dat  The config data structure                                 */
1554
/*---------------------------------------------------------------------------*/
1555
static void
1556
eth_baseaddr (union param_val  val,
1557
              void            *dat)
1558
{
1559
  struct eth_device *eth = dat;
1560
 
1561
  eth->baseaddr = val.addr_val;
1562
 
1563
}       /* eth_baseaddr() */
1564
 
1565
 
1566
/*---------------------------------------------------------------------------*/
1567
/*!Set the Ethernet DMA port
1568
 
1569
   This is not currently supported, so a warning message is printed.
1570
 
1571
   @param[in] val  The value to use
1572
   @param[in] dat  The config data structure                                 */
1573
/*---------------------------------------------------------------------------*/
1574
static void
1575
eth_dma (union param_val  val,
1576
         void            *dat)
1577
{
1578
  struct eth_device *eth = dat;
1579
 
1580
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported\n");
1581
  eth->dma = val.addr_val;
1582
 
1583
}       /* eth_dma() */
1584
 
1585
 
1586
/*---------------------------------------------------------------------------*/
1587
/*!Set the Ethernet IRQ
1588
 
1589
   @param[in] val  The value to use
1590
   @param[in] dat  The config data structure                                 */
1591
/*---------------------------------------------------------------------------*/
1592
static void
1593
eth_irq (union param_val  val,
1594
         void            *dat)
1595
{
1596
  struct eth_device *eth = dat;
1597
 
1598
  eth->mac_int = val.int_val;
1599
 
1600
}       /* eth_irq() */
1601
 
1602
 
1603
/*---------------------------------------------------------------------------*/
1604
/*!Set the Ethernet interface type
1605
 
1606 434 jeremybenn
   Currently two types are supported, file and tap.
1607 19 jeremybenn
 
1608 434 jeremybenn
   @param[in] val  The value to use. Currently "file" and "tap" are supported.
1609 19 jeremybenn
   @param[in] dat  The config data structure                                 */
1610
/*---------------------------------------------------------------------------*/
1611
static void
1612
eth_rtx_type (union param_val  val,
1613
              void            *dat)
1614
{
1615
  struct eth_device *eth = dat;
1616
 
1617 434 jeremybenn
  if (0 == strcasecmp ("file", val.str_val))
1618 19 jeremybenn
    {
1619 434 jeremybenn
      printf ("Ethernet FILE type\n");
1620
      eth->rtx_type = ETH_RTX_FILE;
1621 19 jeremybenn
    }
1622 434 jeremybenn
  else if (0 == strcasecmp ("tap", val.str_val))
1623
    {
1624
      printf ("Ethernet TAP type\n");
1625
      eth->rtx_type = ETH_RTX_TAP;
1626
    }
1627
  else
1628
    {
1629
      fprintf (stderr, "Warning: Unknown Ethernet type: file assumed.\n");
1630
      eth->rtx_type = ETH_RTX_FILE;
1631
    }
1632 19 jeremybenn
}       /* eth_rtx_type() */
1633
 
1634
 
1635
/*---------------------------------------------------------------------------*/
1636
/*!Set the Ethernet DMA Rx channel
1637
 
1638
   External DMA is not currently supported, so a warning message is printed.
1639
 
1640
   @param[in] val  The value to use
1641
   @param[in] dat  The config data structure                                 */
1642
/*---------------------------------------------------------------------------*/
1643
static void
1644
eth_rx_channel (union param_val  val,
1645
                void            *dat)
1646
{
1647
  struct eth_device *eth = dat;
1648
 
1649
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1650
           "Rx channel ignored\n");
1651
  eth->rx_channel = val.int_val;
1652
 
1653
}       /* eth_rx_channel() */
1654
 
1655
 
1656
/*---------------------------------------------------------------------------*/
1657
/*!Set the Ethernet DMA Tx channel
1658
 
1659
   External DMA is not currently supported, so a warning message is printed.
1660
 
1661
   @param[in] val  The value to use
1662
   @param[in] dat  The config data structure                                 */
1663
/*---------------------------------------------------------------------------*/
1664
static void
1665
eth_tx_channel (union param_val  val,
1666
                void            *dat)
1667
{
1668
  struct eth_device *eth = dat;
1669
 
1670
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1671
           "Tx channel ignored\n");
1672
  eth->tx_channel = val.int_val;
1673
 
1674
}       /* eth_tx_channel() */
1675
 
1676
 
1677
/*---------------------------------------------------------------------------*/
1678
/*!Set the Ethernet DMA Rx file
1679
 
1680
   Free any previously allocated value.
1681
 
1682
   @param[in] val  The value to use
1683
   @param[in] dat  The config data structure                                 */
1684
/*---------------------------------------------------------------------------*/
1685
static void
1686
eth_rxfile (union param_val  val,
1687
            void            *dat)
1688
{
1689
  struct eth_device *eth = dat;
1690
 
1691
  if (NULL != eth->rxfile)
1692
    {
1693
      free (eth->rxfile);
1694
      eth->rxfile = NULL;
1695
    }
1696
 
1697
  if (!(eth->rxfile = strdup (val.str_val)))
1698
    {
1699
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1700
      exit (-1);
1701
    }
1702
}       /* eth_rxfile() */
1703
 
1704
 
1705
/*---------------------------------------------------------------------------*/
1706
/*!Set the Ethernet DMA Tx file
1707
 
1708
   Free any previously allocated value.
1709
 
1710
   @param[in] val  The value to use
1711
   @param[in] dat  The config data structure                                 */
1712
/*---------------------------------------------------------------------------*/
1713
static void
1714
eth_txfile (union param_val  val,
1715
            void            *dat)
1716
{
1717
  struct eth_device *eth = dat;
1718
 
1719
  if (NULL != eth->txfile)
1720
    {
1721
      free (eth->txfile);
1722
      eth->txfile = NULL;
1723
    }
1724
 
1725
  if (!(eth->txfile = strdup (val.str_val)))
1726
    {
1727
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1728
      exit (-1);
1729
    }
1730
}       /* eth_txfile() */
1731
 
1732
 
1733
/*---------------------------------------------------------------------------*/
1734 434 jeremybenn
/*!Set the Ethernet TAP device.
1735 19 jeremybenn
 
1736 434 jeremybenn
   If we are not superuser (or do not have CAP_NET_ADMIN priviledges), then we
1737
   must work with a persistent TAP device that is already set up. This option
1738
   specifies the device to user.
1739 19 jeremybenn
 
1740 434 jeremybenn
   @param[in] val  The value to use.
1741 19 jeremybenn
   @param[in] dat  The config data structure                                 */
1742
/*---------------------------------------------------------------------------*/
1743
static void
1744 434 jeremybenn
eth_tap_dev (union param_val  val,
1745
              void            *dat)
1746 19 jeremybenn
{
1747
  struct eth_device *eth = dat;
1748
 
1749 434 jeremybenn
  if (NULL != eth->tap_dev)
1750 19 jeremybenn
    {
1751 434 jeremybenn
      free (eth->tap_dev);
1752
      eth->tap_dev = NULL;
1753 19 jeremybenn
    }
1754
 
1755 434 jeremybenn
  eth->tap_dev = strdup (val.str_val);
1756
 
1757
  if (NULL == eth->tap_dev)
1758 19 jeremybenn
    {
1759 434 jeremybenn
      fprintf (stderr, "ERROR: Peripheral Ethernet: Run out of memory\n");
1760 19 jeremybenn
      exit (-1);
1761
    }
1762 434 jeremybenn
}       /* eth_tap_dev() */
1763 19 jeremybenn
 
1764
 
1765 451 jeremybenn
/*---------------------------------------------------------------------------*/
1766
/*!Set the PHY address
1767
 
1768
   Used to identify different physical interfaces (important for MII).
1769
 
1770
   @param[in] val  The value to use.
1771
   @param[in] dat  The config data structure                                 */
1772
/*---------------------------------------------------------------------------*/
1773 19 jeremybenn
static void
1774 451 jeremybenn
eth_phy_addr (union param_val  val,
1775
              void            *dat)
1776
{
1777
  struct eth_device *eth = dat;
1778
  eth->phy_addr = val.int_val & ETH_MIIADDR_FIAD_MASK;
1779
 
1780
}       /* eth_phy_addr () */
1781
 
1782
 
1783
/*---------------------------------------------------------------------------*/
1784
/*!Enable or disable a dummy CRC
1785
 
1786
   The MAC should not report anything about the CRC back to the core. However
1787
   the hardware implementation of the OpenRISC MAC does, and the Linux drivers
1788
   have been written to expect the value (which they ignore).
1789
 
1790
   Setting this parameter causes a dummy CRC to be added. For consistency with
1791
   the hardware, its default setting is TRUE.
1792
 
1793
   @param[in] val  The value to use
1794
   @param[in] dat  The config data structure                                 */
1795
/*---------------------------------------------------------------------------*/
1796
static void
1797
eth_dummy_crc (union param_val  val,
1798 19 jeremybenn
             void            *dat)
1799
{
1800
  struct eth_device *eth = dat;
1801
 
1802 451 jeremybenn
  eth->dummy_crc = val.int_val;
1803 428 julius
 
1804 451 jeremybenn
}       /* eth_dummy_crc() */
1805
 
1806
 
1807
/*---------------------------------------------------------------------------*/
1808
/*!Set the VAPI id
1809
 
1810
   Used for remote testing of the interface.
1811
 
1812
   @param[in] val  The value to use.
1813
   @param[in] dat  The config data structure                                 */
1814
/*---------------------------------------------------------------------------*/
1815 428 julius
static void
1816 451 jeremybenn
eth_vapi_id (union param_val  val,
1817
             void            *dat)
1818 428 julius
{
1819
  struct eth_device *eth = dat;
1820 451 jeremybenn
  eth->base_vapi_id = val.int_val;
1821 428 julius
 
1822 451 jeremybenn
}       /* eth_vapi_id () */
1823 428 julius
 
1824 451 jeremybenn
 
1825 19 jeremybenn
/*---------------------------------------------------------------------------*/
1826 451 jeremybenn
/*!Start the initialization of a new Ethernet configuration
1827 19 jeremybenn
 
1828
   ALL parameters are set explicitly to default values.                      */
1829
/*---------------------------------------------------------------------------*/
1830
static void *
1831
eth_sec_start (void)
1832
{
1833
  struct eth_device *new = malloc (sizeof (struct eth_device));
1834
 
1835
  if (!new)
1836
    {
1837
      fprintf (stderr, "Peripheral Eth: Run out of memory\n");
1838
      exit (-1);
1839
    }
1840
 
1841
  memset (new, 0, sizeof (struct eth_device));
1842
 
1843
  new->enabled      = 1;
1844
  new->baseaddr     = 0;
1845
  new->dma          = 0;
1846
  new->mac_int      = 0;
1847 437 julius
  new->int_line_stat= 0;
1848 434 jeremybenn
  new->rtx_type     = ETH_RTX_FILE;
1849 19 jeremybenn
  new->rx_channel   = 0;
1850
  new->tx_channel   = 0;
1851 451 jeremybenn
  new->rtx_fd       = -1;
1852 19 jeremybenn
  new->rxfile       = strdup ("eth_rx");
1853
  new->txfile       = strdup ("eth_tx");
1854 434 jeremybenn
  new->tap_dev      = strdup ("");
1855 451 jeremybenn
  new->phy_addr     = 0;
1856
  new->dummy_crc    = 1;
1857 19 jeremybenn
  new->base_vapi_id = 0;
1858
 
1859
  return new;
1860
 
1861 451 jeremybenn
}       /* eth_sec_start () */
1862
 
1863
 
1864
/*---------------------------------------------------------------------------*/
1865
/*!Complete the initialization of a new Ethernet configuration
1866
 
1867
   ALL parameters are set explicitly to default values.                      */
1868
/*---------------------------------------------------------------------------*/
1869 19 jeremybenn
static void
1870
eth_sec_end (void *dat)
1871
{
1872
  struct eth_device *eth = dat;
1873
  struct mem_ops ops;
1874
 
1875
  if (!eth->enabled)
1876
    {
1877
      free (eth->rxfile);
1878
      free (eth->txfile);
1879 434 jeremybenn
      free (eth->tap_dev);
1880 19 jeremybenn
      free (eth);
1881
      return;
1882
    }
1883
 
1884
  memset (&ops, 0, sizeof (struct mem_ops));
1885
 
1886
  ops.readfunc32 = eth_read32;
1887
  ops.writefunc32 = eth_write32;
1888
  ops.read_dat32 = dat;
1889
  ops.write_dat32 = dat;
1890
 
1891
  /* FIXME: Correct delay? */
1892
  ops.delayr = 2;
1893
  ops.delayw = 2;
1894
  reg_mem_area (eth->baseaddr, ETH_ADDR_SPACE, 0, &ops);
1895
  reg_sim_stat (eth_status, dat);
1896
  reg_sim_reset (eth_reset, dat);
1897
 
1898 451 jeremybenn
}       /* eth_sec_end () */
1899 19 jeremybenn
 
1900 451 jeremybenn
 
1901 19 jeremybenn
/*---------------------------------------------------------------------------*/
1902
/*!Register a new Ethernet configuration                                     */
1903
/*---------------------------------------------------------------------------*/
1904
void
1905
reg_ethernet_sec ()
1906
{
1907
  struct config_section *sec =
1908
    reg_config_sec ("ethernet", eth_sec_start, eth_sec_end);
1909
 
1910 224 jeremybenn
  reg_config_param (sec, "enabled",    PARAMT_INT,  eth_enabled);
1911
  reg_config_param (sec, "baseaddr",   PARAMT_ADDR, eth_baseaddr);
1912
  reg_config_param (sec, "dma",        PARAMT_INT,  eth_dma);
1913
  reg_config_param (sec, "irq",        PARAMT_INT,  eth_irq);
1914 434 jeremybenn
  reg_config_param (sec, "rtx_type",   PARAMT_STR,  eth_rtx_type);
1915 224 jeremybenn
  reg_config_param (sec, "rx_channel", PARAMT_INT,  eth_rx_channel);
1916
  reg_config_param (sec, "tx_channel", PARAMT_INT,  eth_tx_channel);
1917
  reg_config_param (sec, "rxfile",     PARAMT_STR,  eth_rxfile);
1918
  reg_config_param (sec, "txfile",     PARAMT_STR,  eth_txfile);
1919 434 jeremybenn
  reg_config_param (sec, "tap_dev",    PARAMT_STR,  eth_tap_dev);
1920 451 jeremybenn
  reg_config_param (sec, "phy_addr",   PARAMT_INT,  eth_phy_addr);
1921
  reg_config_param (sec, "dummy_crc",  PARAMT_INT,  eth_dummy_crc);
1922 224 jeremybenn
  reg_config_param (sec, "vapi_id",    PARAMT_INT,  eth_vapi_id);
1923 19 jeremybenn
 
1924
}       /* reg_ethernet_sec() */

powered by: WebSVN 2.1.0

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