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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26