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

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc1/] [or1ksim/] [peripheral/] [eth.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 696 ivang
/* ethernet.c -- Simulation of Ethernet MAC
2 1748 jeremybenn
 
3 696 ivang
   Copyright (C) 2001 by Erez Volk, erez@opencores.org
4
                         Ivan Guzvinec, ivang@opencores.org
5 1748 jeremybenn
   Copyright (C) 2008 Embecosm Limited
6 696 ivang
 
7 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8 696 ivang
 
9 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
10 696 ivang
 
11 1748 jeremybenn
   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 696 ivang
#include <stdlib.h>
34
#include <stdio.h>
35
#include <sys/types.h>
36 1748 jeremybenn
#include <sys/stat.h>
37
#include <fcntl.h>
38
#include <sys/poll.h>
39
#include <sys/time.h>
40
#include <unistd.h>
41 696 ivang
#include <errno.h>
42 1308 phoenix
#include <netinet/in.h>
43 1748 jeremybenn
#include <sys/ioctl.h>
44
#include <sys/socket.h>
45
#include <net/if.h>
46 696 ivang
 
47 1748 jeremybenn
#ifdef HAVE_ETH_PHY
48
#include <netpacket/packet.h>
49
#endif /* HAVE_ETH_PHY */
50 1350 nogj
 
51 1748 jeremybenn
#ifdef HAVE_NET_ETHERNET_H
52
# include <net/ethernet.h>
53
#elif defined(HAVE_SYS_ETHERNET_H)
54
# include <sys/ethernet.h>
55
#else /* !HAVE_NET_ETHERNET_H && !HAVE_SYS_ETHERNET_H - */
56
#include <sys/types.h>
57 1350 nogj
#endif
58
 
59 1748 jeremybenn
/* Package includes */
60 1350 nogj
#include "arch.h"
61
#include "config.h"
62 696 ivang
#include "abstract.h"
63 1748 jeremybenn
#include "eth.h"
64 696 ivang
#include "dma.h"
65
#include "sim-config.h"
66
#include "fields.h"
67
#include "crc32.h"
68 889 ivang
#include "vapi.h"
69 1308 phoenix
#include "pic.h"
70 1372 nogj
#include "sched.h"
71 1308 phoenix
#include "debug.h"
72 1748 jeremybenn
#include "toplevel-support.h"
73
#include "sim-cmd.h"
74 696 ivang
 
75 1748 jeremybenn
/* Address space required by one Ethernet MAC */
76
#define ETH_ADDR_SPACE 0x1000
77 1463 nogj
 
78 1748 jeremybenn
/* Relative Register Addresses */
79
#define ETH_MODER       (4 * 0x00)
80
#define ETH_INT_SOURCE  (4 * 0x01)
81
#define ETH_INT_MASK    (4 * 0x02)
82
#define ETH_IPGT        (4 * 0x03)
83
#define ETH_IPGR1       (4 * 0x04)
84
#define ETH_IPGR2       (4 * 0x05)
85
#define ETH_PACKETLEN   (4 * 0x06)
86
#define ETH_COLLCONF    (4 * 0x07)
87
#define ETH_TX_BD_NUM   (4 * 0x08)
88
#define ETH_CTRLMODER   (4 * 0x09)
89
#define ETH_MIIMODER    (4 * 0x0A)
90
#define ETH_MIICOMMAND  (4 * 0x0B)
91
#define ETH_MIIADDRESS  (4 * 0x0C)
92
#define ETH_MIITX_DATA  (4 * 0x0D)
93
#define ETH_MIIRX_DATA  (4 * 0x0E)
94
#define ETH_MIISTATUS   (4 * 0x0F)
95
#define ETH_MAC_ADDR0   (4 * 0x10)
96
#define ETH_MAC_ADDR1   (4 * 0x11)
97
#define ETH_HASH0       (4 * 0x12)
98
#define ETH_HASH1       (4 * 0x13)
99
 
100
/* Where BD's are stored */
101
#define ETH_BD_BASE        0x400
102
#define ETH_BD_COUNT       0x100
103
#define ETH_BD_SPACE       (4 * ETH_BD_COUNT)
104
 
105
/* Where to point DMA to transmit/receive */
106
#define ETH_DMA_RX_TX      0x800
107
 
108
/* Field definitions for MODER */
109
#define ETH_MODER_DMAEN_OFFSET     17
110
#define ETH_MODER_RECSMALL_OFFSET  16
111
#define ETH_MODER_PAD_OFFSET       15
112
#define ETH_MODER_HUGEN_OFFSET     14
113
#define ETH_MODER_CRCEN_OFFSET     13
114
#define ETH_MODER_DLYCRCEN_OFFSET  12
115
#define ETH_MODER_RST_OFFSET       11
116
#define ETH_MODER_FULLD_OFFSET     10
117
#define ETH_MODER_EXDFREN_OFFSET   9
118
#define ETH_MODER_NOBCKOF_OFFSET   8
119
#define ETH_MODER_LOOPBCK_OFFSET   7
120
#define ETH_MODER_IFG_OFFSET       6
121
#define ETH_MODER_PRO_OFFSET       5
122
#define ETH_MODER_IAM_OFFSET       4
123
#define ETH_MODER_BRO_OFFSET       3
124
#define ETH_MODER_NOPRE_OFFSET     2
125
#define ETH_MODER_TXEN_OFFSET      1
126
#define ETH_MODER_RXEN_OFFSET      0
127
 
128
/* Field definitions for INT_SOURCE */
129
#define ETH_INT_SOURCE_RXC_OFFSET  6
130
#define ETH_INT_SOURCE_TXC_OFFSET  5
131
#define ETH_INT_SOURCE_BUSY_OFFSET 4
132
#define ETH_INT_SOURCE_RXE_OFFSET  3
133
#define ETH_INT_SOURCE_RXB_OFFSET  2
134
#define ETH_INT_SOURCE_TXE_OFFSET  1
135
#define ETH_INT_SOURCE_TXB_OFFSET  0
136
 
137
/* Field definitions for INT_MASK */
138
#define ETH_INT_MASK_RXC_M_OFFSET  6
139
#define ETH_INT_MASK_TXC_M_OFFSET  5
140
#define ETH_INT_MASK_BUSY_M_OFFSET 4
141
#define ETH_INT_MASK_RXE_M_OFFSET  3
142
#define ETH_INT_MASK_RXB_M_OFFSET  2
143
#define ETH_INT_MASK_TXE_M_OFFSET  1
144
#define ETH_INT_MASK_TXB_M_OFFSET  0
145
 
146
/* Field definitions for PACKETLEN */
147
#define ETH_PACKETLEN_MINFL_OFFSET 16
148
#define ETH_PACKETLEN_MINFL_WIDTH  16
149
#define ETH_PACKETLEN_MAXFL_OFFSET 0
150
#define ETH_PACKETLEN_MAXFL_WIDTH  16
151
 
152
/* Field definitions for COLLCONF */
153
#define ETH_COLLCONF_MAXRET_OFFSET 16
154
#define ETH_COLLCONF_MAXRET_WIDTH  4
155
#define ETH_COLLCONF_COLLVALID_OFFSET 0
156
#define ETH_COLLCONF_COLLVALID_WIDTH  6
157
 
158
/* Field definitions for CTRLMODER */
159
#define ETH_CMODER_TXFLOW_OFFSET   2
160
#define ETH_CMODER_RXFLOW_OFFSET   1
161
#define ETH_CMODER_PASSALL_OFFSET  0
162
 
163
/* Field definitions for MIIMODER */
164
#define ETH_MIIMODER_MRST_OFFSET   9
165
#define ETH_MIIMODER_NOPRE_OFFSET  8
166
#define ETH_MIIMODER_CLKDIV_OFFSET 0
167
#define ETH_MIIMODER_CLKDIV_WIDTH  8
168
 
169
/* Field definitions for MIICOMMAND */
170
#define ETH_MIICOMM_WCDATA_OFFSET  2
171
#define ETH_MIICOMM_RSTAT_OFFSET   1
172
#define ETH_MIICOMM_SCANS_OFFSET   0
173
 
174
/* Field definitions for MIIADDRESS */
175
#define ETH_MIIADDR_RGAD_OFFSET    8
176
#define ETH_MIIADDR_RGAD_WIDTH     5
177
#define ETH_MIIADDR_FIAD_OFFSET    0
178
#define ETH_MIIADDR_FIAD_WIDTH     5
179
 
180
/* Field definitions for MIISTATUS */
181
#define ETH_MIISTAT_NVALID_OFFSET  1
182
#define ETH_MIISTAT_BUSY_OFFSET    1
183
#define ETH_MIISTAT_FAIL_OFFSET    0
184
 
185
/* Field definitions for TX buffer descriptors */
186
#define ETH_TX_BD_LENGTH_OFFSET        16
187
#define ETH_TX_BD_LENGTH_WIDTH         16
188
#define ETH_TX_BD_READY_OFFSET         15
189
#define ETH_TX_BD_IRQ_OFFSET           14
190
#define ETH_TX_BD_WRAP_OFFSET          13
191
#define ETH_TX_BD_PAD_OFFSET           12
192
#define ETH_TX_BD_CRC_OFFSET           11
193
#define ETH_TX_BD_LAST_OFFSET          10
194
#define ETH_TX_BD_PAUSE_OFFSET         9
195
#define ETH_TX_BD_UNDERRUN_OFFSET      8
196
#define ETH_TX_BD_RETRY_OFFSET         4
197
#define ETH_TX_BD_RETRY_WIDTH          4
198
#define ETH_TX_BD_RETRANSMIT_OFFSET    3
199
#define ETH_TX_BD_COLLISION_OFFSET     2
200
#define ETH_TX_BD_DEFER_OFFSET         1
201
#define ETH_TX_BD_NO_CARRIER_OFFSET    0
202
 
203
 
204
/* Field definitions for RX buffer descriptors */
205
#define ETH_RX_BD_LENGTH_OFFSET        16
206
#define ETH_RX_BD_LENGTH_WIDTH         16
207
#define ETH_RX_BD_READY_OFFSET         15
208
#define ETH_RX_BD_IRQ_OFFSET           14
209
#define ETH_RX_BD_WRAP_OFFSET          13
210
#define ETH_RX_BD_MISS_OFFSET          7
211
#define ETH_RX_BD_UVERRUN_OFFSET       6
212
#define ETH_RX_BD_INVALID_OFFSET       5
213
#define ETH_RX_BD_DRIBBLE_OFFSET       4
214
#define ETH_RX_BD_TOOBIG_OFFSET        3
215
#define ETH_RX_BD_TOOSHORT_OFFSET      2
216
#define ETH_RX_BD_CRC_OFFSET           1
217
#define ETH_RX_BD_COLLISION_OFFSET     0
218
 
219
/*
220
 * Ethernet protocol definitions
221
 */
222
#ifdef HAVE_NET_ETHERNET_H
223
#elif defined(HAVE_SYS_ETHERNET_H)
224
#ifndef ETHER_ADDR_LEN
225
#define ETHER_ADDR_LEN ETHERADDRL
226
#endif
227
#ifndef ETHER_HDR_LEN
228
#define ETHER_HDR_LEN sizeof(struct ether_header)
229
#endif
230
#else /* !HAVE_NET_ETHERNET_H && !HAVE_SYS_ETHERNET_H - */
231
#ifdef __CYGWIN__
232
/* define some missing cygwin defines.
233
 *
234
 * NOTE! there is no nonblocking socket option implemented in cygwin.dll
235
 *       so defining MSG_DONTWAIT is just (temporary) workaround !!!
236
 */
237
#define MSG_DONTWAIT  0x40
238
#define ETH_HLEN      14
239
#endif /* __CYGWIN__ */
240
 
241
#define ETH_ALEN    6
242
 
243
struct ether_addr
244
{
245
  u_int8_t ether_addr_octet[ETH_ALEN];
246
};
247
 
248
struct ether_header
249
{
250
  u_int8_t ether_dhost[ETH_ALEN];       /* destination eth addr */
251
  u_int8_t ether_shost[ETH_ALEN];       /* source ether addr    */
252
  u_int16_t ether_type;         /* packet type ID field */
253
};
254
 
255
/* Ethernet protocol ID's */
256
#define ETHERTYPE_PUP           0x0200  /* Xerox PUP */
257
#define ETHERTYPE_IP            0x0800  /* IP */
258
#define ETHERTYPE_ARP           0x0806  /* Address resolution */
259
#define ETHERTYPE_REVARP        0x8035  /* Reverse ARP */
260
 
261
#define ETHER_ADDR_LEN  ETH_ALEN        /* size of ethernet addr */
262
#define ETHER_TYPE_LEN  2       /* bytes in type field */
263
#define ETHER_CRC_LEN   4       /* bytes in CRC field */
264
#define ETHER_HDR_LEN   ETH_HLEN        /* total octets in header */
265
#define ETHER_MIN_LEN   (ETH_ZLEN + ETHER_CRC_LEN)      /* min packet length */
266
#define ETHER_MAX_LEN   (ETH_FRAME_LEN + ETHER_CRC_LEN) /* max packet length */
267
 
268
/* make sure ethenet length is valid */
269
#define ETHER_IS_VALID_LEN(foo) \
270
        ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
271
 
272
/*
273
 * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
274
 * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
275
 * by an ETHER type (as given above) and then the (variable-length) header.
276
 */
277
#define ETHERTYPE_TRAIL         0x1000  /* Trailer packet */
278
#define ETHERTYPE_NTRAILER      16
279
 
280
#define ETHERMTU        ETH_DATA_LEN
281
#define ETHERMIN        (ETHER_MIN_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
282
 
283
#endif /* HAVE_NET_ETHERNET_H */
284
 
285
/*
286
 * Implementatino of Ethernet MAC Registers and State
287
 */
288
#define ETH_TXSTATE_IDLE        0
289
#define ETH_TXSTATE_WAIT4BD     10
290
#define ETH_TXSTATE_READFIFO    20
291
#define ETH_TXSTATE_TRANSMIT    30
292
 
293
#define ETH_RXSTATE_IDLE        0
294
#define ETH_RXSTATE_WAIT4BD     10
295
#define ETH_RXSTATE_RECV        20
296
#define ETH_RXSTATE_WRITEFIFO   30
297
 
298
#define ETH_RTX_FILE    0
299
#define ETH_RTX_SOCK    1
300
#define ETH_RTX_VAPI    2
301
 
302
#define ETH_MAXPL   0x10000
303
 
304
enum
305
{ ETH_VAPI_DATA = 0,
306
  ETH_VAPI_CTRL,
307
  ETH_NUM_VAPI_IDS
308
};
309
 
310
struct eth_device
311
{
312
  /* Is peripheral enabled */
313
  int enabled;
314
 
315
  /* Base address in memory */
316
  oraddr_t baseaddr;
317
 
318
  /* Which DMA controller is this MAC connected to */
319
  unsigned dma;
320
  unsigned tx_channel;
321
  unsigned rx_channel;
322
 
323
  /* Our address */
324
  unsigned char mac_address[ETHER_ADDR_LEN];
325
 
326
  /* interrupt line */
327
  unsigned long mac_int;
328
 
329
  /* VAPI ID */
330
  unsigned long base_vapi_id;
331
 
332
  /* RX and TX file names and handles */
333
  char *rxfile, *txfile;
334
  int txfd;
335
  int rxfd;
336
  off_t loopback_offset;
337
 
338
  /* Socket interface name */
339
  char *sockif;
340
 
341
  int rtx_sock;
342
  int rtx_type;
343
  struct ifreq ifr;
344
  fd_set rfds, wfds;
345
 
346
  /* Current TX state */
347
  struct
348
  {
349
    unsigned long state;
350
    unsigned long bd_index;
351
    unsigned long bd;
352
    unsigned long bd_addr;
353
    unsigned working, waiting_for_dma, error;
354
    long packet_length;
355
    unsigned minimum_length, maximum_length;
356
    unsigned add_crc;
357
    unsigned crc_dly;
358
    unsigned long crc_value;
359
    long bytes_left, bytes_sent;
360
  } tx;
361
 
362
  /* Current RX state */
363
  struct
364
  {
365
    unsigned long state;
366
    unsigned long bd_index;
367
    unsigned long bd;
368
    unsigned long bd_addr;
369
    int fd;
370
    off_t *offset;
371
    unsigned working, error, waiting_for_dma;
372
    long packet_length, bytes_read, bytes_left;
373
  } rx;
374
 
375
  /* Visible registers */
376
  struct
377
  {
378
    unsigned long moder;
379
    unsigned long int_source;
380
    unsigned long int_mask;
381
    unsigned long ipgt;
382
    unsigned long ipgr1;
383
    unsigned long ipgr2;
384
    unsigned long packetlen;
385
    unsigned long collconf;
386
    unsigned long tx_bd_num;
387
    unsigned long controlmoder;
388
    unsigned long miimoder;
389
    unsigned long miicommand;
390
    unsigned long miiaddress;
391
    unsigned long miitx_data;
392
    unsigned long miirx_data;
393
    unsigned long miistatus;
394
    unsigned long hash0;
395
    unsigned long hash1;
396
 
397
    /* Buffer descriptors */
398
    unsigned long bd_ram[ETH_BD_SPACE / 4];
399
  } regs;
400
 
401
  unsigned char rx_buff[ETH_MAXPL];
402
  unsigned char tx_buff[ETH_MAXPL];
403
  unsigned char lo_buff[ETH_MAXPL];
404
};
405
 
406
 
407
DEFAULT_DEBUG_CHANNEL (eth);
408
 
409 702 ivang
/* simulator interface */
410 1748 jeremybenn
static void eth_vapi_read (unsigned long id, unsigned long data, void *dat);
411 696 ivang
/* register interface */
412 1748 jeremybenn
static void eth_write32 (oraddr_t addr, uint32_t value, void *dat);
413
static uint32_t eth_read32 (oraddr_t addr, void *dat);
414 696 ivang
/* clock */
415 1748 jeremybenn
static void eth_controller_tx_clock (void *);
416
static void eth_controller_rx_clock (void *);
417 696 ivang
/* utility functions */
418 1748 jeremybenn
static ssize_t eth_read_rx_file (struct eth_device *, void *, size_t);
419
static void eth_skip_rx_file (struct eth_device *, off_t);
420
static void eth_rx_next_packet (struct eth_device *);
421
static void eth_write_tx_bd_num (struct eth_device *, unsigned long value);
422 696 ivang
/* ========================================================================= */
423 702 ivang
/*  TX LOGIC                                                                 */
424 696 ivang
/*---------------------------------------------------------------------------*/
425
 
426
/*
427
 * TX clock
428
 * Responsible for starting and finishing TX
429
 */
430 1748 jeremybenn
static void
431
eth_controller_tx_clock (void *dat)
432 696 ivang
{
433 1748 jeremybenn
  struct eth_device *eth = dat;
434
  int bAdvance = 1;
435 867 markom
#if HAVE_ETH_PHY
436 1748 jeremybenn
  struct sockaddr_ll sll;
437 849 markom
#endif /* HAVE_ETH_PHY */
438 1748 jeremybenn
  long nwritten = 0;
439
  unsigned long read_word;
440 696 ivang
 
441 1748 jeremybenn
  switch (eth->tx.state)
442
    {
443 1372 nogj
    case ETH_TXSTATE_IDLE:
444 1748 jeremybenn
      TRACE ("TX - entering state WAIT4BD (%ld)\n", eth->tx.bd_index);
445
      eth->tx.state = ETH_TXSTATE_WAIT4BD;
446
      break;
447 696 ivang
    case ETH_TXSTATE_WAIT4BD:
448 1748 jeremybenn
      /* Read buffer descriptor */
449
      eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index];
450
      eth->tx.bd_addr = eth->regs.bd_ram[eth->tx.bd_index + 1];
451
 
452
      if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, READY))
