/[gxemul]/upstream/0.3.7/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.3.7/src/devices/dev_ether.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 21 - (show annotations)
Mon Oct 8 16:19:28 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 6867 byte(s)
0.3.7
1 /*
2 * Copyright (C) 2005 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.9 2005/11/13 00:14:08 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 "devices.h"
41 #include "emul.h"
42 #include "machine.h"
43 #include "memory.h"
44 #include "misc.h"
45 #include "net.h"
46
47
48 #define DEV_ETHER_MAXBUFLEN 16384
49 #define DEV_ETHER_TICK_SHIFT 14
50
51 #define STATUS_RECEIVED 0x01
52 #define STATUS_MORE_AVAIL 0x02
53
54 struct ether_data {
55 unsigned char buf[DEV_ETHER_MAXBUFLEN];
56 unsigned char mac[6];
57
58 int status;
59 int packet_len;
60
61 int irq_nr;
62 };
63
64
65 /*
66 * dev_ether_tick():
67 */
68 void dev_ether_tick(struct cpu *cpu, void *extra)
69 {
70 struct ether_data *d = (struct ether_data *) extra;
71 int r = 0;
72
73 d->status &= ~STATUS_MORE_AVAIL;
74 if (cpu->machine->emul->net != NULL)
75 r = net_ethernet_rx_avail(cpu->machine->emul->net, d);
76 if (r)
77 d->status |= STATUS_MORE_AVAIL;
78
79 if (d->status)
80 cpu_interrupt(cpu, d->irq_nr);
81 else
82 cpu_interrupt_ack(cpu, d->irq_nr);
83 }
84
85
86 /*
87 * dev_ether_buf_access():
88 */
89 int dev_ether_buf_access(struct cpu *cpu, struct memory *mem,
90 uint64_t relative_addr, unsigned char *data, size_t len,
91 int writeflag, void *extra)
92 {
93 struct ether_data *d = (struct ether_data *) extra;
94
95 if (writeflag == MEM_WRITE)
96 memcpy(d->buf + relative_addr, data, len);
97 else
98 memcpy(data, d->buf + relative_addr, len);
99 return 1;
100 }
101
102
103 /*
104 * dev_ether_access():
105 */
106 int dev_ether_access(struct cpu *cpu, struct memory *mem,
107 uint64_t relative_addr, unsigned char *data, size_t len,
108 int writeflag, void *extra)
109 {
110 struct ether_data *d = (struct ether_data *) extra;
111 uint64_t idata = 0, odata = 0;
112 unsigned char *incoming_ptr;
113 int incoming_len;
114
115 if (writeflag == MEM_WRITE)
116 idata = memory_readmax64(cpu, data, len);
117
118 switch (relative_addr) {
119 case 0x0000:
120 if (writeflag == MEM_READ) {
121 odata = d->status;
122 d->status = 0;
123 cpu_interrupt_ack(cpu, d->irq_nr);
124 } else
125 fatal("[ ether: WARNING: write to status ]\n");
126 break;
127 case 0x0010:
128 if (writeflag == MEM_READ)
129 odata = d->packet_len;
130 else {
131 if ((int64_t)idata < 0) {
132 fatal("[ ether: ERROR: packet len too"
133 " short (%i bytes) ]\n", (int)idata);
134 idata = -1;
135 }
136 if (idata > DEV_ETHER_MAXBUFLEN) {
137 fatal("[ ether: ERROR: packet len too"
138 " large (%i bytes) ]\n", (int)idata);
139 idata = DEV_ETHER_MAXBUFLEN;
140 }
141 d->packet_len = idata;
142 }
143 break;
144 case 0x0020:
145 if (writeflag == MEM_READ)
146 fatal("[ ether: WARNING: read from command ]\n");
147 else {
148 switch (idata) {
149 case 0x00: /* Receive: */
150 if (cpu->machine->emul->net == NULL)
151 fatal("[ ether: RECEIVE but no "
152 "net? ]\n");
153 else {
154 d->status &= ~STATUS_RECEIVED;
155 net_ethernet_rx(cpu->machine->emul->net,
156 d, &incoming_ptr, &incoming_len);
157 if (incoming_ptr != NULL) {
158 d->status |= STATUS_RECEIVED;
159 if (incoming_len >
160 DEV_ETHER_MAXBUFLEN)
161 incoming_len =
162 DEV_ETHER_MAXBUFLEN;
163 memcpy(d->buf, incoming_ptr,
164 incoming_len);
165 free(incoming_ptr);
166 d->packet_len = incoming_len;
167 }
168 }
169 dev_ether_tick(cpu, d);
170 break;
171 case 0x01: /* 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 &= ~STATUS_RECEIVED;
178 dev_ether_tick(cpu, d);
179 break;
180 default:fatal("[ ether: UNIMPLEMENTED command 0x"
181 "%02x ]\n", idata);
182 cpu->running = 0;
183 }
184 }
185 break;
186 default:if (writeflag == MEM_WRITE) {
187 fatal("[ ether: unimplemented write to "
188 "offset 0x%x: data=0x%x ]\n", (int)
189 relative_addr, (int)idata);
190 } else {
191 fatal("[ ether: unimplemented read from "
192 "offset 0x%x ]\n", (int)relative_addr);
193 }
194 }
195
196 if (writeflag == MEM_READ)
197 memory_writemax64(cpu, data, len, odata);
198
199 return 1;
200 }
201
202
203 /*
204 * devinit_ether():
205 */
206 int devinit_ether(struct devinit *devinit)
207 {
208 struct ether_data *d = malloc(sizeof(struct ether_data));
209 size_t nlen;
210 char *n1, *n2;
211 char tmp[50];
212
213 nlen = strlen(devinit->name) + 80;
214 n1 = malloc(nlen);
215 n2 = malloc(nlen);
216
217 if (d == NULL || n1 == NULL || n2 == NULL) {
218 fprintf(stderr, "out of memory\n");
219 exit(1);
220 }
221 memset(d, 0, sizeof(struct ether_data));
222 d->irq_nr = devinit->irq_nr;
223
224 net_generate_unique_mac(devinit->machine, d->mac);
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
231 memory_device_register(devinit->machine->memory, n1,
232 devinit->addr, DEV_ETHER_MAXBUFLEN, dev_ether_buf_access, (void *)d,
233 DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK |
234 DM_READS_HAVE_NO_SIDE_EFFECTS, d->buf);
235 memory_device_register(devinit->machine->memory, n2,
236 devinit->addr + DEV_ETHER_MAXBUFLEN,
237 DEV_ETHER_LENGTH-DEV_ETHER_MAXBUFLEN, dev_ether_access, (void *)d,
238 DM_DEFAULT, NULL);
239
240 net_add_nic(devinit->machine->emul->net, d, d->mac);
241
242 machine_add_tickfunction(devinit->machine,
243 dev_ether_tick, d, DEV_ETHER_TICK_SHIFT);
244
245 return 1;
246 }
247

  ViewVC Help
Powered by ViewVC 1.1.26