/[gxemul]/upstream/0.3.8/src/devices/dev_le.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.8/src/devices/dev_le.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Mon Oct 8 16:19:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 22238 byte(s)
0.3.8
1 /*
2 * Copyright (C) 2003-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_le.c,v 1.49 2006/01/01 13:17:16 debug Exp $
29 *
30 * LANCE ethernet, as used in DECstations.
31 *
32 * This is based on "PMAD-AA TURBOchannel Ethernet Module Functional
33 * Specification". I've tried to keep symbol names in this file to what
34 * the specs use.
35 *
36 * This is what the memory layout looks like on a DECstation 5000/200:
37 *
38 * 0x000000 - 0x0fffff Ethernet SRAM buffer (should be 128KB)
39 * 0x100000 - 0x17ffff LANCE registers
40 * 0x1c0000 - 0x1fffff Ethernet Diagnostic ROM and Station
41 * Address ROM
42 *
43 * The length of the device is set to 0x1c0200, however, because Sprite
44 * tries to read TURBOchannel rom data from 0x1c03f0, and that is provided
45 * by the turbochannel device, not this device.
46 *
47 *
48 * TODO: Error conditions (such as when there are not enough receive
49 * buffers) are not emulated yet.
50 *
51 * (Old bug, but probably still valid: "UDP packets that are too
52 * large are not handled well by the Lance device.")
53 */
54
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58
59 #include "cpu.h"
60 #include "devices.h"
61 #include "emul.h"
62 #include "machine.h"
63 #include "memory.h"
64 #include "misc.h"
65 #include "net.h"
66
67 #include "if_lereg.h"
68
69
70 #define LE_TICK_SHIFT 14
71
72 /* #define LE_DEBUG */
73 /* #define debug fatal */
74
75 extern int quiet_mode;
76
77 #define LE_MODE_LOOP 4
78 #define LE_MODE_DTX 2
79 #define LE_MODE_DRX 1
80
81
82 #define N_REGISTERS 4
83 #define SRAM_SIZE (128*1024)
84 #define ROM_SIZE 32
85
86
87 struct le_data {
88 int irq_nr;
89
90 uint64_t buf_start;
91 uint64_t buf_end;
92 int len;
93
94 uint8_t rom[ROM_SIZE];
95
96 int reg_select;
97 uint16_t reg[N_REGISTERS];
98
99 unsigned char *sram;
100
101 /* Initialization block: */
102 uint32_t init_block_addr;
103
104 uint16_t mode;
105 uint64_t padr; /* MAC address */
106 uint64_t ladrf;
107 uint32_t rdra; /* receive descriptor ring address */
108 int rlen; /* nr of rx descriptors */
109 uint32_t tdra; /* transmit descriptor ring address */
110 int tlen; /* nr ot tx descriptors */
111
112 /* Current rx and tx descriptor indices: */
113 int rxp;
114 int txp;
115
116 unsigned char *tx_packet;
117 int tx_packet_len;
118
119 unsigned char *rx_packet;
120 int rx_packet_len;
121 int rx_packet_offset;
122 int rx_middle_bit;
123 };
124
125
126 /*
127 * le_read_16bit():
128 *
129 * Read a 16-bit word from the SRAM.
130 */
131 static uint64_t le_read_16bit(struct le_data *d, int addr)
132 {
133 /* TODO: This is for little endian only */
134 int x = d->sram[addr & (SRAM_SIZE-1)] +
135 (d->sram[(addr+1) & (SRAM_SIZE-1)] << 8);
136 return x;
137 }
138
139
140 /*
141 * le_write_16bit():
142 *
143 * Write a 16-bit word to the SRAM.
144 */
145 static void le_write_16bit(struct le_data *d, int addr, uint16_t x)
146 {
147 /* TODO: This is for little endian only */
148 d->sram[addr & (SRAM_SIZE-1)] = x & 0xff;
149 d->sram[(addr+1) & (SRAM_SIZE-1)] = (x >> 8) & 0xff;
150 }
151
152
153 /*
154 * le_chip_init():
155 *
156 * Initialize data structures by reading an 'initialization block' from the
157 * SRAM.
158 */
159 static void le_chip_init(struct le_data *d)
160 {
161 d->init_block_addr = (d->reg[1] & 0xffff) + ((d->reg[2] & 0xff) << 16);
162 if (d->init_block_addr & 1)
163 fatal("[ le: WARNING! initialization block address "
164 "not word aligned? ]\n");
165
166 debug("[ le: d->init_block_addr = 0x%06x ]\n", d->init_block_addr);
167
168 d->mode = le_read_16bit(d, d->init_block_addr + 0);
169 d->padr = le_read_16bit(d, d->init_block_addr + 2);
170 d->padr += (le_read_16bit(d, d->init_block_addr + 4) << 16);
171 d->padr += (le_read_16bit(d, d->init_block_addr + 6) << 32);
172 d->ladrf = le_read_16bit(d, d->init_block_addr + 8);
173 d->ladrf += (le_read_16bit(d, d->init_block_addr + 10) << 16);
174 d->ladrf += (le_read_16bit(d, d->init_block_addr + 12) << 32);
175 d->ladrf += (le_read_16bit(d, d->init_block_addr + 14) << 48);
176 d->rdra = le_read_16bit(d, d->init_block_addr + 16);
177 d->rdra += ((le_read_16bit(d, d->init_block_addr + 18) & 0xff) << 16);
178 d->rlen = 1 << ((le_read_16bit(d, d->init_block_addr + 18) >> 13) & 7);
179 d->tdra = le_read_16bit(d, d->init_block_addr + 20);
180 d->tdra += ((le_read_16bit(d, d->init_block_addr + 22) & 0xff) << 16);
181 d->tlen = 1 << ((le_read_16bit(d, d->init_block_addr + 22) >> 13) & 7);
182
183 debug("[ le: DEBUG: mode %04x ]\n", d->mode);
184 debug("[ le: DEBUG: padr %016llx ]\n", (long long)d->padr);
185 debug("[ le: DEBUG: ladrf %016llx ]\n", (long long)d->ladrf);
186 debug("[ le: DEBUG: rdra %06llx ]\n", d->rdra);
187 debug("[ le: DEBUG: rlen %3i ]\n", d->rlen);
188 debug("[ le: DEBUG: tdra %06llx ]\n", d->tdra);
189 debug("[ le: DEBUG: tlen %3i ]\n", d->tlen);
190
191 /* Set TXON and RXON, unless they are disabled by 'mode': */
192 if (d->mode & LE_MODE_DTX)
193 d->reg[0] &= ~LE_TXON;
194 else
195 d->reg[0] |= LE_TXON;
196
197 if (d->mode & LE_MODE_DRX)
198 d->reg[0] &= ~LE_RXON;
199 else
200 d->reg[0] |= LE_RXON;
201
202 /* Go to the start of the descriptor rings: */
203 d->rxp = d->txp = 0;
204
205 /* Set IDON and reset the INIT bit when we are done. */
206 d->reg[0] |= LE_IDON;
207 d->reg[0] &= ~LE_INIT;
208
209 /* Free any old packets: */
210 if (d->tx_packet != NULL)
211 free(d->tx_packet);
212 d->tx_packet = NULL;
213 d->tx_packet_len = 0;
214
215 if (d->rx_packet != NULL)
216 free(d->rx_packet);
217 d->rx_packet = NULL;
218 d->rx_packet_len = 0;
219 d->rx_packet_offset = 0;
220 d->rx_middle_bit = 0;
221 }
222
223
224 /*
225 * le_tx():
226 *
227 * Check the transmitter descriptor ring for buffers that are owned by the
228 * Lance chip (that is, buffers that are to be transmitted).
229 *
230 * This routine should only be called if TXON is enabled.
231 */
232 static void le_tx(struct net *net, struct le_data *d)
233 {
234 int start_txp = d->txp;
235 uint16_t tx_descr[4];
236 int stp, enp, cur_packet_offset;
237 size_t i;
238 uint32_t bufaddr, buflen;
239
240 /* TODO: This is just a guess: */
241 d->reg[0] &= ~LE_TDMD;
242
243 do {
244 /* Load the 8 descriptor bytes: */
245 tx_descr[0] = le_read_16bit(d, d->tdra + d->txp*8 + 0);
246 tx_descr[1] = le_read_16bit(d, d->tdra + d->txp*8 + 2);
247 tx_descr[2] = le_read_16bit(d, d->tdra + d->txp*8 + 4);
248 tx_descr[3] = le_read_16bit(d, d->tdra + d->txp*8 + 6);
249
250 bufaddr = tx_descr[0] + ((tx_descr[1] & 0xff) << 16);
251 stp = tx_descr[1] & LE_STP? 1 : 0;
252 enp = tx_descr[1] & LE_ENP? 1 : 0;
253 buflen = 4096 - (tx_descr[2] & 0xfff);
254
255 /*
256 * Check the OWN bit. If it is zero, then this buffer is
257 * not ready to be transmitted yet. Also check the '1111'
258 * mark, and make sure that byte-count is reasonable.
259 */
260 if (!(tx_descr[1] & LE_OWN))
261 return;
262 if ((tx_descr[2] & 0xf000) != 0xf000)
263 return;
264 if (buflen < 12 || buflen > 1900) {
265 fatal("[ le_tx(): buflen = %i ]\n", buflen);
266 return;
267 }
268
269 debug("[ le_tx(): descr %3i DUMP: 0x%04x 0x%04x 0x%04x 0x%04x "
270 "=> addr=0x%06x, len=%i bytes, STP=%i ENP=%i ]\n", d->txp,
271 tx_descr[0], tx_descr[1], tx_descr[2], tx_descr[3],
272 bufaddr, buflen, stp, enp);
273
274 if (d->tx_packet == NULL && !stp) {
275 fatal("[ le_tx(): !stp but tx_packet == NULL ]\n");
276 return;
277 }
278
279 if (d->tx_packet != NULL && stp) {
280 fatal("[ le_tx(): stp but tx_packet != NULL ]\n");
281 free(d->tx_packet);
282 d->tx_packet = NULL;
283 d->tx_packet_len = 0;
284 }
285
286 /* Where to write to in the tx_packet: */
287 cur_packet_offset = d->tx_packet_len;
288
289 /* Start of a new packet: */
290 if (stp) {
291 d->tx_packet_len = buflen;
292 d->tx_packet = malloc(buflen);
293 if (d->tx_packet == NULL) {
294 fprintf(stderr, "out of memory (1) in "
295 "le_tx()\n");
296 exit(1);
297 }
298 } else {
299 d->tx_packet_len += buflen;
300 d->tx_packet = realloc(d->tx_packet, d->tx_packet_len);
301 if (d->tx_packet == NULL) {
302 fprintf(stderr, "out of memory (2) in"
303 " le_tx()\n");
304 exit(1);
305 }
306 }
307
308 /* Copy data from SRAM into the tx packet: */
309 for (i=0; i<buflen; i++) {
310 unsigned char ch;
311 ch = d->sram[(bufaddr + i) & (SRAM_SIZE-1)];
312 d->tx_packet[cur_packet_offset + i] = ch;
313 }
314
315 /*
316 * Is this the last buffer in a packet? Then transmit
317 * it, cause an interrupt, and free the memory used by
318 * the packet.
319 */
320 if (enp) {
321 net_ethernet_tx(net, d, d->tx_packet, d->tx_packet_len);
322
323 free(d->tx_packet);
324 d->tx_packet = NULL;
325 d->tx_packet_len = 0;
326
327 d->reg[0] |= LE_TINT;
328 }
329
330 /* Clear the OWN bit: */
331 tx_descr[1] &= ~LE_OWN;
332
333 /* Write back the descriptor to SRAM: */
334 le_write_16bit(d, d->tdra + d->txp*8 + 2, tx_descr[1]);
335 le_write_16bit(d, d->tdra + d->txp*8 + 4, tx_descr[2]);
336 le_write_16bit(d, d->tdra + d->txp*8 + 6, tx_descr[3]);
337
338 /* Go to the next descriptor: */
339 d->txp ++;
340 if (d->txp >= d->tlen)
341 d->txp = 0;
342 } while (d->txp != start_txp);
343
344 /* We are here if all descriptors were taken care of. */
345 fatal("[ le_tx(): all TX descriptors used up? ]\n");
346 }
347
348
349 /*
350 * le_rx():
351 *
352 * This routine should only be called if RXON is enabled.
353 */
354 static void le_rx(struct net *net, struct le_data *d)
355 {
356 int start_rxp = d->rxp;
357 size_t i;
358 uint16_t rx_descr[4];
359 uint32_t bufaddr, buflen;
360
361 do {
362 if (d->rx_packet == NULL)
363 return;
364
365 /* Load the 8 descriptor bytes: */
366 rx_descr[0] = le_read_16bit(d, d->rdra + d->rxp*8 + 0);
367 rx_descr[1] = le_read_16bit(d, d->rdra + d->rxp*8 + 2);
368 rx_descr[2] = le_read_16bit(d, d->rdra + d->rxp*8 + 4);
369 rx_descr[3] = le_read_16bit(d, d->rdra + d->rxp*8 + 6);
370
371 bufaddr = rx_descr[0] + ((rx_descr[1] & 0xff) << 16);
372 buflen = 4096 - (rx_descr[2] & 0xfff);
373
374 /*
375 * Check the OWN bit. If it is zero, then this buffer is
376 * not ready to receive data yet. Also check the '1111'
377 * mark, and make sure that byte-count is reasonable.
378 */
379 if (!(rx_descr[1] & LE_OWN))
380 return;
381 if ((rx_descr[2] & 0xf000) != 0xf000)
382 return;
383 if (buflen < 12 || buflen > 1900) {
384 fatal("[ le_rx(): buflen = %i ]\n", buflen);
385 return;
386 }
387
388 debug("[ le_rx(): descr %3i DUMP: 0x%04x 0x%04x 0x%04x 0x%04x "
389 "=> addr=0x%06x, len=%i bytes ]\n", d->rxp,
390 rx_descr[0], rx_descr[1], rx_descr[2], rx_descr[3],
391 bufaddr, buflen);
392
393 /* Copy data from the packet into SRAM: */
394 for (i=0; i<buflen; i++) {
395 if (d->rx_packet_offset+(ssize_t)i >= d->rx_packet_len)
396 break;
397 d->sram[(bufaddr + i) & (SRAM_SIZE-1)] =
398 d->rx_packet[d->rx_packet_offset + i];
399 }
400
401 /* Here, i is the number of bytes copied. */
402 d->rx_packet_offset += i;
403
404 /* Set the ENP bit if this was the end of a packet: */
405 if (d->rx_packet_offset >= d->rx_packet_len) {
406 rx_descr[1] |= LE_ENP;
407
408 /*
409 * NOTE: The Lance documentation that I have read
410 * says _NOTHING_ about the length being 4 more than
411 * the length of the data. You can guess how
412 * surprised I was when I saw the following in
413 * NetBSD (dev/ic/am7990.c):
414 *
415 * lance_read(sc, LE_RBUFADDR(sc, bix),
416 * (int)rmd.rmd3 - 4);
417 */
418 rx_descr[3] &= ~0xfff;
419 rx_descr[3] |= d->rx_packet_len + 4;
420
421 free(d->rx_packet);
422 d->rx_packet = NULL;
423 d->rx_packet_len = 0;
424 d->rx_packet_offset = 0;
425 d->rx_middle_bit = 0;
426
427 d->reg[0] |= LE_RINT;
428 }
429
430 /* Set the STP bit if this was the start of a packet: */
431 if (!d->rx_middle_bit) {
432 rx_descr[1] |= LE_STP;
433
434 /* Are we continuing on this packet? */
435 if (d->rx_packet != NULL)
436 d->rx_middle_bit = 1;
437 }
438
439 /* Clear the OWN bit: */
440 rx_descr[1] &= ~LE_OWN;
441
442 /* Write back the descriptor to SRAM: */
443 le_write_16bit(d, d->rdra + d->rxp*8 + 2, rx_descr[1]);
444 le_write_16bit(d, d->rdra + d->rxp*8 + 4, rx_descr[2]);
445 le_write_16bit(d, d->rdra + d->rxp*8 + 6, rx_descr[3]);
446
447 /* Go to the next descriptor: */
448 d->rxp ++;
449 if (d->rxp >= d->rlen)
450 d->rxp = 0;
451 } while (d->rxp != start_rxp);
452
453 /* We are here if all descriptors were taken care of. */
454 fatal("[ le_rx(): all RX descriptors used up? ]\n");
455 }
456
457
458 /*
459 * le_register_fix():
460 */
461 static void le_register_fix(struct net *net, struct le_data *d)
462 {
463 /* Init with new Initialization block, if needed. */
464 if (d->reg[0] & LE_INIT)
465 le_chip_init(d);
466
467 #ifdef LE_DEBUG
468 {
469 static int x = 1234;
470 if (x != d->reg[0]) {
471 debug("[ le reg[0] = 0x%04x ]\n", d->reg[0]);
472 x = d->reg[0];
473 }
474 }
475 #endif
476
477 /*
478 * If the receiver is on:
479 * If there is a current rx_packet, try to receive it into the
480 * Lance buffers. Then try to receive any additional packets.
481 */
482 if (d->reg[0] & LE_RXON) {
483 do {
484 if (d->rx_packet != NULL)
485 /* Try to receive the packet: */
486 le_rx(net, d);
487
488 if (d->rx_packet != NULL)
489 /* If the packet wasn't fully received,
490 then abort for now. */
491 break;
492
493 if (d->rx_packet == NULL &&
494 net_ethernet_rx_avail(net, d))
495 net_ethernet_rx(net, d,
496 &d->rx_packet, &d->rx_packet_len);
497 } while (d->rx_packet != NULL);
498 }
499
500 /* If the transmitter is on, check for outgoing buffers: */
501 if (d->reg[0] & LE_TXON)
502 le_tx(net, d);
503
504 /* SERR should be the OR of BABL, CERR, MISS, and MERR: */
505 d->reg[0] &= ~LE_SERR;
506 if (d->reg[0] & (LE_BABL | LE_CERR | LE_MISS | LE_MERR))
507 d->reg[0] |= LE_SERR;
508
509 /* INTR should be the OR of BABL, MISS, MERR, RINT, TINT, IDON: */
510 d->reg[0] &= ~LE_INTR;
511 if (d->reg[0] & (LE_BABL | LE_MISS | LE_MERR | LE_RINT |
512 LE_TINT | LE_IDON))
513 d->reg[0] |= LE_INTR;
514
515 /* The MERR bit clears some bits: */
516 if (d->reg[0] & LE_MERR)
517 d->reg[0] &= ~(LE_RXON | LE_TXON);
518
519 /* The STOP bit clears a lot of stuff: */
520 #if 0
521 /* According to the LANCE manual: (doesn't work with Ultrix) */
522 if (d->reg[0] & LE_STOP)
523 d->reg[0] &= ~(LE_SERR | LE_BABL | LE_CERR | LE_MISS | LE_MERR
524 | LE_RINT | LE_TINT | LE_IDON | LE_INTR | LE_INEA
525 | LE_RXON | LE_TXON | LE_TDMD);
526 #else
527 /* Works with Ultrix: */
528 if (d->reg[0] & LE_STOP)
529 d->reg[0] &= ~(LE_IDON);
530 #endif
531 }
532
533
534 /*
535 * dev_le_tick():
536 */
537 void dev_le_tick(struct cpu *cpu, void *extra)
538 {
539 struct le_data *d = (struct le_data *) extra;
540
541 le_register_fix(cpu->machine->emul->net, d);
542
543 if (d->reg[0] & LE_INTR && d->reg[0] & LE_INEA)
544 cpu_interrupt(cpu, d->irq_nr);
545 else
546 cpu_interrupt_ack(cpu, d->irq_nr);
547 }
548
549
550 /*
551 * le_register_write():
552 *
553 * This function is called when the value 'x' is written to register 'r'.
554 */
555 void le_register_write(struct le_data *d, int r, uint32_t x)
556 {
557 switch (r) {
558 case 0: /* CSR0: */
559 /* Some bits are write-one-to-clear: */
560 if (x & LE_BABL)
561 d->reg[r] &= ~LE_BABL;
562 if (x & LE_CERR)
563 d->reg[r] &= ~LE_CERR;
564 if (x & LE_MISS)
565 d->reg[r] &= ~LE_MISS;
566 if (x & LE_MERR)
567 d->reg[r] &= ~LE_MERR;
568 if (x & LE_RINT)
569 d->reg[r] &= ~LE_RINT;
570 if (x & LE_TINT)
571 d->reg[r] &= ~LE_TINT;
572 if (x & LE_IDON)
573 d->reg[r] &= ~LE_IDON;
574
575 /* Some bits are write-only settable, not clearable: */
576 if (x & LE_TDMD)
577 d->reg[r] |= LE_TDMD;
578 if (x & LE_STRT) {
579 d->reg[r] |= LE_STRT;
580 d->reg[r] &= ~LE_STOP;
581 }
582 if (x & LE_INIT) {
583 if (!(d->reg[r] & LE_STOP))
584 fatal("[ le: attempt to INIT before"
585 " STOPped! ]\n");
586 d->reg[r] |= LE_INIT;
587 d->reg[r] &= ~LE_STOP;
588 }
589 if (x & LE_STOP) {
590 d->reg[r] |= LE_STOP;
591 /* STOP takes precedence over STRT and INIT: */
592 d->reg[r] &= ~(LE_STRT | LE_INIT);
593 }
594
595 /* Some bits get through, both settable and clearable: */
596 d->reg[r] &= ~LE_INEA;
597 d->reg[r] |= (x & LE_INEA);
598 break;
599
600 default:
601 /* CSR1, CSR2, and CSR3: */
602 d->reg[r] = x;
603 }
604 }
605
606
607 /*
608 * dev_le_sram_access():
609 */
610 DEVICE_ACCESS(le_sram)
611 {
612 size_t i;
613 int retval;
614 struct le_data *d = extra;
615
616 #ifdef LE_DEBUG
617 if (writeflag == MEM_WRITE) {
618 fatal("[ le_sram: write to addr 0x%06x: ", (int)relative_addr);
619 for (i=0; i<len; i++)
620 fatal("%02x ", data[i]);
621 fatal("]\n");
622 }
623 #endif
624
625 /* Read/write of the SRAM: */
626 if (relative_addr < SRAM_SIZE && relative_addr + len <= SRAM_SIZE) {
627 if (writeflag == MEM_READ) {
628 memcpy(data, d->sram + relative_addr, len);
629 if (!quiet_mode) {
630 debug("[ le: read from SRAM offset 0x%05x:",
631 relative_addr);
632 for (i=0; i<len; i++)
633 debug(" %02x", data[i]);
634 debug(" ]\n");
635 }
636 retval = 9; /* 9 cycles */
637 } else {
638 memcpy(d->sram + relative_addr, data, len);
639 if (!quiet_mode) {
640 debug("[ le: write to SRAM offset 0x%05x:",
641 relative_addr);
642 for (i=0; i<len; i++)
643 debug(" %02x", data[i]);
644 debug(" ]\n");
645 }
646 retval = 6; /* 6 cycles */
647 }
648 return retval;
649 }
650
651 return 0;
652 }
653
654
655 /*
656 * dev_le_access():
657 */
658 DEVICE_ACCESS(le)
659 {
660 uint64_t idata = 0, odata = 0;
661 size_t i;
662 int retval = 1;
663 struct le_data *d = extra;
664
665 if (writeflag == MEM_WRITE)
666 idata = memory_readmax64(cpu, data, len);
667
668 #ifdef LE_DEBUG
669 if (writeflag == MEM_WRITE) {
670 fatal("[ le: write to addr 0x%06x: ", (int)relative_addr);
671 for (i=0; i<len; i++)
672 fatal("%02x ", data[i]);
673 fatal("]\n");
674 }
675 #endif
676
677 /* Read from station's ROM (ethernet address): */
678 if (relative_addr >= 0xc0000 && relative_addr <= 0xfffff) {
679 uint32_t a;
680 int j = (relative_addr & 0xff) / 4;
681 a = d->rom[j & (ROM_SIZE-1)];
682
683 if (writeflag == MEM_READ) {
684 odata = (a << 24) + (a << 16) + (a << 8) + a;
685 } else {
686 fatal("[ le: WRITE to ethernet addr (%08lx):",
687 (long)relative_addr);
688 for (i=0; i<len; i++)
689 fatal(" %02x", data[i]);
690 fatal(" ]\n");
691 }
692
693 retval = 13; /* 13 cycles */
694 goto do_return;
695 }
696
697
698 switch (relative_addr) {
699
700 /* Register read/write: */
701 case 0:
702 if (writeflag==MEM_READ) {
703 odata = d->reg[d->reg_select];
704 if (!quiet_mode)
705 debug("[ le: read from register 0x%02x: 0x"
706 "%02x ]\n", d->reg_select, (int)odata);
707 /*
708 * A read from csr1..3 should return "undefined"
709 * result if the stop bit is set. However, Ultrix
710 * seems to do just that, so let's _not_ print
711 * a warning here.
712 */
713 } else {
714 if (!quiet_mode)
715 debug("[ le: write to register 0x%02x: 0x"
716 "%02x ]\n", d->reg_select, (int)idata);
717 /*
718 * A write to from csr1..3 when the stop bit is
719 * set should be ignored. However, Ultrix writes
720 * even if the stop bit is set, so let's _not_
721 * print a warning about it.
722 */
723 le_register_write(d, d->reg_select, idata);
724 }
725 break;
726
727 /* Register select: */
728 case 4:
729 if (writeflag==MEM_READ) {
730 odata = d->reg_select;
731 if (!quiet_mode)
732 debug("[ le: read from register select: "
733 "0x%02x ]\n", (int)odata);
734 } else {
735 if (!quiet_mode)
736 debug("[ le: write to register select: "
737 "0x%02x ]\n", (int)idata);
738 d->reg_select = idata & (N_REGISTERS - 1);
739 if (idata >= N_REGISTERS)
740 fatal("[ le: WARNING! register select %i "
741 "(max is %i) ]\n", idata, N_REGISTERS - 1);
742 }
743 break;
744
745 default:
746 if (writeflag==MEM_READ) {
747 fatal("[ le: read from UNIMPLEMENTED addr 0x%06x ]\n",
748 (int)relative_addr);
749 } else {
750 fatal("[ le: write to UNIMPLEMENTED addr 0x%06x: "
751 "0x%08x ]\n", (int)relative_addr, (int)idata);
752 }
753 }
754
755 do_return:
756 if (writeflag == MEM_READ) {
757 memory_writemax64(cpu, data, len, odata);
758 #ifdef LE_DEBUG
759 fatal("[ le: read from addr 0x%06x: 0x%08x ]\n",
760 relative_addr, odata);
761 #endif
762 }
763
764 dev_le_tick(cpu, extra);
765
766 return retval;
767 }
768
769
770 /*
771 * dev_le_init():
772 */
773 void dev_le_init(struct machine *machine, struct memory *mem, uint64_t baseaddr,
774 uint64_t buf_start, uint64_t buf_end, int irq_nr, int len)
775 {
776 char *name2;
777 size_t nlen = 55;
778 struct le_data *d = malloc(sizeof(struct le_data));
779
780 if (d == NULL) {
781 fprintf(stderr, "out of memory\n");
782 exit(1);
783 }
784
785 memset(d, 0, sizeof(struct le_data));
786 d->irq_nr = irq_nr;
787
788 d->sram = malloc(SRAM_SIZE);
789 if (d->sram == NULL) {
790 fprintf(stderr, "out of memory\n");
791 exit(1);
792 }
793 memset(d->sram, 0, SRAM_SIZE);
794
795 /* TODO: Are these actually used yet? */
796 d->len = len;
797 d->buf_start = buf_start;
798 d->buf_end = buf_end;
799
800 /* Initial register contents: */
801 d->reg[0] = LE_STOP;
802
803 d->tx_packet = NULL;
804 d->rx_packet = NULL;
805
806 /* ROM (including the MAC address): */
807 net_generate_unique_mac(machine, &d->rom[0]);
808
809 /* Copies of the MAC address and a test pattern: */
810 d->rom[10] = d->rom[21] = d->rom[5];
811 d->rom[11] = d->rom[20] = d->rom[4];
812 d->rom[12] = d->rom[19] = d->rom[3];
813 d->rom[7] = d->rom[8] = d->rom[23] =
814 d->rom[13] = d->rom[18] = d->rom[2];
815 d->rom[6] = d->rom[9] = d->rom[22] =
816 d->rom[14] = d->rom[17] = d->rom[1];
817 d->rom[15] = d->rom[16] = d->rom[0];
818 d->rom[24] = d->rom[28] = 0xff;
819 d->rom[25] = d->rom[29] = 0x00;
820 d->rom[26] = d->rom[30] = 0x55;
821 d->rom[27] = d->rom[31] = 0xaa;
822
823 memory_device_register(mem, "le_sram", baseaddr,
824 SRAM_SIZE, dev_le_sram_access, (void *)d,
825 DM_DYNTRANS_OK | DM_DYNTRANS_WRITE_OK
826 | DM_READS_HAVE_NO_SIDE_EFFECTS, d->sram);
827
828 name2 = malloc(nlen);
829 if (name2 == NULL) {
830 fprintf(stderr, "out of memory in dev_le_init()\n");
831 exit(1);
832 }
833 snprintf(name2, nlen, "le [%02x:%02x:%02x:%02x:%02x:%02x]",
834 d->rom[0], d->rom[1], d->rom[2], d->rom[3], d->rom[4], d->rom[5]);
835
836 memory_device_register(mem, name2, baseaddr + 0x100000,
837 len - 0x100000, dev_le_access, (void *)d, DM_DEFAULT, NULL);
838
839 machine_add_tickfunction(machine, dev_le_tick, d, LE_TICK_SHIFT);
840
841 net_add_nic(machine->emul->net, d, &d->rom[0]);
842 }
843

  ViewVC Help
Powered by ViewVC 1.1.26