453
        {
454
            /*****************/
455
          /* initialize TX */
456
          eth->tx.bytes_left = eth->tx.packet_length =
457
            GET_FIELD (eth->tx.bd, ETH_TX_BD, LENGTH);
458
          eth->tx.bytes_sent = 0;
459
 
460
          /*   Initialize error status bits */
461
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, DEFER);
462
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION);
463
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, RETRANSMIT);
464
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, UNDERRUN);
465
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, NO_CARRIER);
466
          SET_FIELD (eth->tx.bd, ETH_TX_BD, RETRY, 0);
467
 
468
          /* Find out minimum length */
469
          if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, PAD) ||
470
              TEST_FLAG (eth->regs.moder, ETH_MODER, PAD))
471
            eth->tx.minimum_length =
472
              GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL);
473
          else
474
            eth->tx.minimum_length = eth->tx.packet_length;
475
 
476
          /* Find out maximum length */
477
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, HUGEN))
478
            eth->tx.maximum_length = eth->tx.packet_length;
479
          else
480
            eth->tx.maximum_length =
481
              GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MAXFL);
482
 
483
          /* Do we need CRC on this packet? */
484
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, CRCEN) ||
485
              (TEST_FLAG (eth->tx.bd, ETH_TX_BD, CRC) &&
486
               TEST_FLAG (eth->tx.bd, ETH_TX_BD, LAST)))
