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

Subversion Repositories openrisc

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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