/[gxemul]/upstream/0.3.1/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.1/devices/dev_le.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26