487
            eth->tx.add_crc = 1;
488
          else
489
            eth->tx.add_crc = 0;
490
 
491
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, DLYCRCEN))
492
            eth->tx.crc_dly = 1;
493
          else
494
            eth->tx.crc_dly = 0;
495
          /* XXX - For now we skip CRC calculation */
496
 
497
          TRACE ("Ethernet: Starting TX of %lu bytes (min. %u, max. %u)\n",
498
                 eth->tx.packet_length, eth->tx.minimum_length,
499
                 eth->tx.maximum_length);
500
 
501
          if (eth->rtx_type == ETH_RTX_FILE)
502
            {
503
              /* write packet length to file */
504
              nwritten =
505
                write (eth->txfd, &(eth->tx.packet_length),
506
                       sizeof (eth->tx.packet_length));
507
            }
508
 
509
            /************************************************/
510
          /* start transmit with reading packet into FIFO */
511
          TRACE ("TX - entering state READFIFO\n");
512
          eth->tx.state = ETH_TXSTATE_READFIFO;
513
        }
514
 
515
      /* stay in this state if (TXEN && !READY) */
516
      break;
517 696 ivang
    case ETH_TXSTATE_READFIFO:
518 744 simons
#if 1
519 1748 jeremybenn
      if (eth->tx.bytes_sent < eth->tx.packet_length)
520
        {
521
          read_word =
522
            eval_direct32 (eth->tx.bytes_sent + eth->tx.bd_addr, 0, 0);
523
          eth->tx_buff[eth->tx.bytes_sent] =
524
            (unsigned char) (read_word >> 24);
525
          eth->tx_buff[eth->tx.bytes_sent + 1] =
526
            (unsigned char) (read_word >> 16);
527
          eth->tx_buff[eth->tx.bytes_sent + 2] =
528
            (unsigned char) (read_word >> 8);
529
          eth->tx_buff[eth->tx.bytes_sent + 3] = (unsigned char) (read_word);
530
          eth->tx.bytes_sent += 4;
531
        }
532 744 simons
#else
533 1748 jeremybenn
      if (eth->tx.bytes_sent < eth->tx.packet_length)
534
        {
535
          eth->tx_buff[eth->tx.bytes_sent] =
536
            eval_direct8 (eth->tx.bytes_sent + eth->tx.bd_addr, 0, 0);
537
          eth->tx.bytes_sent += 1;
538
        }
539 744 simons
#endif
540 1748 jeremybenn
      else
541
        {
542
          TRACE ("TX - entering state TRANSMIT\n");
543
          eth->tx.state = ETH_TXSTATE_TRANSMIT;
544
        }
545
      break;
546 696 ivang
    case ETH_TXSTATE_TRANSMIT:
547 1748 jeremybenn
      /* send packet */
548
      switch (eth->rtx_type)
549
        {
550
        case ETH_RTX_FILE:
551
          nwritten = write (eth->txfd, eth->tx_buff, eth->tx.packet_length);
552
          break;
553 867 markom
#if HAVE_ETH_PHY
554 1748 jeremybenn
        case ETH_RTX_SOCK:
555
          memset (&sll, 0, sizeof (sll));
556
          sll.sll_ifindex = eth->ifr.ifr_ifindex;
557
          nwritten =
558
            sendto (eth->rtx_sock, eth->tx_buff, eth->tx.packet_length, 0,
559
                    (struct sockaddr *) &sll, sizeof (sll));
560 849 markom
#endif /* HAVE_ETH_PHY */
561 1748 jeremybenn
        }
562
 
563
      /* set BD status */
564
      if (nwritten == eth->tx.packet_length)
565
        {
566
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
567
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB);
568
          TRACE ("ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
569
 
570
          TRACE ("TX - entering state WAIT4BD\n");
571
          eth->tx.state = ETH_TXSTATE_WAIT4BD;
572
          TRACE ("send (%ld)bytes OK\n", nwritten);
573
        }
574
      else
575
        {
576
          /* XXX - implement retry mechanism here! */
577
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY);
578
          CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION);
579
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE);
580
          TRACE ("ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
581
 
582
          TRACE ("TX - entering state WAIT4BD\n");
583
          eth->tx.state = ETH_TXSTATE_WAIT4BD;
584
          TRACE ("send FAILED!\n");
585
        }
586
 
587
      eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd;
588
 
589
      /* generate OK interrupt */
590
      if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, TXE_M) ||
591
          TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, TXB_M))
592
        {
593
          if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, IRQ))
594
            report_interrupt (eth->mac_int);
595
        }
596
 
597
      /* advance to next BD */
598
      if (bAdvance)
