/[gxemul]/upstream/0.4.2/src/devices/dev_ether.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.4.2/src/devices/dev_ether.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations)
Mon Oct 8 16:20:48 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 6749 byte(s)
0.4.2
1 /*
2 * Copyright (C) 2005-2006 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 * $Id: dev_ether.c,v 1.14 2006/06/15 17:29:38 debug Exp $
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;
56 int packet_len;
57
58 int irq_nr;
59 };
60
61
62 /*
63 * dev_ether_tick():
64 */
65 void dev_ether_tick(struct cpu *cpu, void *extra)
66 {
67 struct ether_data *d = (struct ether_data *) extra;
68 int r = 0;
69
70 d->status &= ~DEV_ETHER_STATUS_MORE_PACKETS_AVAILABLE;
71 if (cpu->machine->emul->net != NULL)
72 r = net_ethernet_rx_avail(cpu->machine->emul->net, d);
73 if (r)
74 d->status |= DEV_ETHER_STATUS_MORE_PACKETS_AVAILABLE;
75
76 if (d->status)
77 cpu_interrupt(cpu, d->irq_nr);
78 else
79 cpu_interrupt_ack(cpu, d->irq_nr);
80 }
81
82
83 /*
84 * dev_ether_buf_access():
85 */
86 DEVICE_ACCESS(ether_buf)
87 {
88 struct ether_data *d = (struct ether_data *) extra;
89
90 if (writeflag == MEM_WRITE)
91 memcpy(d->buf + relative_addr, data, len);
92 else
93 memcpy(data, d->buf + relative_addr, len);
94 return 1;
95 }
96
97
98 DEVICE_ACCESS(ether)
99 {
100 struct ether_data *d = (struct ether_data *) extra;
101 uint64_t idata = 0, odata = 0;
102 unsigned char *incoming_ptr;
103 int incoming_len;
104
105 if (writeflag == MEM_WRITE)
106 idata = memory_readmax64(cpu, data, len);
107
108 /* Note: relative_addr + DEV_ETHER_BUFFER_SIZE to get the same
109 offsets as in the header file: */
110
111 switch (relative_addr + DEV_ETHER_BUFFER_SIZE) {
112
113 case DEV_ETHER_STATUS:
114 if (writeflag == MEM_READ) {
115 odata = d->status;
116 d->status = 0;
117 cpu_interrupt_ack(cpu, d->irq_nr);
118 } else
119 fatal("[ ether: WARNING: write to status ]\n");
120 break;
121
122 case DEV_ETHER_PACKETLENGTH:
123 if (writeflag == MEM_READ)
124 odata = d->packet_len;
125 else {
126 if ((int64_t)idata < 0) {
127 fatal("[ ether: ERROR: packet len too"
128 " short (%i bytes) ]\n", (int)idata);
129 idata = -1;
130 }
131 if (idata > DEV_ETHER_BUFFER_SIZE) {
132 fatal("[ ether: ERROR: packet len too"
133 " large (%i bytes) ]\n", (int)idata);
134 idata = DEV_ETHER_BUFFER_SIZE;
135 }
136 d->packet_len = idata;
137 }
138 break;
139
140 case DEV_ETHER_COMMAND:
141 if (writeflag == MEM_READ) {
142 fatal("[ ether: WARNING: read from command ]\n");
143 break;
144 }
145
146 /* Write: */
147 switch (idata) {
148
149 case DEV_ETHER_COMMAND_RX: /* Receive: */
150 if (cpu->machine->emul->net == NULL)
151 fatal("[ ether: RECEIVE but no net? ]\n");
152 else {
153 d->status &= ~DEV_ETHER_STATUS_PACKET_RECEIVED;
154 net_ethernet_rx(cpu->machine->emul->net,
155 d, &incoming_ptr, &incoming_len);
156 if (incoming_ptr != NULL) {
157 d->status |=
158 DEV_ETHER_STATUS_PACKET_RECEIVED;
159 if (incoming_len>DEV_ETHER_BUFFER_SIZE)
160 incoming_len =
161 DEV_ETHER_BUFFER_SIZE;
162 memcpy(d->buf, incoming_ptr,
163 incoming_len);
164 free(incoming_ptr);
165 d->packet_len = incoming_len;
166 }
167 }
168 dev_ether_tick(cpu, d);
169 break;
170
171 case DEV_ETHER_COMMAND_TX: /* Send */
172 if (cpu->machine->emul->net == NULL)
173 fatal("[ ether: SEND but no net? ]\n");
174 else
175 net_ethernet_tx(cpu->machine->emul->net,
176 d, d->buf, d->packet_len);
177 d->status &= ~DEV_ETHER_STATUS_PACKET_RECEIVED;
178 dev_ether_tick(cpu, d);
179 break;
180
181 default:fatal("[ ether: UNIMPLEMENTED command 0x"
182 "%02x ]\n", idata);
183 cpu->running = 0;
184 }
185 break;
186
187 default:if (writeflag == MEM_WRITE) {
188 fatal("[ ether: unimplemented write to "
189 "offset 0x%x: data=0x%x ]\n", (int)
190 relative_addr, (int)idata);
191 } else {
192 fatal("[ ether: unimplemented read from "
193 "offset 0x%x ]\n", (int)relative_addr);
194 }
195 }
196
197 if (writeflag == MEM_READ)
198 memory_writemax64(cpu, data, len, odata);
199
200 return 1;
201 }
202
203
204 DEVINIT(ether)
205 {
206 struct ether_data *d = malloc(sizeof(struct ether_data));
207 size_t nlen;
208 char *n1, *n2;
209 char tmp[50];
210
211 nlen = strlen(devinit->name) + 80;
212 n1 = malloc(nlen);
213 n2 = malloc(nlen);
214
215 if (d == NULL || n1 == NULL || n2 == NULL) {
216 fprintf(stderr, "out of memory\n");
217 exit(1);
218 }
219 memset(d, 0, sizeof(struct ether_data));
220 d->irq_nr = devinit->irq_nr;
221
222 net_generate_unique_mac(devinit->machine, d->mac);
223 snprintf(tmp, sizeof(tmp), "%02x:%02x:%02x:%02x:%02x:%02x",
224 d->mac[0], d->mac[1], d->mac[2], d->mac[3], d->mac[4], d->mac[5]);
225
226 snprintf(n1, nlen, "%s [%s]", devinit->name, tmp);
227 snprintf(n2, nlen, "%s [%s, control]", devinit->name, tmp);
228
229 memory_device_register(devinit->machine->memory, n1, devinit->addr,
230 DEV_ETHER_BUFFER_SIZE, dev_ether_buf_access, (void *)d,
231 DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK |
232 DM_READS_HAVE_NO_SIDE_EFFECTS, d->buf);
233 memory_device_register(devinit->machine->memory, n2,
234 devinit->addr + DEV_ETHER_BUFFER_SIZE,
235 DEV_ETHER_LENGTH-DEV_ETHER_BUFFER_SIZE, dev_ether_access, (void *)d,
236 DM_DEFAULT, NULL);
237
238 net_add_nic(devinit->machine->emul->net, d, d->mac);
239
240 machine_add_tickfunction(devinit->machine,
241 dev_ether_tick, d, DEV_ETHER_TICK_SHIFT, 0.0);
242
243 return 1;
244 }
245

  ViewVC Help
Powered by ViewVC 1.1.26