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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26