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

Subversion Repositories openrisc

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

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

powered by: WebSVN 2.1.0

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