599
        {
600
          if (TEST_FLAG (eth->tx.bd, ETH_TX_BD, WRAP) ||
601
              eth->tx.bd_index >= ETH_BD_COUNT)
602
            eth->tx.bd_index = 0;
603
          else
604
            eth->tx.bd_index += 2;
605
        }
606
 
607
      break;
608 696 ivang
    }
609 1372 nogj
 
610 1748 jeremybenn
  /* Reschedule */
611
  SCHED_ADD (eth_controller_tx_clock, dat, 1);
612 696 ivang
}
613 1748 jeremybenn
 
614 696 ivang
/* ========================================================================= */
615
 
616
 
617
/* ========================================================================= */
618 702 ivang
/*  RX LOGIC                                                                 */
619 696 ivang
/*---------------------------------------------------------------------------*/
620
 
621
/*
622
 * RX clock
623
 * Responsible for starting and finishing RX
624
 */
625 1748 jeremybenn
static void
626
eth_controller_rx_clock (void *dat)
627 696 ivang
{
628 1748 jeremybenn
  struct eth_device *eth = dat;
629
  long nread;
630
  unsigned long send_word;
631
 
632
 
633
  switch (eth->rx.state)
634
    {
635 696 ivang
    case ETH_RXSTATE_IDLE:
636 1748 jeremybenn
      TRACE ("RX - entering state WAIT4BD (%ld)\n", eth->rx.bd_index);
637
      eth->rx.state = ETH_RXSTATE_WAIT4BD;
638
      break;
639
 
640 696 ivang
    case ETH_RXSTATE_WAIT4BD:
641 1748 jeremybenn
      eth->rx.bd = eth->regs.bd_ram[eth->rx.bd_index];
642
      eth->rx.bd_addr = eth->regs.bd_ram[eth->rx.bd_index + 1];
643
 
644
      if (TEST_FLAG (eth->rx.bd, ETH_RX_BD, READY))
645
        {
646
            /*****************/
647
          /* Initialize RX */
648
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, MISS);
649
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, INVALID);
650
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, DRIBBLE);
651
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, UVERRUN);
652
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, COLLISION);
653
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
654
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
655
 
656
          TRACE ("Ethernet: Starting RX\n");
657
 
658
          /* Setup file to read from */
659
          if (TEST_FLAG (eth->regs.moder, ETH_MODER, LOOPBCK))
660
            {
661
              eth->rx.fd = eth->txfd;
662
              eth->rx.offset = &(eth->loopback_offset);
663
            }
664
          else
665
            {
666
              eth->rx.fd = eth->rxfd;
667
              eth->rx.offset = 0;
668
            }
669
          TRACE ("RX - entering state RECV\n");
670
          eth->rx.state = ETH_RXSTATE_RECV;
671
        }
672
      else if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN))
673
        {
674 1463 nogj
          TRACE ("RX - entering state IDLE\n");
675 705 ivang
          eth->rx.state = ETH_RXSTATE_IDLE;
676
        }
677 1748 jeremybenn
      else
678
        {
679
          nread =
680
            recv (eth->rtx_sock, eth->rx_buff, ETH_MAXPL, /*MSG_PEEK | */
681
                  MSG_DONTWAIT);
682
          if (nread > 0)
683
            {
684
              SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY);
685
              if (TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, BUSY_M))
686
                report_interrupt (eth->mac_int);
687
            }
688
        }
689
      break;
690
 
691 696 ivang
    case ETH_RXSTATE_RECV:
692 1748 jeremybenn
      switch (eth->rtx_type)
693
        {
694
        case ETH_RTX_FILE:
695
          /* Read packet length */
696
          if (eth_read_rx_file
697
              (eth, &(eth->rx.packet_length),
698
               sizeof (eth->rx.packet_length)) <
699
              sizeof (eth->rx.packet_length))
700
            {
701
              /* TODO: just do what real ethernet would do (some kind of error state) */
702
              TRACE
703
                ("eth_start_rx(): File does not have a packet ready for RX (len = %ld)\n",
704
                 eth->rx.packet_length);
705
              sim_done ();
706
              break;
707
            }
708 702 ivang
 
709 1748 jeremybenn
          /* Packet must be big enough to hold a header */
710
          if (eth->rx.packet_length < ETHER_HDR_LEN)
711
            {
712
              TRACE ("eth_start_rx(): Packet too small\n");
713
              eth_rx_next_packet (eth);
714 702 ivang
 
715 1748 jeremybenn
              TRACE ("RX - entering state WAIT4BD\n");
716
              eth->rx.state = ETH_RXSTATE_WAIT4BD;
717
              break;
718
            }
719 844 ivang
 
720 1748 jeremybenn
          eth->rx.bytes_read = 0;
721
          eth->rx.bytes_left = eth->rx.packet_length;
722 844 ivang
 
723 1748 jeremybenn
          /* for now Read entire packet into memory */
724
          nread = eth_read_rx_file (eth, eth->rx_buff, eth->rx.bytes_left);
725
          if (nread < eth->rx.bytes_left)
726
            {
727
              TRACE ("Read %ld from %ld. Error!\n", nread,
728
                     eth->rx.bytes_left);
729
              eth->rx.error = 1;
730
              break;
731
            }
732 744 simons
 
733 1748 jeremybenn
          eth->rx.packet_length = nread;
734
          eth->rx.bytes_left = nread;
735
          eth->rx.bytes_read = 0;
736
 
737
          TRACE ("RX - entering state WRITEFIFO\n");
738
          eth->rx.state = ETH_RXSTATE_WRITEFIFO;
739
 
740
          break;
741
 
742
        case ETH_RTX_SOCK:
743
          nread = recv (eth->rtx_sock, eth->rx_buff, ETH_MAXPL, MSG_DONTWAIT);
744
 
745
          if (nread == 0)
746
            {
747
              TRACE ("No data read\n");
748
              break;
749
            }
750
          else if (nread < 0)
751
            {
752
              if (errno != EAGAIN)
753
                {
754
                  TRACE ("recv() FAILED!\n");
755
                  break;
756
                }
757
              else
758 744 simons
                break;
759 1748 jeremybenn
            }
760
          /* If not promiscouos mode, check the destination address */
761
          if (!TEST_FLAG (eth->regs.moder, ETH_MODER, PRO))
762
            {
763
              if (TEST_FLAG (eth->regs.moder, ETH_MODER, IAM)
764
                  && (eth->rx_buff[0] & 1))
765
                {
766
                  /* Nothing for now */
767
                }
768 744 simons
 
769 1748 jeremybenn
              if (eth->mac_address[5] != eth->rx_buff[0] ||
770
                  eth->mac_address[4] != eth->rx_buff[1] ||
771
                  eth->mac_address[3] != eth->rx_buff[2] ||
772
                  eth->mac_address[2] != eth->rx_buff[3] ||
773
                  eth->mac_address[1] != eth->rx_buff[4] ||
774
                  eth->mac_address[0] != eth->rx_buff[5])
775
                break;
776
            }
777
 
778
          eth->rx.packet_length = nread;
779
          eth->rx.bytes_left = nread;
780
          eth->rx.bytes_read = 0;
781
 
782
          TRACE ("RX - entering state WRITEFIFO\n");
783
          eth->rx.state = ETH_RXSTATE_WRITEFIFO;
784
 
785
          break;
786 889 ivang
        case ETH_RTX_VAPI:
787 1748 jeremybenn
          break;
788
        }
789
      break;
790
 
791 696 ivang
    case ETH_RXSTATE_WRITEFIFO:
792 744 simons
#if 1
793 1748 jeremybenn
      send_word = ((unsigned long) eth->rx_buff[eth->rx.bytes_read] << 24) |
794
        ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 1] << 16) |
795
        ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 2] << 8) |
796
        ((unsigned long) eth->rx_buff[eth->rx.bytes_read + 3]);
797
      set_direct32 (eth->rx.bd_addr + eth->rx.bytes_read, send_word, 0, 0);
798
      /* update counters */
799
      TRACE ("Write %ld, left %ld - %08lXd\n", eth->rx.bytes_read,
800
             eth->rx.bytes_left, send_word);
801
      eth->rx.bytes_left -= 4;
802
      eth->rx.bytes_read += 4;
803 744 simons
#else
804 1748 jeremybenn
      set_direct8 (eth->rx.bd_addr + eth->rx.bytes_read,
805
                   eth->rx_buff[eth->rx.bytes_read], 0, 0);
806
      eth->rx.bytes_left -= 1;
807
      eth->rx.bytes_read += 1;
808 744 simons
#endif
809 1748 jeremybenn
 
810
      if (eth->rx.bytes_left <= 0)
811
        {
812
          /* Write result to bd */
813
          SET_FIELD (eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length);
814
          CLEAR_FLAG (eth->rx.bd, ETH_RX_BD, READY);
815
          SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, RXB);
