dev_ether.cc Source File

Back to the index.

dev_ether.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2009 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * COMMENT: A simple ethernet controller, for the test machines
29  *
30  * Basic "ethernet" network device. This is a simple test device which can
31  * be used to send and receive packets to/from a simulated ethernet network.
32  */
33 
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 #include "cpu.h"
39 #include "device.h"
40 #include "emul.h"
41 #include "machine.h"
42 #include "memory.h"
43 #include "misc.h"
44 #include "net.h"
45 
46 #include "testmachine/dev_ether.h"
47 
48 
49 #define DEV_ETHER_TICK_SHIFT 14
50 
51 struct ether_data {
52  unsigned char buf[DEV_ETHER_BUFFER_SIZE];
53  unsigned char mac[6];
54 
55  int status;
57 
58  struct interrupt irq;
59 };
60 
61 
63 {
64  struct ether_data *d = (struct ether_data *) extra;
65  int r = 0;
66 
68  if (cpu->machine->emul->net != NULL)
70  if (r)
72 
73  if (d->status)
75  else
77 }
78 
79 
80 DEVICE_ACCESS(ether_buf)
81 {
82  struct ether_data *d = (struct ether_data *) extra;
83 
84  if (writeflag == MEM_WRITE)
85  memcpy(d->buf + relative_addr, data, len);
86  else
87  memcpy(data, d->buf + relative_addr, len);
88 
89  return 1;
90 }
91 
92 
94 {
95  struct ether_data *d = (struct ether_data *) extra;
96  uint64_t idata = 0, odata = 0;
97  unsigned char *incoming_ptr;
98  int incoming_len;
99 
100  if (writeflag == MEM_WRITE)
101  idata = memory_readmax64(cpu, data, len);
102 
103  /* Note: relative_addr + DEV_ETHER_BUFFER_SIZE to get the same
104  offsets as in the header file: */
105 
106  switch (relative_addr + DEV_ETHER_BUFFER_SIZE) {
107 
108  case DEV_ETHER_STATUS:
109  if (writeflag == MEM_READ) {
110  odata = d->status;
111  d->status = 0;
113  } else
114  fatal("[ ether: WARNING: write to status ]\n");
115  break;
116 
118  if (writeflag == MEM_READ)
119  odata = d->packet_len;
120  else {
121  if ((int64_t)idata < 0) {
122  fatal("[ ether: ERROR: packet len too"
123  " short (%i bytes) ]\n", (int)idata);
124  idata = (uint64_t) -1;
125  }
126  if (idata > DEV_ETHER_BUFFER_SIZE) {
127  fatal("[ ether: ERROR: packet len too"
128  " large (%i bytes) ]\n", (int)idata);
129  idata = DEV_ETHER_BUFFER_SIZE;
130  }
131  d->packet_len = idata;
132  }
133  break;
134 
135  case DEV_ETHER_COMMAND:
136  if (writeflag == MEM_READ) {
137  fatal("[ ether: WARNING: read from command ]\n");
138  break;
139  }
140 
141  /* Write: */
142  switch (idata) {
143 
144  case DEV_ETHER_COMMAND_RX: /* Receive: */
145  if (cpu->machine->emul->net == NULL)
146  fatal("[ ether: RECEIVE but no net? ]\n");
147  else {
150  d, &incoming_ptr, &incoming_len)) {
151  d->status |=
153  if (incoming_len>DEV_ETHER_BUFFER_SIZE)
154  incoming_len =
156  memcpy(d->buf, incoming_ptr,
157  incoming_len);
158  free(incoming_ptr);
159  d->packet_len = incoming_len;
160  }
161  }
162  dev_ether_tick(cpu, d);
163  break;
164 
165  case DEV_ETHER_COMMAND_TX: /* Send */
166  if (cpu->machine->emul->net == NULL)
167  fatal("[ ether: SEND but no net? ]\n");
168  else
170  d, d->buf, d->packet_len);
172  dev_ether_tick(cpu, d);
173  break;
174 
175  default:fatal("[ ether: UNIMPLEMENTED command 0x"
176  "%02x ]\n", idata);
177  cpu->running = 0;
178  }
179  break;
180 
181  case DEV_ETHER_MAC:
182  if (writeflag == MEM_READ) {
183  fatal("[ ether: read of MAC is not allowed! ]\n");
184  } else {
185  // Write out the MAC address to the address given.
186  cpu->memory_rw(cpu, cpu->mem, idata, d->mac,
187  6, MEM_WRITE, CACHE_NONE);
188  }
189  break;
190 
191  default:if (writeflag == MEM_WRITE) {
192  fatal("[ ether: unimplemented write to "
193  "offset 0x%x: data=0x%x ]\n", (int)
194  relative_addr, (int)idata);
195  } else {
196  fatal("[ ether: unimplemented read from "
197  "offset 0x%x ]\n", (int)relative_addr);
198  }
199  }
200 
201  if (writeflag == MEM_READ)
202  memory_writemax64(cpu, data, len, odata);
203 
204  return 1;
205 }
206 
207 
208 DEVINIT(ether)
209 {
210  struct ether_data *d;
211  size_t nlen;
212  char *n1, *n2;
213  char tmp[50];
214 
215  CHECK_ALLOCATION(d = (struct ether_data *) malloc(sizeof(struct ether_data)));
216  memset(d, 0, sizeof(struct ether_data));
217 
218  nlen = strlen(devinit->name) + 80;
219  CHECK_ALLOCATION(n1 = (char *) malloc(nlen));
220  CHECK_ALLOCATION(n2 = (char *) malloc(nlen));
221 
223 
225  snprintf(tmp, sizeof(tmp), "%02x:%02x:%02x:%02x:%02x:%02x",
226  d->mac[0], d->mac[1], d->mac[2], d->mac[3], d->mac[4], d->mac[5]);
227 
228  snprintf(n1, nlen, "%s [%s]", devinit->name, tmp);
229  snprintf(n2, nlen, "%s [%s, control]", devinit->name, tmp);
230 
232  DEV_ETHER_BUFFER_SIZE, dev_ether_buf_access, (void *)d,
237  DEV_ETHER_LENGTH-DEV_ETHER_BUFFER_SIZE, dev_ether_access, (void *)d,
238  DM_DEFAULT, NULL);
239 
240  net_add_nic(devinit->machine->emul->net, d, d->mac);
241 
243  dev_ether_tick, d, DEV_ETHER_TICK_SHIFT);
244 
245  return 1;
246 }
247 
uint64_t memory_readmax64(struct cpu *cpu, unsigned char *buf, int len)
Definition: memory.cc:55
void net_ethernet_tx(struct net *net, void *extra, unsigned char *packet, int len)
Definition: net.cc:371
void fatal(const char *fmt,...)
Definition: main.cc:152
#define DM_DEFAULT
Definition: memory.h:130
#define DEV_ETHER_STATUS_PACKET_RECEIVED
Definition: dev_ether.h:22
char * name
Definition: device.h:43
#define DEV_ETHER_STATUS_MORE_PACKETS_AVAILABLE
Definition: dev_ether.h:23
struct memory * mem
Definition: cpu.h:362
DEVICE_TICK(ether)
Definition: dev_ether.cc:62
struct machine * machine
Definition: cpu.h:328
DEVINIT(ether)
Definition: dev_ether.cc:208
#define MEM_READ
Definition: memory.h:116
#define DEV_ETHER_BUFFER_SIZE
Definition: dev_ether.h:15
struct memory * memory
Definition: machine.h:126
struct interrupt irq
Definition: dev_ether.cc:58
#define DEV_ETHER_LENGTH
Definition: dev_ether.h:12
int packet_len
Definition: dev_ether.cc:56
int net_ethernet_rx(struct net *net, void *extra, unsigned char **packetp, int *lenp)
Definition: net.cc:316
struct emul * emul
Definition: machine.h:99
#define CHECK_ALLOCATION(ptr)
Definition: misc.h:239
void net_add_nic(struct net *net, void *extra, unsigned char *macaddr)
Definition: net.cc:598
#define DEV_ETHER_COMMAND
Definition: dev_ether.h:18
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
Definition: cpu.h:365
#define DM_READS_HAVE_NO_SIDE_EFFECTS
Definition: memory.h:133
u_short data
Definition: siireg.h:79
#define DEV_ETHER_COMMAND_RX
Definition: dev_ether.h:26
#define INTERRUPT_ASSERT(istruct)
Definition: interrupt.h:74
#define DM_DYNTRANS_WRITE_OK
Definition: memory.h:132
uint8_t running
Definition: cpu.h:353
void net_generate_unique_mac(struct machine *, unsigned char *macbuf)
Definition: net_misc.cc:88
#define MEM_WRITE
Definition: memory.h:117
unsigned char buf[DEV_ETHER_BUFFER_SIZE]
Definition: dev_ether.cc:52
Definition: device.h:40
int net_ethernet_rx_avail(struct net *net, void *extra)
Definition: net.cc:253
#define DEV_ETHER_TICK_SHIFT
Definition: dev_ether.cc:49
#define INTERRUPT_CONNECT(name, istruct)
Definition: interrupt.h:77
Definition: cpu.h:326
struct machine * machine
Definition: device.h:41
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
void memory_writemax64(struct cpu *cpu, unsigned char *buf, int len, uint64_t data)
Definition: memory.cc:89
DEVICE_ACCESS(ether_buf)
Definition: dev_ether.cc:80
void memory_device_register(struct memory *mem, const char *, uint64_t baseaddr, uint64_t len, int(*f)(struct cpu *, struct memory *, uint64_t, unsigned char *, size_t, int, void *), void *extra, int flags, unsigned char *dyntrans_data)
Definition: memory.cc:339
struct net * net
Definition: emul.h:43
#define DM_DYNTRANS_OK
Definition: memory.h:131
#define DEV_ETHER_MAC
Definition: dev_ether.h:19
int status
Definition: dev_ether.cc:55
unsigned char mac[6]
Definition: dev_ether.cc:53
uint64_t addr
Definition: device.h:46
#define DEV_ETHER_PACKETLENGTH
Definition: dev_ether.h:17
void machine_add_tickfunction(struct machine *machine, void(*func)(struct cpu *, void *), void *extra, int clockshift)
Definition: machine.cc:280
#define DEV_ETHER_COMMAND_TX
Definition: dev_ether.h:27
#define CACHE_NONE
Definition: memory.h:123
#define DEV_ETHER_STATUS
Definition: dev_ether.h:16
char * interrupt_path
Definition: device.h:50
#define INTERRUPT_DEASSERT(istruct)
Definition: interrupt.h:75

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13