/[gxemul]/upstream/0.4.6/src/devices/dev_rtl8139c.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_rtl8139c.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: 6221 byte(s)
0.4.6
1 /*
2 * Copyright (C) 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_rtl8139c.c,v 1.5 2007/06/15 19:57:34 debug Exp $
29 *
30 * COMMENT: Realtek 8139 ethernet controller
31 *
32 * TODO: Pretty much everything.
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "cpu.h"
40 #include "device.h"
41 #include "emul.h"
42 #include "interrupt.h"
43 #include "machine.h"
44 #include "memory.h"
45 #include "misc.h"
46 #include "net.h"
47
48
49 #include "rtl81x9reg.h"
50
51
52 #define DEV_RTL8139C_LENGTH 0x100
53 #define EEPROM_SIZE 0x100
54
55 struct rtl8139c_data {
56 struct interrupt irq;
57 unsigned char macaddr[6];
58
59 /* Registers: */
60 uint8_t rl_command;
61 uint8_t rl_eecmd;
62
63 /* EEPROM: */
64 int eeprom_address_width;
65 int eeprom_selected;
66 int8_t eeprom_cur_cmd_bit;
67 uint16_t eeprom_cur_cmd;
68 uint16_t eeprom_cur_data;
69 uint16_t eeprom_reg[EEPROM_SIZE];
70 };
71
72
73 /*
74 * eeprom_clk():
75 *
76 * Called whenever the eeprom CLK bit is toggled from 0 to 1.
77 */
78 static void eeprom_clk(struct rtl8139c_data *d)
79 {
80 int data_in = d->rl_eecmd & RL_EE_DATAIN? 1 : 0;
81
82 if (d->eeprom_cur_cmd_bit < d->eeprom_address_width + 4) {
83 d->eeprom_cur_cmd <<= 1;
84 d->eeprom_cur_cmd |= data_in;
85 }
86
87 if (d->eeprom_cur_cmd_bit == d->eeprom_address_width + 3) {
88 int cmd = d->eeprom_cur_cmd >> d->eeprom_address_width;
89 int addr = d->eeprom_cur_cmd & ((1<<d->eeprom_address_width)-1);
90
91 debug("[ rtl8139c eeprom cmd=0x%x addr=0x%02x ]\n", cmd, addr);
92
93 switch (cmd) {
94
95 case RL_9346_READ:
96 d->eeprom_cur_data = d->eeprom_reg[addr % EEPROM_SIZE];
97 break;
98
99 default:fatal("[ rtl8139c eeprom: only the read command has"
100 " been implemented. sorry. ]\n");
101 exit(1);
102 }
103 }
104
105 /* Data output: (Note: Only the READ command has been implemented.) */
106 if (d->eeprom_cur_cmd_bit >= d->eeprom_address_width + 4) {
107 int cur_out_bit = d->eeprom_cur_cmd_bit -
108 (d->eeprom_address_width + 4);
109 int bit = d->eeprom_cur_data & (1 << (15-cur_out_bit));
110
111 if (bit)
112 d->rl_eecmd |= RL_EE_DATAOUT;
113 else
114 d->rl_eecmd &= ~RL_EE_DATAOUT;
115 }
116
117 d->eeprom_cur_cmd_bit ++;
118
119 if (d->eeprom_cur_cmd_bit >= d->eeprom_address_width + 4 + 16) {
120 d->eeprom_cur_cmd = 0;
121 d->eeprom_cur_cmd_bit = 0;
122 }
123 }
124
125
126 DEVICE_ACCESS(rtl8139c)
127 {
128 struct rtl8139c_data *d = extra;
129 uint64_t idata = 0, odata = 0;
130
131 if (writeflag == MEM_WRITE)
132 idata = memory_readmax64(cpu, data, len);
133
134 switch (relative_addr) {
135
136 case RL_COMMAND:
137 if (writeflag == MEM_WRITE) {
138 if (idata & RL_CMD_RESET) {
139 /* Reset. TODO */
140
141 /* ... and then clear the reset bit: */
142 idata &= ~RL_CMD_RESET;
143 }
144
145 d->rl_command = idata;
146 } else {
147 odata = d->rl_command;
148 }
149 break;
150
151 case RL_EECMD:
152 if (writeflag == MEM_WRITE) {
153 uint8_t old = d->rl_eecmd;
154 d->rl_eecmd = idata;
155
156 if (!d->eeprom_selected && d->rl_eecmd & RL_EE_SEL) {
157 /* Reset eeprom cmd bit state: */
158 d->eeprom_cur_cmd = 0;
159 d->eeprom_cur_cmd_bit = 0;
160 }
161 d->eeprom_selected = d->rl_eecmd & RL_EE_SEL;
162
163 if (idata & RL_EE_CLK && !(old & RL_EE_CLK))
164 eeprom_clk(d);
165 } else {
166 odata = d->rl_eecmd;
167 }
168 break;
169
170 case 0x82:
171 /* Unknown address, but OpenBSD's re driver writes
172 a 0x01 to this address, in re_reset(). */
173 if (writeflag == MEM_WRITE) {
174 if (idata != 0x01) {
175 fatal("rtl8139c: unimplemented write to"
176 " register 0x82.\n");
177 exit(1);
178 }
179 }
180 break;
181
182 default:if (writeflag == MEM_WRITE) {
183 fatal("[ rtl8139c: unimplemented write to "
184 "offset 0x%x: data=0x%x ]\n", (int)
185 relative_addr, (int)idata);
186 } else {
187 fatal("[ rtl8139c: unimplemented read from "
188 "offset 0x%x ]\n", (int)relative_addr);
189 }
190 exit(1);
191 }
192
193 if (writeflag == MEM_READ)
194 memory_writemax64(cpu, data, len, odata);
195
196 return 1;
197 }
198
199
200 DEVINIT(rtl8139c)
201 {
202 char *name2;
203 size_t nlen = 100;
204 struct rtl8139c_data *d;
205
206 CHECK_ALLOCATION(d = malloc(sizeof(struct rtl8139c_data)));
207 memset(d, 0, sizeof(struct rtl8139c_data));
208
209 INTERRUPT_CONNECT(devinit->interrupt_path, d->irq);
210
211 net_generate_unique_mac(devinit->machine, d->macaddr);
212
213 /* TODO: eeprom address width = 6 on 8129? */
214 d->eeprom_address_width = 8;
215 d->eeprom_reg[0] = 0x8139;
216 d->eeprom_reg[7] = d->macaddr[0] + (d->macaddr[1] << 8);
217 d->eeprom_reg[8] = d->macaddr[2] + (d->macaddr[3] << 8);
218 d->eeprom_reg[9] = d->macaddr[4] + (d->macaddr[5] << 8);
219
220 CHECK_ALLOCATION(name2 = malloc(nlen));
221 snprintf(name2, nlen, "%s [%02x:%02x:%02x:%02x:%02x:%02x]",
222 devinit->name, d->macaddr[0], d->macaddr[1], d->macaddr[2],
223 d->macaddr[3], d->macaddr[4], d->macaddr[5]);
224
225 memory_device_register(devinit->machine->memory, name2,
226 devinit->addr, DEV_RTL8139C_LENGTH, dev_rtl8139c_access, (void *)d,
227 DM_DEFAULT, NULL);
228
229 net_add_nic(devinit->machine->emul->net, d, d->macaddr);
230
231 return 1;
232 }
233

  ViewVC Help
Powered by ViewVC 1.1.26