816
          TRACE ("ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
817
 
818
          if (eth->rx.packet_length <
819
              (GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MINFL) - 4))
820
            SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOSHORT);
821
          if (eth->rx.packet_length >
822
              GET_FIELD (eth->regs.packetlen, ETH_PACKETLEN, MAXFL))
823
            SET_FLAG (eth->rx.bd, ETH_RX_BD, TOOBIG);
824
 
825
          eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd;
826
 
827
          /* advance to next BD */
828
          if (TEST_FLAG (eth->rx.bd, ETH_RX_BD, WRAP)
829
              || eth->rx.bd_index >= ETH_BD_COUNT)
830
            eth->rx.bd_index = eth->regs.tx_bd_num << 1;
831
          else
832
            eth->rx.bd_index += 2;
833
 
834
          if ((TEST_FLAG (eth->regs.int_mask, ETH_INT_MASK, RXB_M)) &&
835
              (TEST_FLAG (eth->rx.bd, ETH_RX_BD, IRQ)))
836
            {
837
              report_interrupt (eth->mac_int);
838
            }
839
 
840
          /* ready to receive next packet */
841
          TRACE ("RX - entering state IDLE\n");
842
          eth->rx.state = ETH_RXSTATE_IDLE;
843
        }
844
      break;
845 696 ivang
    }
846 1748 jeremybenn
 
847
  /* Reschedule */
848
  SCHED_ADD (eth_controller_rx_clock, dat, 1);
849 696 ivang
}
850 702 ivang
 
851 696 ivang
/* ========================================================================= */
852 702 ivang
/* Move to next RX BD */
853 1748 jeremybenn
static void
854
eth_rx_next_packet (struct eth_device *eth)
855 702 ivang
{
856 1748 jeremybenn
  /* Skip any possible leftovers */
857
  if (eth->rx.bytes_left)
858
    eth_skip_rx_file (eth, eth->rx.bytes_left);
859 702 ivang
}
860 1748 jeremybenn
 
861 702 ivang
/* "Skip" bytes in RX file */
862 1748 jeremybenn
static void
863
eth_skip_rx_file (struct eth_device *eth, off_t count)
864 702 ivang
{
865 1748 jeremybenn
  eth->rx.offset += count;
866 702 ivang
}
867 696 ivang
 
868 702 ivang
/*
869
 * Utility function to read from the ethernet RX file
870
 * This function moves the file pointer to the current place in the packet before reading
871
 */
872 1748 jeremybenn
static ssize_t
873
eth_read_rx_file (struct eth_device *eth, void *buf, size_t count)
874 702 ivang
{
875 1748 jeremybenn
  ssize_t result;
876
 
877
  if (eth->rx.fd <= 0)
878
    {
879
      TRACE ("Ethernet: No RX file\n");
880
      return 0;
881 702 ivang
    }
882 696 ivang
 
883 1748 jeremybenn
  if (eth->rx.offset)
884
    if (lseek (eth->rx.fd, *(eth->rx.offset), SEEK_SET) == (off_t) - 1)
885
      {
886
        TRACE ("Ethernet: Error seeking RX file\n");
887
        return 0;
888
      }
889
 
890
  result = read (eth->rx.fd, buf, count);
891
  TRACE ("Ethernet: read result = %d \n", result);
892
  if (eth->rx.offset && result >= 0)
893
    *(eth->rx.offset) += result;
894
 
895
  return result;
896 702 ivang
}
897
 
898
/* ========================================================================= */
899
 
900 696 ivang
/*
901 702 ivang
  Reset. Initializes all registers to default and places devices in
902
         memory address space.
903 696 ivang
*/
904 1748 jeremybenn
static void
905
eth_reset (void *dat)
906 696 ivang
{
907 1748 jeremybenn
  struct eth_device *eth = dat;
908 1308 phoenix
#if HAVE_ETH_PHY
909 1748 jeremybenn
  int j;
910
  struct sockaddr_ll sll;
911 849 markom
#endif /* HAVE_ETH_PHY */
912 1748 jeremybenn
 
913
  if (eth->baseaddr != 0)
914
    {
915
      switch (eth->rtx_type)
916
        {
917
        case ETH_RTX_FILE:
918
          /* (Re-)open TX/RX files */
919
          if (eth->rxfd > 0)
920
            close (eth->rxfd);
921
          if (eth->txfd > 0)
922
            close (eth->txfd);
923
          eth->rxfd = eth->txfd = -1;
924
 
925
          if ((eth->rxfd = open (eth->rxfile, O_RDONLY)) < 0)
926
            fprintf (stderr, "Cannot open Ethernet RX file \"%s\"\n",
927
                     eth->rxfile);
928
          if ((eth->txfd = open (eth->txfile, O_RDWR | O_CREAT | O_APPEND
929
#if defined(O_SYNC)             /* BSD / Mac OS X manual doesn't know about O_SYNC */
930
                                 | O_SYNC
931 1244 hpanther
#endif
932 1748 jeremybenn
                                 ,
933
                                 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0)
934
            fprintf (stderr, "Cannot open Ethernet TX file \"%s\"\n",
935
                     eth->txfile);
936
          eth->loopback_offset = lseek (eth->txfd, 0, SEEK_END);
937
 
938
          break;
939 867 markom
#if HAVE_ETH_PHY
940 1748 jeremybenn
        case ETH_RTX_SOCK:
941
          /* (Re-)open TX/RX sockets */
942
          if (eth->rtx_sock != 0)
943
            break;
944
 
945
          TRACE ("RTX opening socket...\n");
946
          eth->rtx_sock = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL));
947
          if (eth->rtx_sock == -1)
948
            {
949
              fprintf (stderr, "Cannot open rtx_sock.\n");
950
              return;
951
            }
952
 
953
          /* get interface index number */
954
          TRACE ("RTX getting interface...\n");
955
          memset (&(eth->ifr), 0, sizeof (eth->ifr));
956
          strncpy (eth->ifr.ifr_name, eth->sockif, IFNAMSIZ);
957
          if (ioctl (eth->rtx_sock, SIOCGIFINDEX, &(eth->ifr)) == -1)
958
            {
959
              fprintf (stderr, "SIOCGIFINDEX failed!\n");
960
              return;
961
            }
962
          TRACE ("RTX Socket Interface : %d\n", eth->ifr.ifr_ifindex);
963
 
964
          /* Bind to interface... */
965
          TRACE ("Binding to the interface ifindex=%d\n",
966
                 eth->ifr.ifr_ifindex);
967
          memset (&sll, 0xff, sizeof (sll));
968
          sll.sll_family = AF_PACKET;   /* allways AF_PACKET */
969
          sll.sll_protocol = htons (ETH_P_ALL);
970
          sll.sll_ifindex = eth->ifr.ifr_ifindex;
971
          if (bind (eth->rtx_sock, (struct sockaddr *) &sll, sizeof (sll)) ==
972
              -1)
973
            {
974
              fprintf (stderr, "Error bind().\n");
975
              return;
976
            }
977
 
978
          /* first, flush all received packets. */
979
          TRACE ("Flush");
980
          do
981
            {
982
              fd_set fds;
983
              struct timeval t;
984
 
985
              TRACE (".");
986
              FD_ZERO (&fds);
987
              FD_SET (eth->rtx_sock, &fds);
988
              memset (&t, 0, sizeof (t));
989
              j = select (FD_SETSIZE, &fds, NULL, NULL, &t);
990
              if (j > 0)
991
                recv (eth->rtx_sock, eth->rx_buff, j, 0);
992
            }
993
          while (j);
994
          TRACE ("\n");
995
 
996
          break;
997 1372 nogj
#else /* HAVE_ETH_PHY */
998 1748 jeremybenn
        case ETH_RTX_SOCK:
999
          fprintf (stderr,
1000
                   "Ethernet phy not enabled in this configuration.  Configure with --enable-ethphy.\n");
1001
          exit (1);
1002
          break;
1003 849 markom
#endif /* HAVE_ETH_PHY */
1004 1748 jeremybenn
        }
1005 889 ivang
 
1006 1748 jeremybenn
      /* Set registers to default values */
1007
      memset (&(eth->regs), 0, sizeof (eth->regs));
1008
      eth->regs.moder = 0x0000A000;
1009
      eth->regs.ipgt = 0x00000012;
1010
      eth->regs.ipgr1 = 0x0000000C;
1011
      eth->regs.ipgr2 = 0x00000012;
1012
      eth->regs.packetlen = 0x003C0600;
1013
      eth->regs.collconf = 0x000F003F;
1014
      eth->regs.miimoder = 0x00000064;
1015
      eth->regs.tx_bd_num = 0x00000040;
1016
 
1017
      /* Initialize TX/RX status */
1018
      memset (&(eth->tx), 0, sizeof (eth->tx));
1019
      memset (&(eth->rx), 0, sizeof (eth->rx));
1020
      eth->rx.bd_index = eth->regs.tx_bd_num << 1;
1021
 
1022
      /* Initialize VAPI */
1023
      if (eth->base_vapi_id)
1024
        {
1025
          vapi_install_multi_handler (eth->base_vapi_id, ETH_NUM_VAPI_IDS,
1026
                                      eth_vapi_read, dat);
1027 889 ivang
        }
1028 702 ivang
    }
1029
}
1030 1748 jeremybenn
 
