/[gxemul]/upstream/0.4.4/src/devices/dev_dec21143.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.4/src/devices/dev_dec21143.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 35 - (show annotations)
Mon Oct 8 16:21:26 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 28387 byte(s)
0.4.4
1 /*
2 * Copyright (C) 2005-2007 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_dec21143.c,v 1.28 2007/01/05 15:20:06 debug Exp $
29 *
30 * DEC 21143 ("Tulip") ethernet controller. Implemented from Intel document
31 * 278074-001 ("21143 PC/CardBus 10/100Mb/s Ethernet LAN Controller") and by
32 * reverse-engineering OpenBSD and NetBSD sources.
33 *
34 * This device emulates several sub-components:
35 *
36 * 21143: This is the actual ethernet controller.
37 *
38 * MII: The "physical" network interface.
39 *
40 * SROM: A ROM area containing setting such as which MAC address to
41 * use, and info about the MII.
42 *
43 *
44 * TODO:
45 * o) Handle _writes_ to MII registers.
46 * o) Make it work with modern Linux kernels (as a guest OS).
47 * o) Endianness for descriptors? If necessary.
48 * o) Actually handle the "Setup" packet.
49 * o) MAC filtering on incoming packets.
50 * o) Don't hardcode as many values.
51 */
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56
57 #include "cpu.h"
58 #include "device.h"
59 #include "devices.h"
60 #include "emul.h"
61 #include "interrupt.h"
62 #include "machine.h"
63 #include "memory.h"
64 #include "misc.h"
65 #include "net.h"
66
67 #include "mii.h"
68 #include "tulipreg.h"
69
70
71 /* #define debug fatal */
72
73 #define DEC21143_TICK_SHIFT 16
74
75 #define N_REGS 32
76 #define ROM_WIDTH 6
77
78 struct dec21143_data {
79 struct interrupt irq;
80 int irq_was_asserted;
81
82 /* PCI: */
83 int pci_little_endian;
84
85 /* Ethernet address, and a network which we are connected to: */
86 uint8_t mac[6];
87 struct net *net;
88
89 /* SROM emulation: */
90 uint8_t srom[1 << (ROM_WIDTH + 1)];
91 int srom_curbit;
92 int srom_opcode;
93 int srom_opcode_has_started;
94 int srom_addr;
95
96 /* MII PHY emulation: */
97 uint16_t mii_phy_reg[MII_NPHY * 32];
98 int mii_state;
99 int mii_bit;
100 int mii_opcode;
101 int mii_phyaddr;
102 int mii_regaddr;
103
104 /* 21143 registers: */
105 uint32_t reg[N_REGS];
106
107 /* Internal TX state: */
108 uint64_t cur_tx_addr;
109 unsigned char *cur_tx_buf;
110 int cur_tx_buf_len;
111 int tx_idling;
112 int tx_idling_threshold;
113
114 /* Internal RX state: */
115 uint64_t cur_rx_addr;
116 unsigned char *cur_rx_buf;
117 int cur_rx_buf_len;
118 int cur_rx_offset;
119 };
120
121
122 /* Internal states during MII data stream decode: */
123 #define MII_STATE_RESET 0
124 #define MII_STATE_START_WAIT 1
125 #define MII_STATE_READ_OP 2
126 #define MII_STATE_READ_PHYADDR_REGADDR 3
127 #define MII_STATE_A 4
128 #define MII_STATE_D 5
129 #define MII_STATE_IDLE 6
130
131
132 /*
133 * dec21143_rx():
134 *
135 * Receive a packet. (If there is no current packet, then check for newly
136 * arrived ones. If the current packet couldn't be fully transfered the
137 * last time, then continue on that packet.)
138 */
139 int dec21143_rx(struct cpu *cpu, struct dec21143_data *d)
140 {
141 uint64_t addr = d->cur_rx_addr, bufaddr;
142 unsigned char descr[16];
143 uint32_t rdes0, rdes1, rdes2, rdes3;
144 int bufsize, buf1_size, buf2_size, i, writeback_len = 4, to_xfer;
145
146 /* No current packet? Then check for new ones. */
147 if (d->cur_rx_buf == NULL) {
148 /* Nothing available? Then abort. */
149 if (!net_ethernet_rx_avail(d->net, d))
150 return 0;
151
152 /* Get the next packet into our buffer: */
153 net_ethernet_rx(d->net, d, &d->cur_rx_buf,
154 &d->cur_rx_buf_len);
155
156 /* Append a 4 byte CRC: */
157 d->cur_rx_buf_len += 4;
158 d->cur_rx_buf = realloc(d->cur_rx_buf, d->cur_rx_buf_len);
159 if (d->cur_rx_buf == NULL) {
160 fatal("dec21143_rx(): out of memory\n");
161 exit(1);
162 }
163 /* Well... the CRC is just zeros, for now. */
164 memset(d->cur_rx_buf + d->cur_rx_buf_len - 4, 0, 4);
165
166 d->cur_rx_offset = 0;
167 }
168
169 /* fatal("{ dec21143_rx: base = 0x%08x }\n", (int)addr); */
170 addr &= 0x7fffffff;
171
172 if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),
173 MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {
174 fatal("[ dec21143_rx: memory_rw failed! ]\n");
175 return 0;
176 }
177
178 rdes0 = descr[0] + (descr[1]<<8) + (descr[2]<<16) + (descr[3]<<24);
179
180 /* Only use descriptors owned by the 21143: */
181 if (!(rdes0 & TDSTAT_OWN)) {
182 d->reg[CSR_STATUS/8] |= STATUS_RU;
183 return 0;
184 }
185
186 if (!cpu->memory_rw(cpu, cpu->mem, addr + sizeof(uint32_t), descr +
187 sizeof(uint32_t), sizeof(uint32_t) * 3, MEM_READ, PHYSICAL |
188 NO_EXCEPTIONS)) {
189 fatal("[ dec21143_rx: memory_rw failed! ]\n");
190 return 0;
191 }
192
193 rdes1 = descr[4] + (descr[5]<<8) + (descr[6]<<16) + (descr[7]<<24);
194 rdes2 = descr[8] + (descr[9]<<8) + (descr[10]<<16) + (descr[11]<<24);
195 rdes3 = descr[12] + (descr[13]<<8) + (descr[14]<<16) + (descr[15]<<24);
196
197 buf1_size = rdes1 & TDCTL_SIZE1;
198 buf2_size = (rdes1 & TDCTL_SIZE2) >> TDCTL_SIZE2_SHIFT;
199 bufaddr = buf1_size? rdes2 : rdes3;
200 bufsize = buf1_size? buf1_size : buf2_size;
201
202 d->reg[CSR_STATUS/8] &= ~STATUS_RS;
203
204 if (rdes1 & TDCTL_ER)
205 d->cur_rx_addr = d->reg[CSR_RXLIST / 8];
206 else {
207 if (rdes1 & TDCTL_CH)
208 d->cur_rx_addr = rdes3;
209 else
210 d->cur_rx_addr += 4 * sizeof(uint32_t);
211 }
212
213 debug("{ RX (%llx): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
214 (long long)addr, rdes0, rdes1, rdes2, rdes3, bufsize, (int)bufaddr);
215 bufaddr &= 0x7fffffff;
216
217 /* Turn off all status bits, and give up ownership: */
218 rdes0 = 0x00000000;
219
220 to_xfer = d->cur_rx_buf_len - d->cur_rx_offset;
221 if (to_xfer > bufsize)
222 to_xfer = bufsize;
223
224 /* DMA bytes from the packet into emulated physical memory: */
225 for (i=0; i<to_xfer; i++) {
226 cpu->memory_rw(cpu, cpu->mem, bufaddr + i,
227 d->cur_rx_buf + d->cur_rx_offset + i, 1, MEM_WRITE,
228 PHYSICAL | NO_EXCEPTIONS);
229 /* fatal(" %02x", d->cur_rx_buf[d->cur_rx_offset + i]); */
230 }
231
232 /* Was this the first buffer in a frame? Then mark it as such. */
233 if (d->cur_rx_offset == 0)
234 rdes0 |= TDSTAT_Rx_FS;
235
236 d->cur_rx_offset += to_xfer;
237
238 /* Frame completed? */
239 if (d->cur_rx_offset >= d->cur_rx_buf_len) {
240 rdes0 |= TDSTAT_Rx_LS;
241
242 /* Set the frame length: */
243 rdes0 |= (d->cur_rx_buf_len << 16) & TDSTAT_Rx_FL;
244
245 /* Frame too long? (1518 is max ethernet frame length) */
246 if (d->cur_rx_buf_len > 1518)
247 rdes0 |= TDSTAT_Rx_TL;
248
249 /* Cause a receiver interrupt: */
250 d->reg[CSR_STATUS/8] |= STATUS_RI;
251
252 free(d->cur_rx_buf);
253 d->cur_rx_buf = NULL;
254 d->cur_rx_buf_len = 0;
255 }
256
257 /* Descriptor writeback: */
258 descr[ 0] = rdes0; descr[ 1] = rdes0 >> 8;
259 descr[ 2] = rdes0 >> 16; descr[ 3] = rdes0 >> 24;
260 if (writeback_len > 1) {
261 descr[ 4] = rdes1; descr[ 5] = rdes1 >> 8;
262 descr[ 6] = rdes1 >> 16; descr[ 7] = rdes1 >> 24;
263 descr[ 8] = rdes2; descr[ 9] = rdes2 >> 8;
264 descr[10] = rdes2 >> 16; descr[11] = rdes2 >> 24;
265 descr[12] = rdes3; descr[13] = rdes3 >> 8;
266 descr[14] = rdes3 >> 16; descr[15] = rdes3 >> 24;
267 }
268
269 if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t)
270 * writeback_len, MEM_WRITE, PHYSICAL | NO_EXCEPTIONS)) {
271 fatal("[ dec21143_rx: memory_rw failed! ]\n");
272 return 0;
273 }
274
275 return 1;
276 }
277
278
279 /*
280 * dec21143_tx():
281 *
282 * Transmit a packet, if the guest OS has marked a descriptor as containing
283 * data to transmit.
284 */
285 int dec21143_tx(struct cpu *cpu, struct dec21143_data *d)
286 {
287 uint64_t addr = d->cur_tx_addr, bufaddr;
288 unsigned char descr[16];
289 uint32_t tdes0, tdes1, tdes2, tdes3;
290 int bufsize, buf1_size, buf2_size, i, writeback_len = 4;
291
292 addr &= 0x7fffffff;
293
294 if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t),
295 MEM_READ, PHYSICAL | NO_EXCEPTIONS)) {
296 fatal("[ dec21143_tx: memory_rw failed! ]\n");
297 return 0;
298 }
299
300 tdes0 = descr[0] + (descr[1]<<8) + (descr[2]<<16) + (descr[3]<<24);
301
302 /* fatal("{ dec21143_tx: base=0x%08x, tdes0=0x%08x }\n",
303 (int)addr, (int)tdes0); */
304
305 /* Only process packets owned by the 21143: */
306 if (!(tdes0 & TDSTAT_OWN)) {
307 if (d->tx_idling > d->tx_idling_threshold) {
308 d->reg[CSR_STATUS/8] |= STATUS_TU;
309 d->tx_idling = 0;
310 } else
311 d->tx_idling ++;
312 return 0;
313 }
314
315 if (!cpu->memory_rw(cpu, cpu->mem, addr + sizeof(uint32_t), descr +
316 sizeof(uint32_t), sizeof(uint32_t) * 3, MEM_READ, PHYSICAL |
317 NO_EXCEPTIONS)) {
318 fatal("[ dec21143_tx: memory_rw failed! ]\n");
319 return 0;
320 }
321
322 tdes1 = descr[4] + (descr[5]<<8) + (descr[6]<<16) + (descr[7]<<24);
323 tdes2 = descr[8] + (descr[9]<<8) + (descr[10]<<16) + (descr[11]<<24);
324 tdes3 = descr[12] + (descr[13]<<8) + (descr[14]<<16) + (descr[15]<<24);
325
326 buf1_size = tdes1 & TDCTL_SIZE1;
327 buf2_size = (tdes1 & TDCTL_SIZE2) >> TDCTL_SIZE2_SHIFT;
328 bufaddr = buf1_size? tdes2 : tdes3;
329 bufsize = buf1_size? buf1_size : buf2_size;
330
331 d->reg[CSR_STATUS/8] &= ~STATUS_TS;
332
333 if (tdes1 & TDCTL_ER)
334 d->cur_tx_addr = d->reg[CSR_TXLIST / 8];
335 else {
336 if (tdes1 & TDCTL_CH)
337 d->cur_tx_addr = tdes3;
338 else
339 d->cur_tx_addr += 4 * sizeof(uint32_t);
340 }
341
342 /*
343 fatal("{ TX (%llx): 0x%08x 0x%08x 0x%x 0x%x: buf %i bytes at 0x%x }\n",
344 (long long)addr, tdes0, tdes1, tdes2, tdes3, bufsize, (int)bufaddr);
345 */
346 bufaddr &= 0x7fffffff;
347
348 /* Assume no error: */
349 tdes0 &= ~ (TDSTAT_Tx_UF | TDSTAT_Tx_EC | TDSTAT_Tx_LC
350 | TDSTAT_Tx_NC | TDSTAT_Tx_LO | TDSTAT_Tx_TO | TDSTAT_ES);
351
352 if (tdes1 & TDCTL_Tx_SET) {
353 /*
354 * Setup Packet.
355 *
356 * TODO. For now, just ignore it, and pretend it worked.
357 */
358 /* fatal("{ TX: setup packet }\n"); */
359 if (bufsize != 192)
360 fatal("[ dec21143: setup packet len = %i, should be"
361 " 192! ]\n", (int)bufsize);
362 if (tdes1 & TDCTL_Tx_IC)
363 d->reg[CSR_STATUS/8] |= STATUS_TI;
364 /* New descriptor values, according to the docs: */
365 tdes0 = 0x7fffffff; tdes1 = 0xffffffff;
366 tdes2 = 0xffffffff; tdes3 = 0xffffffff;
367 } else {
368 /*
369 * Data Packet.
370 */
371 /* fatal("{ TX: data packet: "); */
372 if (tdes1 & TDCTL_Tx_FS) {
373 /* First segment. Let's allocate a new buffer: */
374 /* fatal("new frame }\n"); */
375 d->cur_tx_buf = malloc(bufsize);
376 d->cur_tx_buf_len = 0;
377 } else {
378 /* Not first segment. Increase the length of
379 the current buffer: */
380 /* fatal("continuing last frame }\n"); */
381 d->cur_tx_buf = realloc(d->cur_tx_buf,
382 d->cur_tx_buf_len + bufsize);
383 }
384
385 if (d->cur_tx_buf == NULL) {
386 fatal("dec21143_tx(): out of memory\n");
387 exit(1);
388 }
389
390 /* "DMA" data from emulated physical memory into the buf: */
391 for (i=0; i<bufsize; i++) {
392 cpu->memory_rw(cpu, cpu->mem, bufaddr + i,
393 d->cur_tx_buf + d->cur_tx_buf_len + i, 1, MEM_READ,
394 PHYSICAL | NO_EXCEPTIONS);
395 /* fatal(" %02x", d->cur_tx_buf[
396 d->cur_tx_buf_len + i]); */
397 }
398
399 d->cur_tx_buf_len += bufsize;
400
401 /* Last segment? Then actually transmit it: */
402 if (tdes1 & TDCTL_Tx_LS) {
403 /* fatal("{ TX: data frame complete. }\n"); */
404 if (d->net != NULL) {
405 net_ethernet_tx(d->net, d, d->cur_tx_buf,
406 d->cur_tx_buf_len);
407 } else {
408 static int warn = 0;
409 if (!warn)
410 fatal("[ dec21143: WARNING! Not "
411 "connected to a network! ]\n");
412 warn = 1;
413 }
414
415 free(d->cur_tx_buf);
416 d->cur_tx_buf = NULL;
417 d->cur_tx_buf_len = 0;
418
419 /* TODO: Shouldn't the OWN bit be cleared on all
420 kinds of segments, not just the Last? */
421
422 /* We are done. */
423 tdes0 &= ~TDSTAT_OWN;
424 writeback_len = 1;
425
426 /* Interrupt, if Tx_IC is set: */
427 if (tdes1 & TDCTL_Tx_IC)
428 d->reg[CSR_STATUS/8] |= STATUS_TI;
429 }
430 }
431
432 /* Error summary: */
433 if (tdes0 & (TDSTAT_Tx_UF | TDSTAT_Tx_EC | TDSTAT_Tx_LC
434 | TDSTAT_Tx_NC | TDSTAT_Tx_LO | TDSTAT_Tx_TO))
435 tdes0 |= TDSTAT_ES;
436
437 /* Descriptor writeback: */
438 descr[ 0] = tdes0; descr[ 1] = tdes0 >> 8;
439 descr[ 2] = tdes0 >> 16; descr[ 3] = tdes0 >> 24;
440 if (writeback_len > 1) {
441 descr[ 4] = tdes1; descr[ 5] = tdes1 >> 8;
442 descr[ 6] = tdes1 >> 16; descr[ 7] = tdes1 >> 24;
443 descr[ 8] = tdes2; descr[ 9] = tdes2 >> 8;
444 descr[10] = tdes2 >> 16; descr[11] = tdes2 >> 24;
445 descr[12] = tdes3; descr[13] = tdes3 >> 8;
446 descr[14] = tdes3 >> 16; descr[15] = tdes3 >> 24;
447 }
448
449 if (!cpu->memory_rw(cpu, cpu->mem, addr, descr, sizeof(uint32_t)
450 * writeback_len, MEM_WRITE, PHYSICAL | NO_EXCEPTIONS)) {
451 fatal("[ dec21143_tx: memory_rw failed! ]\n");
452 return 0;
453 }
454
455 return 1;
456 }
457
458
459 /*
460 * dev_dec21143_tick():
461 */
462 void dev_dec21143_tick(struct cpu *cpu, void *extra)
463 {
464 struct dec21143_data *d = extra;
465 int asserted;
466
467 if (d->reg[CSR_OPMODE / 8] & OPMODE_ST)
468 while (dec21143_tx(cpu, d))
469 ;
470
471 if (d->reg[CSR_OPMODE / 8] & OPMODE_SR)
472 while (dec21143_rx(cpu, d))
473 ;
474
475 /* Normal and Abnormal interrupt summary: */
476 d->reg[CSR_STATUS / 8] &= ~(STATUS_NIS | STATUS_AIS);
477 if (d->reg[CSR_STATUS / 8] & 0x00004845)
478 d->reg[CSR_STATUS / 8] |= STATUS_NIS;
479 if (d->reg[CSR_STATUS / 8] & 0x0c0037ba)
480 d->reg[CSR_STATUS / 8] |= STATUS_AIS;
481
482 asserted = d->reg[CSR_STATUS / 8] & d->reg[CSR_INTEN / 8] & 0x0c01ffff;
483
484 if (asserted)
485 INTERRUPT_ASSERT(d->irq);
486 if (!asserted && d->irq_was_asserted)
487 INTERRUPT_DEASSERT(d->irq);
488
489 /* Remember assertion flag: */
490 d->irq_was_asserted = asserted;
491 }
492
493
494 /*
495 * mii_access():
496 *
497 * This function handles accesses to the MII. Data streams seem to be of the
498 * following format:
499 *
500 * vv---- starting delimiter
501 * ... 01 xx yyyyy zzzzz a[a] dddddddddddddddd
502 * ^---- I am starting with mii_bit = 0 here
503 *
504 * where x = opcode (10 = read, 01 = write)
505 * y = PHY address
506 * z = register address
507 * a = on Reads: ACK bit (returned, should be 0)
508 * on Writes: _TWO_ dummy bits (10)
509 * d = 16 bits of data (MSB first)
510 */
511 static void mii_access(struct cpu *cpu, struct dec21143_data *d,
512 uint32_t oldreg, uint32_t idata)
513 {
514 int obit, ibit = 0;
515 uint16_t tmp;
516
517 /* Only care about data during clock cycles: */
518 if (!(idata & MIIROM_MDC))
519 return;
520
521 if (idata & MIIROM_MDC && oldreg & MIIROM_MDC)
522 return;
523
524 /* fatal("[ mii_access(): 0x%08x ]\n", (int)idata); */
525
526 if (idata & MIIROM_BR) {
527 fatal("[ mii_access(): MIIROM_BR: TODO ]\n");
528 return;
529 }
530
531 obit = idata & MIIROM_MDO? 1 : 0;
532
533 if (d->mii_state >= MII_STATE_START_WAIT &&
534 d->mii_state <= MII_STATE_READ_PHYADDR_REGADDR &&
535 idata & MIIROM_MIIDIR)
536 fatal("[ mii_access(): bad dir? ]\n");
537
538 switch (d->mii_state) {
539
540 case MII_STATE_RESET:
541 /* Wait for a starting delimiter (0 followed by 1). */
542 if (obit)
543 return;
544 if (idata & MIIROM_MIIDIR)
545 return;
546 /* fatal("[ mii_access(): got a 0 delimiter ]\n"); */
547 d->mii_state = MII_STATE_START_WAIT;
548 d->mii_opcode = 0;
549 d->mii_phyaddr = 0;
550 d->mii_regaddr = 0;
551 break;
552
553 case MII_STATE_START_WAIT:
554 /* Wait for a starting delimiter (0 followed by 1). */
555 if (!obit)
556 return;
557 if (idata & MIIROM_MIIDIR) {
558 d->mii_state = MII_STATE_RESET;
559 return;
560 }
561 /* fatal("[ mii_access(): got a 1 delimiter ]\n"); */
562 d->mii_state = MII_STATE_READ_OP;
563 d->mii_bit = 0;
564 break;
565
566 case MII_STATE_READ_OP:
567 if (d->mii_bit == 0) {
568 d->mii_opcode = obit << 1;
569 /* fatal("[ mii_access(): got first opcode bit "
570 "(%i) ]\n", obit); */
571 } else {
572 d->mii_opcode |= obit;
573 /* fatal("[ mii_access(): got opcode = %i ]\n",
574 d->mii_opcode); */
575 d->mii_state = MII_STATE_READ_PHYADDR_REGADDR;
576 }
577 d->mii_bit ++;
578 break;
579
580 case MII_STATE_READ_PHYADDR_REGADDR:
581 /* fatal("[ mii_access(): got phy/reg addr bit nr %i (%i)"
582 " ]\n", d->mii_bit - 2, obit); */
583 if (d->mii_bit <= 6)
584 d->mii_phyaddr |= obit << (6-d->mii_bit);
585 else
586 d->mii_regaddr |= obit << (11-d->mii_bit);
587 d->mii_bit ++;
588 if (d->mii_bit >= 12) {
589 /* fatal("[ mii_access(): phyaddr=0x%x regaddr=0x"
590 "%x ]\n", d->mii_phyaddr, d->mii_regaddr); */
591 d->mii_state = MII_STATE_A;
592 }
593 break;
594
595 case MII_STATE_A:
596 switch (d->mii_opcode) {
597 case MII_COMMAND_WRITE:
598 if (d->mii_bit >= 13)
599 d->mii_state = MII_STATE_D;
600 break;
601 case MII_COMMAND_READ:
602 ibit = 0;
603 d->mii_state = MII_STATE_D;
604 break;
605 default:debug("[ mii_access(): UNIMPLEMENTED MII opcode "
606 "%i (probably just a bug in GXemul's "
607 "MII data stream handling) ]\n", d->mii_opcode);
608 d->mii_state = MII_STATE_RESET;
609 }
610 d->mii_bit ++;
611 break;
612
613 case MII_STATE_D:
614 switch (d->mii_opcode) {
615 case MII_COMMAND_WRITE:
616 if (idata & MIIROM_MIIDIR)
617 fatal("[ mii_access(): write: bad dir? ]\n");
618 obit = obit? (0x8000 >> (d->mii_bit - 14)) : 0;
619 tmp = d->mii_phy_reg[(d->mii_phyaddr << 5) +
620 d->mii_regaddr] | obit;
621 if (d->mii_bit >= 29) {
622 d->mii_state = MII_STATE_IDLE;
623 debug("[ mii_access(): WRITE to phyaddr=0x%x "
624 "regaddr=0x%x: 0x%04x ]\n", d->mii_phyaddr,
625 d->mii_regaddr, tmp);
626 }
627 break;
628 case MII_COMMAND_READ:
629 if (!(idata & MIIROM_MIIDIR))
630 break;
631 tmp = d->mii_phy_reg[(d->mii_phyaddr << 5) +
632 d->mii_regaddr];
633 if (d->mii_bit == 13)
634 debug("[ mii_access(): READ phyaddr=0x%x "
635 "regaddr=0x%x: 0x%04x ]\n", d->mii_phyaddr,
636 d->mii_regaddr, tmp);
637 ibit = tmp & (0x8000 >> (d->mii_bit - 13));
638 if (d->mii_bit >= 28)
639 d->mii_state = MII_STATE_IDLE;
640 break;
641 }
642 d->mii_bit ++;
643 break;
644
645 case MII_STATE_IDLE:
646 d->mii_bit ++;
647 if (d->mii_bit >= 31)
648 d->mii_state = MII_STATE_RESET;
649 break;
650 }
651
652 d->reg[CSR_MIIROM / 8] &= ~MIIROM_MDI;
653 if (ibit)
654 d->reg[CSR_MIIROM / 8] |= MIIROM_MDI;
655 }
656
657
658 /*
659 * srom_access():
660 *
661 * This function handles reads from the Ethernet Address ROM. This is not a
662 * 100% correct implementation, as it was reverse-engineered from OpenBSD
663 * sources; it seems to work with OpenBSD, NetBSD, and Linux, though.
664 *
665 * Each transfer (if I understood this correctly) is of the following format:
666 *
667 * 1xx yyyyyy zzzzzzzzzzzzzzzz
668 *
669 * where 1xx = operation (6 means a Read),
670 * yyyyyy = ROM address
671 * zz...z = data
672 *
673 * y and z are _both_ read and written to at the same time; this enables the
674 * operating system to sense the number of bits in y (when reading, all y bits
675 * are 1 except the last one).
676 */
677 static void srom_access(struct cpu *cpu, struct dec21143_data *d,
678 uint32_t oldreg, uint32_t idata)
679 {
680 int obit, ibit;
681
682 /* debug("CSR9 WRITE! 0x%08x\n", (int)idata); */
683
684 /* New selection? Then reset internal state. */
685 if (idata & MIIROM_SR && !(oldreg & MIIROM_SR)) {
686 d->srom_curbit = 0;
687 d->srom_opcode = 0;
688 d->srom_opcode_has_started = 0;
689 d->srom_addr = 0;
690 }
691
692 /* Only care about data during clock cycles: */
693 if (!(idata & MIIROM_SROMSK))
694 return;
695
696 obit = 0;
697 ibit = idata & MIIROM_SROMDI? 1 : 0;
698 /* debug("CLOCK CYCLE! (bit %i): ", d->srom_curbit); */
699
700 /*
701 * Linux sends more zeroes before starting the actual opcode, than
702 * OpenBSD and NetBSD. Hopefully this is correct. (I'm just guessing
703 * that all opcodes should start with a 1, perhaps that's not really
704 * the case.)
705 */
706 if (!ibit && !d->srom_opcode_has_started)
707 return;
708
709 if (d->srom_curbit < 3) {
710 d->srom_opcode_has_started = 1;
711 d->srom_opcode <<= 1;
712 d->srom_opcode |= ibit;
713 /* debug("opcode input '%i'\n", ibit); */
714 } else {
715 switch (d->srom_opcode) {
716 case TULIP_SROM_OPC_READ:
717 if (d->srom_curbit < ROM_WIDTH + 3) {
718 obit = d->srom_curbit < ROM_WIDTH + 2;
719 d->srom_addr <<= 1;
720 d->srom_addr |= ibit;
721 } else {
722 uint16_t romword = d->srom[d->srom_addr*2]
723 + (d->srom[d->srom_addr*2+1] << 8);
724 if (d->srom_curbit == ROM_WIDTH + 3)
725 debug("[ dec21143: ROM read from offset"
726 " 0x%03x: 0x%04x ]\n",
727 d->srom_addr, romword);
728 obit = romword & (0x8000 >>
729 (d->srom_curbit - ROM_WIDTH - 3))? 1 : 0;
730 }
731 break;
732 default:fatal("[ dec21243: unimplemented SROM/EEPROM "
733 "opcode %i ]\n", d->srom_opcode);
734 }
735 d->reg[CSR_MIIROM / 8] &= ~MIIROM_SROMDO;
736 if (obit)
737 d->reg[CSR_MIIROM / 8] |= MIIROM_SROMDO;
738 /* debug("input '%i', output '%i'\n", ibit, obit); */
739 }
740
741 d->srom_curbit ++;
742
743 /*
744 * Done opcode + addr + data? Then restart. (At least NetBSD does
745 * sequential reads without turning selection off and then on.)
746 */
747 if (d->srom_curbit >= 3 + ROM_WIDTH + 16) {
748 d->srom_curbit = 0;
749 d->srom_opcode = 0;
750 d->srom_opcode_has_started = 0;
751 d->srom_addr = 0;
752 }
753 }
754
755
756 /*
757 * dec21143_reset():
758 *
759 * Set the 21143 registers, SROM, and MII data to reasonable values.
760 */
761 static void dec21143_reset(struct cpu *cpu, struct dec21143_data *d)
762 {
763 int leaf;
764
765 if (d->cur_rx_buf != NULL)
766 free(d->cur_rx_buf);
767 if (d->cur_tx_buf != NULL)
768 free(d->cur_tx_buf);
769 d->cur_rx_buf = d->cur_tx_buf = NULL;
770
771 memset(d->reg, 0, sizeof(uint32_t) * N_REGS);
772 memset(d->srom, 0, sizeof(d->srom));
773 memset(d->mii_phy_reg, 0, sizeof(d->mii_phy_reg));
774
775 /* Register values at reset, according to the manual: */
776 d->reg[CSR_BUSMODE / 8] = 0xfe000000; /* csr0 */
777 d->reg[CSR_MIIROM / 8] = 0xfff483ff; /* csr9 */
778 d->reg[CSR_SIACONN / 8] = 0xffff0000; /* csr13 */
779 d->reg[CSR_SIATXRX / 8] = 0xffffffff; /* csr14 */
780 d->reg[CSR_SIAGEN / 8] = 0x8ff00000; /* csr15 */
781
782 d->tx_idling_threshold = 10;
783 d->cur_rx_addr = d->cur_tx_addr = 0;
784
785 /* Version (= 1) and Chip count (= 1): */
786 d->srom[TULIP_ROM_SROM_FORMAT_VERION] = 1;
787 d->srom[TULIP_ROM_CHIP_COUNT] = 1;
788
789 /* Set the MAC address: */
790 memcpy(d->srom + TULIP_ROM_IEEE_NETWORK_ADDRESS, d->mac, 6);
791
792 leaf = 30;
793 d->srom[TULIP_ROM_CHIPn_DEVICE_NUMBER(0)] = 0;
794 d->srom[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0)] = leaf & 255;
795 d->srom[TULIP_ROM_CHIPn_INFO_LEAF_OFFSET(0)+1] = leaf >> 8;
796
797 d->srom[leaf+TULIP_ROM_IL_SELECT_CONN_TYPE] = 0; /* Not used? */
798 d->srom[leaf+TULIP_ROM_IL_MEDIA_COUNT] = 2;
799 leaf += TULIP_ROM_IL_MEDIAn_BLOCK_BASE;
800
801 d->srom[leaf] = 7; /* descriptor length */
802 d->srom[leaf+1] = TULIP_ROM_MB_21142_SIA;
803 d->srom[leaf+2] = TULIP_ROM_MB_MEDIA_100TX;
804 /* here comes 4 bytes of GPIO control/data settings */
805 leaf += d->srom[leaf];
806
807 d->srom[leaf] = 15; /* descriptor length */
808 d->srom[leaf+1] = TULIP_ROM_MB_21142_MII;
809 d->srom[leaf+2] = 0; /* PHY nr */
810 d->srom[leaf+3] = 0; /* len of select sequence */
811 d->srom[leaf+4] = 0; /* len of reset sequence */
812 /* 5,6, 7,8, 9,10, 11,12, 13,14 = unused by GXemul */
813 leaf += d->srom[leaf];
814
815 /* MII PHY initial state: */
816 d->mii_state = MII_STATE_RESET;
817
818 /* PHY #0: */
819 d->mii_phy_reg[MII_BMSR] = BMSR_100TXFDX | BMSR_10TFDX |
820 BMSR_ACOMP | BMSR_ANEG | BMSR_LINK;
821 }
822
823
824 DEVICE_ACCESS(dec21143)
825 {
826 struct dec21143_data *d = extra;
827 uint64_t idata = 0, odata = 0;
828 uint32_t oldreg = 0;
829 int regnr = relative_addr >> 3;
830
831 if (writeflag == MEM_WRITE)
832 idata = memory_readmax64(cpu, data, len | d->pci_little_endian);
833
834 if ((relative_addr & 7) == 0 && regnr < N_REGS) {
835 if (writeflag == MEM_READ) {
836 odata = d->reg[regnr];
837 } else {
838 oldreg = d->reg[regnr];
839 switch (regnr) {
840 case CSR_STATUS / 8: /* Zero-on-write */
841 d->reg[regnr] &= ~(idata & 0x0c01ffff);
842 break;
843 case CSR_MISSED / 8: /* Read only */
844 break;
845 default:d->reg[regnr] = idata;
846 }
847 }
848 } else
849 fatal("[ dec21143: WARNING! unaligned access (0x%x) ]\n",
850 (int)relative_addr);
851
852 switch (relative_addr) {
853
854 case CSR_BUSMODE: /* csr0 */
855 if (writeflag == MEM_WRITE) {
856 /* Software reset takes effect immediately. */
857 if (idata & BUSMODE_SWR) {
858 dec21143_reset(cpu, d);
859 idata &= ~BUSMODE_SWR;
860 }
861 }
862 break;
863
864 case CSR_TXPOLL: /* csr1 */
865 if (writeflag == MEM_READ)
866 fatal("[ dec21143: UNIMPLEMENTED READ from "
867 "txpoll ]\n");
868 d->tx_idling = d->tx_idling_threshold;
869 dev_dec21143_tick(cpu, extra);
870 break;
871
872 case CSR_RXPOLL: /* csr2 */
873 if (writeflag == MEM_READ)
874 fatal("[ dec21143: UNIMPLEMENTED READ from "
875 "rxpoll ]\n");
876 dev_dec21143_tick(cpu, extra);
877 break;
878
879 case CSR_RXLIST: /* csr3 */
880 if (writeflag == MEM_WRITE) {
881 debug("[ dec21143: setting RXLIST to 0x%x ]\n",
882 (int)idata);
883 if (idata & 0x3)
884 fatal("[ dec21143: WARNING! RXLIST not aligned"
885 "? (0x%llx) ]\n", (long long)idata);
886 idata &= ~0x3;
887 d->cur_rx_addr = idata;
888 }
889 break;
890
891 case CSR_TXLIST: /* csr4 */
892 if (writeflag == MEM_WRITE) {
893 debug("[ dec21143: setting TXLIST to 0x%x ]\n",
894 (int)idata);
895 if (idata & 0x3)
896 fatal("[ dec21143: WARNING! TXLIST not aligned"
897 "? (0x%llx) ]\n", (long long)idata);
898 idata &= ~0x3;
899 d->cur_tx_addr = idata;
900 }
901 break;
902
903 case CSR_STATUS: /* csr5 */
904 case CSR_INTEN: /* csr7 */
905 if (writeflag == MEM_WRITE) {
906 /* Recalculate interrupt assertion. */
907 dev_dec21143_tick(cpu, extra);
908 }
909 break;
910
911 case CSR_OPMODE: /* csr6: */
912 if (writeflag == MEM_WRITE) {
913 if (idata & 0x02000000) {
914 /* A must-be-one bit. */
915 idata &= ~0x02000000;
916 }
917 if (idata & OPMODE_ST) {
918 idata &= ~OPMODE_ST;
919 } else {
920 /* Turned off TX? Then idle: */
921 d->reg[CSR_STATUS/8] |= STATUS_TPS;
922 }
923 if (idata & OPMODE_SR) {
924 idata &= ~OPMODE_SR;
925 } else {
926 /* Turned off RX? Then go to stopped state: */
927 d->reg[CSR_STATUS/8] &= ~STATUS_RS;
928 }
929 idata &= ~(OPMODE_HBD | OPMODE_SCR | OPMODE_PCS
930 | OPMODE_PS | OPMODE_SF | OPMODE_TTM | OPMODE_FD);
931 if (idata & OPMODE_PNIC_IT) {
932 idata &= ~OPMODE_PNIC_IT;
933 d->tx_idling = d->tx_idling_threshold;
934 }
935 if (idata != 0) {
936 fatal("[ dec21143: UNIMPLEMENTED OPMODE bits"
937 ": 0x%08x ]\n", (int)idata);
938 }
939 dev_dec21143_tick(cpu, extra);
940 }
941 break;
942
943 case CSR_MISSED: /* csr8 */
944 break;
945
946 case CSR_MIIROM: /* csr9 */
947 if (writeflag == MEM_WRITE) {
948 if (idata & MIIROM_MDC)
949 mii_access(cpu, d, oldreg, idata);
950 else
951 srom_access(cpu, d, oldreg, idata);
952 }
953 break;
954
955 case CSR_SIASTAT: /* csr12 */
956 /* Auto-negotiation status = Good. */
957 odata = SIASTAT_ANS_FLPGOOD;
958 break;
959
960 case CSR_SIATXRX: /* csr14 */
961 /* Auto-negotiation Enabled */
962 odata = SIATXRX_ANE;
963 break;
964
965 case CSR_SIACONN: /* csr13 */
966 case CSR_SIAGEN: /* csr15 */
967 /* Don't print warnings for these, for now. */
968 break;
969
970 default:if (writeflag == MEM_READ)
971 fatal("[ dec21143: read from unimplemented 0x%02x ]\n",
972 (int)relative_addr);
973 else
974 fatal("[ dec21143: write to unimplemented 0x%02x: "
975 "0x%02x ]\n", (int)relative_addr, (int)idata);
976 }
977
978 if (writeflag == MEM_READ)
979 memory_writemax64(cpu, data, len | d->pci_little_endian, odata);
980
981 return 1;
982 }
983
984
985 DEVINIT(dec21143)
986 {
987 struct dec21143_data *d;
988 char name2[100];
989
990 d = malloc(sizeof(struct dec21143_data));
991 if (d == NULL) {
992 fprintf(stderr, "out of memory\n");
993 exit(1);
994 }
995 memset(d, 0, sizeof(struct dec21143_data));
996
997 INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
998 d->pci_little_endian = devinit->pci_little_endian;
999
1000 net_generate_unique_mac(devinit->machine, d->mac);
1001 net_add_nic(devinit->machine->emul->net, d, d->mac);
1002 d->net = devinit->machine->emul->net;
1003
1004 dec21143_reset(devinit->machine->cpus[0], d);
1005
1006 snprintf(name2, sizeof(name2), "%s [%02x:%02x:%02x:%02x:%02x:%02x]",
1007 devinit->name, d->mac[0], d->mac[1], d->mac[2], d->mac[3],
1008 d->mac[4], d->mac[5]);
1009
1010 memory_device_register(devinit->machine->memory, name2,
1011 devinit->addr, 0x100, dev_dec21143_access, d, DM_DEFAULT, NULL);
1012
1013 machine_add_tickfunction(devinit->machine,
1014 dev_dec21143_tick, d, DEC21143_TICK_SHIFT, 0.0);
1015
1016 /*
1017 * NetBSD/cats uses memory accesses, OpenBSD/cats uses I/O registers.
1018 * Let's make a mirror from the memory range to the I/O range:
1019 */
1020 dev_ram_init(devinit->machine, devinit->addr2, 0x100, DEV_RAM_MIRROR
1021 | DEV_RAM_MIGHT_POINT_TO_DEVICES, devinit->addr);
1022
1023 return 1;
1024 }
1025

  ViewVC Help
Powered by ViewVC 1.1.26