1031 702 ivang
/* ========================================================================= */
1032
 
1033
 
1034 696 ivang
/*
1035
  Print register values on stdout
1036
*/
1037 1748 jeremybenn
static void
1038
eth_status (void *dat)
1039 696 ivang
{
1040 1748 jeremybenn
  struct eth_device *eth = dat;
1041
 
1042
  PRINTF ("\nEthernet MAC at 0x%" PRIxADDR ":\n", eth->baseaddr);
1043
  PRINTF ("MODER        : 0x%08lX\n", eth->regs.moder);
1044
  PRINTF ("INT_SOURCE   : 0x%08lX\n", eth->regs.int_source);
1045
  PRINTF ("INT_MASK     : 0x%08lX\n", eth->regs.int_mask);
1046
  PRINTF ("IPGT         : 0x%08lX\n", eth->regs.ipgt);
1047
  PRINTF ("IPGR1        : 0x%08lX\n", eth->regs.ipgr1);
1048
  PRINTF ("IPGR2        : 0x%08lX\n", eth->regs.ipgr2);
1049
  PRINTF ("PACKETLEN    : 0x%08lX\n", eth->regs.packetlen);
1050
  PRINTF ("COLLCONF     : 0x%08lX\n", eth->regs.collconf);
1051
  PRINTF ("TX_BD_NUM    : 0x%08lX\n", eth->regs.tx_bd_num);
1052
  PRINTF ("CTRLMODER    : 0x%08lX\n", eth->regs.controlmoder);
1053
  PRINTF ("MIIMODER     : 0x%08lX\n", eth->regs.miimoder);
1054
  PRINTF ("MIICOMMAND   : 0x%08lX\n", eth->regs.miicommand);
1055
  PRINTF ("MIIADDRESS   : 0x%08lX\n", eth->regs.miiaddress);
1056
  PRINTF ("MIITX_DATA   : 0x%08lX\n", eth->regs.miitx_data);
1057
  PRINTF ("MIIRX_DATA   : 0x%08lX\n", eth->regs.miirx_data);
1058
  PRINTF ("MIISTATUS    : 0x%08lX\n", eth->regs.miistatus);
1059
  PRINTF ("MAC Address  : %02X:%02X:%02X:%02X:%02X:%02X\n",
1060
          eth->mac_address[0], eth->mac_address[1], eth->mac_address[2],
1061
          eth->mac_address[3], eth->mac_address[4], eth->mac_address[5]);
1062
  PRINTF ("HASH0        : 0x%08lX\n", eth->regs.hash0);
1063
  PRINTF ("HASH1        : 0x%08lX\n", eth->regs.hash1);
1064 696 ivang
}
1065 1748 jeremybenn
 
1066 696 ivang
/* ========================================================================= */
1067
 
1068
 
1069
/*
1070
  Read a register
1071
*/
1072 1748 jeremybenn
static uint32_t
1073
eth_read32 (oraddr_t addr, void *dat)
1074 696 ivang
{
1075 1748 jeremybenn
  struct eth_device *eth = dat;
1076 696 ivang
 
1077 1748 jeremybenn
  switch (addr)
1078
    {
1079
    case ETH_MODER:
1080
      return eth->regs.moder;
1081
    case ETH_INT_SOURCE:
1082
      return eth->regs.int_source;
1083
    case ETH_INT_MASK:
1084
      return eth->regs.int_mask;
1085
    case ETH_IPGT:
1086
      return eth->regs.ipgt;
1087
    case ETH_IPGR1:
1088
      return eth->regs.ipgr1;
1089
    case ETH_IPGR2:
1090
      return eth->regs.ipgr2;
1091
    case ETH_PACKETLEN:
1092
      return eth->regs.packetlen;
1093
    case ETH_COLLCONF:
1094
      return eth->regs.collconf;
1095
    case ETH_TX_BD_NUM:
1096
      return eth->regs.tx_bd_num;
1097
    case ETH_CTRLMODER:
1098
      return eth->regs.controlmoder;
1099
    case ETH_MIIMODER:
1100
      return eth->regs.miimoder;
1101
    case ETH_MIICOMMAND:
1102
      return eth->regs.miicommand;
1103
    case ETH_MIIADDRESS:
1104
      return eth->regs.miiaddress;
1105
    case ETH_MIITX_DATA:
1106
      return eth->regs.miitx_data;
1107
    case ETH_MIIRX_DATA:
1108
      return eth->regs.miirx_data;
1109
    case ETH_MIISTATUS:
1110
      return eth->regs.miistatus;
1111
    case ETH_MAC_ADDR0:
1112
      return (((unsigned long) eth->mac_address[3]) << 24) |
1113
        (((unsigned long) eth->mac_address[2]) << 16) |
1114
        (((unsigned long) eth->mac_address[1]) << 8) |
1115
        (unsigned long) eth->mac_address[0];
1116
    case ETH_MAC_ADDR1:
1117
      return (((unsigned long) eth->mac_address[5]) << 8) |
1118
        (unsigned long) eth->mac_address[4];
1119
    case ETH_HASH0:
1120
      return eth->regs.hash0;
1121
    case ETH_HASH1:
1122
      return eth->regs.hash1;
1123
      /*case ETH_DMA_RX_TX: return eth_rx( eth ); */
1124 696 ivang
    }
1125
 
1126 1748 jeremybenn
  if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
1127
    return eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4];
1128
 
1129
  PRINTF ("eth_read32( 0x%" PRIxADDR " ): Illegal address\n",
1130
          addr + eth->baseaddr);
1131
  return 0;
1132 696 ivang
}
1133 1748 jeremybenn
 
1134 696 ivang
/* ========================================================================= */
1135
 
1136
 
1137
/*
1138
  Write a register
1139
*/
1140 1748 jeremybenn
static void
1141
eth_write32 (oraddr_t addr, uint32_t value, void *dat)
1142 696 ivang
{
1143 1748 jeremybenn
  struct eth_device *eth = dat;
1144 1372 nogj
 
1145 1748 jeremybenn
  switch (addr)
1146
    {
1147 1372 nogj
    case ETH_MODER:
1148
 
1149 1748 jeremybenn
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, RXEN) &&
1150
          TEST_FLAG (value, ETH_MODER, RXEN))
1151
        SCHED_ADD (eth_controller_rx_clock, dat, 1);
1152
      else if (!TEST_FLAG (value, ETH_MODER, RXEN))
1153
        SCHED_FIND_REMOVE (eth_controller_rx_clock, dat);
1154 1372 nogj
 
1155 1748 jeremybenn
      if (!TEST_FLAG (eth->regs.moder, ETH_MODER, TXEN) &&
1156
          TEST_FLAG (value, ETH_MODER, TXEN))
1157
        SCHED_ADD (eth_controller_tx_clock, dat, 1);
1158
      else if (!TEST_FLAG (value, ETH_MODER, TXEN))
1159
        SCHED_FIND_REMOVE (eth_controller_tx_clock, dat);
1160 1372 nogj
 
1161 1748 jeremybenn
      eth->regs.moder = value;
1162 1372 nogj
 
1163 1748 jeremybenn
      if (TEST_FLAG (value, ETH_MODER, RST))
1164
        eth_reset (dat);
1165
      return;
1166 1715 nogj
    case ETH_INT_SOURCE:
1167 1748 jeremybenn
      if (!(eth->regs.int_source & ~value) && eth->regs.int_source)
1168
        clear_interrupt (eth->mac_int);
1169 1715 nogj
      eth->regs.int_source &= ~value;
1170
      return;
1171 1748 jeremybenn
    case ETH_INT_MASK:
1172
      eth->regs.int_mask = value;
1173
      return;
1174
    case ETH_IPGT:
1175
      eth->regs.ipgt = value;
1176
      return;
1177
    case ETH_IPGR1:
1178
      eth->regs.ipgr1 = value;
1179
      return;
1180
    case ETH_IPGR2:
1181
      eth->regs.ipgr2 = value;
1182
      return;
1183
    case ETH_PACKETLEN:
1184
      eth->regs.packetlen = value;
1185
      return;
1186
    case ETH_COLLCONF:
1187
      eth->regs.collconf = value;
1188
      return;
1189
    case ETH_TX_BD_NUM:
1190
      eth_write_tx_bd_num (eth, value);
1191
      return;
1192
    case ETH_CTRLMODER:
1193
      eth->regs.controlmoder = value;
1194
      return;
1195
    case ETH_MIIMODER:
1196
      eth->regs.miimoder = value;
1197
      return;
1198
    case ETH_MIICOMMAND:
1199
      eth->regs.miicommand = value;
1200
      return;
1201
    case ETH_MIIADDRESS:
1202
      eth->regs.miiaddress = value;
1203
      return;
1204
    case ETH_MIITX_DATA:
1205
      eth->regs.miitx_data = value;
1206
      return;
1207
    case ETH_MIIRX_DATA:
1208
      eth->regs.miirx_data = value;
1209
      return;
1210
    case ETH_MIISTATUS:
1211
      eth->regs.miistatus = value;
1212
      return;
1213 696 ivang
    case ETH_MAC_ADDR0:
1214 1748 jeremybenn
      eth->mac_address[0] = value & 0xFF;
1215
      eth->mac_address[1] = (value >> 8) & 0xFF;
1216
      eth->mac_address[2] = (value >> 16) & 0xFF;
1217
      eth->mac_address[3] = (value >> 24) & 0xFF;
1218
      return;
1219 696 ivang
    case ETH_MAC_ADDR1:
1220 1748 jeremybenn
      eth->mac_address[4] = value & 0xFF;
1221
      eth->mac_address[5] = (value >> 8) & 0xFF;
1222
      return;
1223
    case ETH_HASH0:
1224
      eth->regs.hash0 = value;
1225
      return;
1226
    case ETH_HASH1:
1227
      eth->regs.hash1 = value;
1228
      return;
1229
 
1230
      /*case ETH_DMA_RX_TX: eth_tx( eth, value ); return; */
1231 696 ivang
    }
1232
 
1233 1748 jeremybenn
  if ((addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE))
1234
    {
1235
      eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value;
1236
      return;
1237 696 ivang
    }
1238 1748 jeremybenn
 
1239
  PRINTF ("eth_write32( 0x%" PRIxADDR " ): Illegal address\n",
1240
          addr + eth->baseaddr);
1241
  return;
1242 696 ivang
}
1243 1748 jeremybenn
 
1244 696 ivang
/* ========================================================================= */
1245
 
1246
 
1247 889 ivang
/*
1248
 *   VAPI connection to outside
1249
 */
1250 1748 jeremybenn
static void
1251
eth_vapi_read (unsigned long id, unsigned long data, void *dat)
1252 889 ivang
{
1253 1748 jeremybenn
  unsigned long which;
1254
  struct eth_device *eth = dat;
1255 889 ivang
 
1256 1748 jeremybenn
  which = id - eth->base_vapi_id;
1257 1372 nogj
 
1258 1748 jeremybenn
  TRACE ("ETH: id %08lx, data %08lx\n", id, data);
1259 889 ivang
 
1260 1748 jeremybenn
  if (!eth)
1261
    {
1262
      TRACE ("ETH: VAPI ID %08lx is not ours!\n", id);
1263
      return;
1264 889 ivang
    }
1265
 
1266 1748 jeremybenn
  switch (which)
1267
    {
1268 889 ivang
    case ETH_VAPI_DATA:
1269 1748 jeremybenn
      break;
1270 889 ivang
    case ETH_VAPI_CTRL:
1271 1748 jeremybenn
      break;
1272 889 ivang
    }
1273
}
1274 1748 jeremybenn
 
1275 889 ivang
/* ========================================================================= */
1276
 
1277
 
1278 702 ivang
/* When TX_BD_NUM is written, also reset current RX BD index */
1279 1748 jeremybenn
static void
1280
eth_write_tx_bd_num (struct eth_device *eth, unsigned long value)
1281 702 ivang
{
1282 1748 jeremybenn
  eth->regs.tx_bd_num = value & 0xFF;
1283
  eth->rx.bd_index = eth->regs.tx_bd_num << 1;
1284 702 ivang
}
1285 1372 nogj
 
1286 702 ivang
/* ========================================================================= */
1287
 
1288 1372 nogj
/*-----------------------------------------------[ Ethernet configuration ]---*/
1289 1748 jeremybenn
 
1290
 
1291
/*---------------------------------------------------------------------------*/
1292
/*!Enable or disable the Ethernet interface
1293
 
1294
   @param[in] val  The value to use
1295
   @param[in] dat  The config data structure                                 */
1296
/*---------------------------------------------------------------------------*/
1297
static void
1298
eth_enabled (union param_val  val,
1299
             void            *dat)
1300 696 ivang
{
1301 1372 nogj
  struct eth_device *eth = dat;
1302 1748 jeremybenn
 
1303
  eth->enabled = val.int_val;
1304
 
1305
}       /* eth_enabled() */
1306
 
1307
 
1308
/*---------------------------------------------------------------------------*/
1309
/*!Set the Ethernet interface base address
1310
 
1311
   @param[in] val  The value to use
1312
   @param[in] dat  The config data structure                                 */
1313
/*---------------------------------------------------------------------------*/
1314
static void
1315
eth_baseaddr (union param_val  val,
1316
              void            *dat)
1317
{
1318
  struct eth_device *eth = dat;
1319
 
1320 1372 nogj
  eth->baseaddr = val.addr_val;
1321 889 ivang
 
1322 1748 jeremybenn
}       /* eth_baseaddr() */
1323
 
1324
 
1325
/*---------------------------------------------------------------------------*/
1326
/*!Set the Ethernet DMA port
1327
 
1328
   This is not currently supported, so a warning message is printed.
1329
 
1330
   @param[in] val  The value to use
1331
   @param[in] dat  The config data structure                                 */
1332
/*---------------------------------------------------------------------------*/
1333
static void
1334
eth_dma (union param_val  val,
1335
         void            *dat)
1336 889 ivang
{
1337 1372 nogj
  struct eth_device *eth = dat;
1338 1748 jeremybenn
 
1339
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported\n");
1340 1372 nogj
  eth->dma = val.addr_val;
1341 1358 nogj
 
1342 1748 jeremybenn
}       /* eth_dma() */
1343
 
1344
 
1345
/*---------------------------------------------------------------------------*/
1346
/*!Set the Ethernet IRQ
1347
 
1348
   @param[in] val  The value to use
1349
   @param[in] dat  The config data structure                                 */
1350
/*---------------------------------------------------------------------------*/
1351
static void
1352
eth_irq (union param_val  val,
1353
         void            *dat)
1354 1372 nogj
{
1355
  struct eth_device *eth = dat;
1356 1748 jeremybenn
 
1357
  eth->mac_int = val.int_val;
1358
 
1359
}       /* eth_irq() */
1360
 
1361
 
1362
/*---------------------------------------------------------------------------*/
1363
/*!Set the Ethernet interface type
1364
 
1365
   Currently two types are supported, file and socket. Use of the socket
1366
   requires a compile time option.
1367
 
1368
   @param[in] val  The value to use. 0 for file, 1 for socket.
1369
   @param[in] dat  The config data structure                                 */
1370
/*---------------------------------------------------------------------------*/
1371
static void
1372
eth_rtx_type (union param_val  val,
1373
              void            *dat)
1374
{
1375
  struct eth_device *eth = dat;
1376
 
1377
  if (val.int_val)
1378
    {
1379
#ifndef HAVE_ETH_PHY
1380
      fprintf (stderr, "Warning: Ethernet PHY socket not enabled in this "
1381
               "configuration (configure with --enable-ethphy): ignored\n");
1382
      return;
1383
#endif
1384
    }
1385
 
1386 1372 nogj
  eth->rtx_type = val.int_val;
1387 1358 nogj
 
1388 1748 jeremybenn
}       /* eth_rtx_type() */
1389
 
1390
 
1391
/*---------------------------------------------------------------------------*/
1392
/*!Set the Ethernet DMA Rx channel
1393
 
1394
   External DMA is not currently supported, so a warning message is printed.
1395
 
1396
   @param[in] val  The value to use
1397
   @param[in] dat  The config data structure                                 */
1398
/*---------------------------------------------------------------------------*/
1399
static void
1400
eth_rx_channel (union param_val  val,
1401
                void            *dat)
1402 1372 nogj
{
1403
  struct eth_device *eth = dat;
1404 1748 jeremybenn
 
1405
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1406
           "Rx channel ignored\n");
1407 1372 nogj
  eth->rx_channel = val.int_val;
1408 1358 nogj
 
1409 1748 jeremybenn
}       /* eth_rx_channel() */
1410
 
1411
 
1412
/*---------------------------------------------------------------------------*/
1413
/*!Set the Ethernet DMA Tx channel
1414
 
1415
   External DMA is not currently supported, so a warning message is printed.
1416
 
1417
   @param[in] val  The value to use
1418
   @param[in] dat  The config data structure                                 */
1419
/*---------------------------------------------------------------------------*/
1420
static void
1421
eth_tx_channel (union param_val  val,
1422
                void            *dat)
1423 1372 nogj
{
1424
  struct eth_device *eth = dat;
1425 1748 jeremybenn
 
1426
  fprintf (stderr, "Warning: External Ethernet DMA not currently supported: "
1427
           "Tx channel ignored\n");
1428 1372 nogj
  eth->tx_channel = val.int_val;
1429 1358 nogj
 
1430 1748 jeremybenn
}       /* eth_tx_channel() */
1431 1358 nogj
 
1432 1748 jeremybenn
 
1433
/*---------------------------------------------------------------------------*/
1434
/*!Set the Ethernet DMA Rx file
1435
 
1436
   Free any previously allocated value.
1437
 
1438
   @param[in] val  The value to use
1439
   @param[in] dat  The config data structure                                 */
1440
/*---------------------------------------------------------------------------*/
1441
static void
1442
eth_rxfile (union param_val  val,
1443
            void            *dat)
1444 1358 nogj
{
1445 1372 nogj
  struct eth_device *eth = dat;
1446 1358 nogj
 
1447 1748 jeremybenn
  if (NULL != eth->rxfile)
1448
    {
1449
      free (eth->rxfile);
1450
      eth->rxfile = NULL;
1451
    }
1452
 
1453
  if (!(eth->rxfile = strdup (val.str_val)))
1454
    {
1455
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1456
      exit (-1);
1457
    }
1458
}       /* eth_rxfile() */
1459
 
1460
 
1461
/*---------------------------------------------------------------------------*/
1462
/*!Set the Ethernet DMA Tx file
1463
 
1464
   Free any previously allocated value.
1465
 
1466
   @param[in] val  The value to use
1467
   @param[in] dat  The config data structure                                 */
1468
/*---------------------------------------------------------------------------*/
1469
static void
1470
eth_txfile (union param_val  val,
1471
            void            *dat)
1472 1358 nogj
{
1473 1372 nogj
  struct eth_device *eth = dat;
1474 1358 nogj
 
1475 1748 jeremybenn
  if (NULL != eth->txfile)
1476
    {
1477
      free (eth->txfile);
1478
      eth->txfile = NULL;
1479
    }
1480
 
1481
  if (!(eth->txfile = strdup (val.str_val)))
1482
    {
1483
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1484
      exit (-1);
1485
    }
1486
}       /* eth_txfile() */
1487
 
1488
 
1489
/*---------------------------------------------------------------------------*/
1490
/*!Set the Ethernet socket interface
1491
 
1492
   Free any previously allocated value. This is only meaningful if the socket
1493
   interface is configured.
1494
 
1495
   @param[in] val  The value to use
1496
   @param[in] dat  The config data structure                                 */
1497
/*---------------------------------------------------------------------------*/
1498
static void
1499
eth_sockif (union param_val  val,
1500
            void            *dat)
1501 1358 nogj
{
1502 1372 nogj
  struct eth_device *eth = dat;
1503 1358 nogj
 
1504 1748 jeremybenn
#ifndef HAVE_ETH_PHY
1505
  fprintf (stderr, "Warning: Ethernet PHY socket not enabled in this "
1506
           "configuration (configure with --enable-ethphy): "
1507
           "sockif ignored\n");
1508
  return;
1509
#endif
1510
 
1511
  if (NULL != eth->sockif)
1512
    {
1513
      free (eth->sockif);
1514
      eth->sockif = NULL;
1515
    }
1516
 
1517
  if (!(eth->sockif = strdup (val.str_val)))
1518
    {
1519
      fprintf (stderr, "Peripheral Ethernet: Run out of memory\n");
1520
      exit (-1);
1521
    }
1522
}       /* eth_sockif() */
1523
 
1524
 
1525
static void
1526
eth_vapi_id (union param_val  val,
1527
             void            *dat)
1528 1358 nogj
{
1529 1372 nogj
  struct eth_device *eth = dat;
1530
  eth->base_vapi_id = val.int_val;
1531 1358 nogj
}
1532
 
1533 1748 jeremybenn
/*---------------------------------------------------------------------------*/
1534
/*!Initialize a new Ethernet configuration
1535 1461 nogj
 
1536 1748 jeremybenn
   ALL parameters are set explicitly to default values.                      */
1537
/*---------------------------------------------------------------------------*/
1538
static void *
1539
eth_sec_start (void)
1540 1372 nogj
{
1541 1748 jeremybenn
  struct eth_device *new = malloc (sizeof (struct eth_device));
1542 1372 nogj
 
1543 1748 jeremybenn
  if (!new)
1544
    {
1545
      fprintf (stderr, "Peripheral Eth: Run out of memory\n");
1546
      exit (-1);
1547
    }
1548 1372 nogj
 
1549 1748 jeremybenn
  memset (new, 0, sizeof (struct eth_device));
1550 1461 nogj
 
1551 1748 jeremybenn
  new->enabled      = 1;
1552
  new->baseaddr     = 0;
1553
  new->dma          = 0;
1554
  new->mac_int      = 0;
1555
  new->rtx_type     = 0;
1556
  new->rx_channel   = 0;
1557
  new->tx_channel   = 0;
1558
  new->rxfile       = strdup ("eth_rx");
1559
  new->txfile       = strdup ("eth_tx");
1560
  new->sockif       = strdup ("or1ksim_eth");
1561
  new->base_vapi_id = 0;
1562
 
1563 1372 nogj
  return new;
1564
}
1565
 
1566 1748 jeremybenn
static void
1567
eth_sec_end (void *dat)
1568 1372 nogj
{
1569
  struct eth_device *eth = dat;
1570 1486 nogj
  struct mem_ops ops;
1571 1372 nogj
 
1572 1748 jeremybenn
  if (!eth->enabled)
1573
    {
1574
      free (eth->rxfile);
1575
      free (eth->txfile);
1576
      free (eth->sockif);
1577
      free (eth);
1578
      return;
1579
    }
1580 1461 nogj
 
1581 1748 jeremybenn
  memset (&ops, 0, sizeof (struct mem_ops));
1582 1486 nogj
 
1583
  ops.readfunc32 = eth_read32;
1584
  ops.writefunc32 = eth_write32;
1585
  ops.read_dat32 = dat;
1586
  ops.write_dat32 = dat;
1587
 
1588
  /* FIXME: Correct delay? */
1589
  ops.delayr = 2;
1590
  ops.delayw = 2;
1591 1748 jeremybenn
  reg_mem_area (eth->baseaddr, ETH_ADDR_SPACE, 0, &ops);
1592
  reg_sim_stat (eth_status, dat);
1593
  reg_sim_reset (eth_reset, dat);
1594 1372 nogj
}
1595
 
1596 1748 jeremybenn
 
1597
/*---------------------------------------------------------------------------*/
1598
/*!Register a new Ethernet configuration                                     */
1599
/*---------------------------------------------------------------------------*/
1600
void
1601
reg_ethernet_sec ()
1602 1358 nogj
{
1603 1748 jeremybenn
  struct config_section *sec =
1604
    reg_config_sec ("ethernet", eth_sec_start, eth_sec_end);
1605 1358 nogj
 
1606 1748 jeremybenn
  reg_config_param (sec, "enabled",    paramt_int,  eth_enabled);
1607
  reg_config_param (sec, "baseaddr",   paramt_addr, eth_baseaddr);
1608
  reg_config_param (sec, "dma",        paramt_int,  eth_dma);
1609
  reg_config_param (sec, "irq",        paramt_int,  eth_irq);
1610
  reg_config_param (sec, "rtx_type",   paramt_int,  eth_rtx_type);
1611
  reg_config_param (sec, "rx_channel", paramt_int,  eth_rx_channel);
1612
  reg_config_param (sec, "tx_channel", paramt_int,  eth_tx_channel);
1613
  reg_config_param (sec, "rxfile",     paramt_str,  eth_rxfile);
1614
  reg_config_param (sec, "txfile",     paramt_str,  eth_txfile);
1615
  reg_config_param (sec, "sockif",     paramt_str,  eth_sockif);
1616
  reg_config_param (sec, "vapi_id",    paramt_int,  eth_vapi_id);
1617
 
1618
}       /* reg_ethernet_sec() */
1619
 

powered by: WebSVN 2.1.0

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