/[gxemul]/upstream/0.4.4.1/src/devices/dev_mb8696x.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.1/src/devices/dev_mb8696x.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 37 - (show annotations)
Mon Oct 8 16:21:43 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 8074 byte(s)
0.4.4.1
1 /*
2 * Copyright (C) 2006-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_mb8696x.c,v 1.3 2007/02/03 20:14:23 debug Exp $
29 *
30 * Fujitsu MB8696x Ethernet interface.
31 *
32 * Used as the LAN adapter (MB86967) in the Dreamcast machine mode.
33 *
34 *
35 * Note: This is just a bogus module so far.
36 *
37 * (TODO: "Reverse engineer" more of NetBSD's mb86960.c to implement this.)
38 */
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/time.h>
44
45 #include "cpu.h"
46 #include "device.h"
47 #include "machine.h"
48 #include "memory.h"
49 #include "misc.h"
50 #include "net.h"
51
52 #include "mb86960reg.h"
53
54
55 #ifdef UNSTABLE_DEVEL
56 #define MB8696X_DEBUG
57 #endif
58
59 #ifdef MB8696X_DEBUG
60 #define debug fatal
61 #endif
62
63 struct mb8696x_data {
64 int addr_mult;
65
66 /*
67 * Registers:
68 *
69 * reg contains 32 registers. However, registers 8..15 are bank-
70 * switched, based on a setting in FE_DLCR7. mar_8_15 are "multicast
71 * address registers", and bmpr_8_15 are "buffer memory port
72 * registers".
73 */
74 uint8_t reg[MB8696X_NREGS];
75 uint8_t mar_8_15[8];
76 uint8_t bmpr_8_15[8];
77
78 /* EEPROM contents and internal state during a read operation: */
79 uint8_t eeprom[FE_EEPROM_SIZE];
80 int eeprom_state;
81 uint8_t eeprom_bit_count;
82 uint8_t eeprom_command;
83 uint16_t eeprom_data;
84 };
85
86 #define EEPROM_STATE_NOTHING 0
87 #define EEPROM_STATE_READY 1 /* Waiting for start bit */
88 #define EEPROM_STATE_COMMAND 2 /* Waiting for 8 command bits */
89 #define EEPROM_STATE_READ 3
90
91
92 DEVICE_ACCESS(mb8696x)
93 {
94 struct mb8696x_data *d = (struct mb8696x_data *) extra;
95 uint64_t idata = 0, odata = 0;
96 uint8_t *reg_ptr;
97
98 if (writeflag == MEM_WRITE)
99 idata = memory_readmax64(cpu, data, len);
100
101 relative_addr /= d->addr_mult;
102
103 /*
104 * Default result on reads: (Note special treatment of banked regs.)
105 */
106 reg_ptr = &d->reg[relative_addr];
107 if (relative_addr >= 8 && relative_addr <= 15 &&
108 (d->reg[FE_DLCR7] & FE_D7_RBS) == FE_D7_RBS_MAR)
109 reg_ptr = &d->mar_8_15[relative_addr - 8];
110 if (relative_addr >= 8 && relative_addr <= 15 &&
111 (d->reg[FE_DLCR7] & FE_D7_RBS) == FE_D7_RBS_BMPR)
112 reg_ptr = &d->bmpr_8_15[relative_addr - 8];
113
114 odata = *reg_ptr;
115
116
117 switch (relative_addr) {
118
119 case FE_DLCR0: /* TX interrupt status */
120 case FE_DLCR1: /* RX interrupt status */
121 /* Write-1-to-clear: */
122 if (writeflag == MEM_WRITE)
123 (*reg_ptr) &= ~idata;
124
125 /* TODO: reassert interrupts */
126
127 break;
128
129 case FE_DLCR2: /* TX interrupt control */
130 case FE_DLCR3: /* RX interrupt control */
131 if (writeflag == MEM_WRITE)
132 (*reg_ptr) = idata;
133
134 /* TODO: reassert interrupts */
135
136 break;
137
138 case FE_DLCR6:
139 case FE_DLCR8: /* Ethernet addr byte 0 */
140 case FE_DLCR9: /* Ethernet addr byte 1 */
141 case FE_DLCR10: /* Ethernet addr byte 2 */
142 case FE_DLCR11: /* Ethernet addr byte 3 */
143 case FE_DLCR12: /* Ethernet addr byte 4 */
144 case FE_DLCR13: /* Ethernet addr byte 5 */
145 if (writeflag == MEM_WRITE)
146 (*reg_ptr) = idata;
147 break;
148
149 case FE_DLCR7:
150 if (writeflag == MEM_WRITE) {
151 /* Identification cannot be overwritten: */
152 (*reg_ptr) &= FE_D7_IDENT;
153 (*reg_ptr) |= (idata & ~FE_D7_IDENT);
154 }
155 break;
156
157 case FE_BMPR16:
158 /* EEPROM control */
159 if (writeflag == MEM_WRITE) {
160 if (idata & ~(FE_B16_DOUT | FE_B16_DIN |
161 FE_B16_SELECT | FE_B16_CLOCK)) {
162 fatal("mb8696x: UNIMPLEMENTED bits when "
163 "writing to FE_BMPR16: 0x%02x\n",
164 (int)idata);
165 exit(1);
166 }
167
168 /* Dropped out of select state? */
169 if (!(idata & FE_B16_SELECT))
170 d->eeprom_state = EEPROM_STATE_NOTHING;
171
172 /* Switching to select state? */
173 if (!((*reg_ptr) & FE_B16_SELECT) &&
174 idata & FE_B16_SELECT)
175 d->eeprom_state = EEPROM_STATE_READY;
176
177 /* Bit clock? */
178 if (!((*reg_ptr) & FE_B16_CLOCK) &&
179 idata & FE_B16_CLOCK) {
180 int bit = d->reg[FE_BMPR17] & FE_B17_DATA? 1:0;
181 switch (d->eeprom_state) {
182 case EEPROM_STATE_READY:
183 d->eeprom_state = EEPROM_STATE_COMMAND;
184 d->eeprom_bit_count = 0;
185 break;
186 case EEPROM_STATE_COMMAND:
187 d->eeprom_bit_count ++;
188 d->eeprom_command <<= 1;
189 d->eeprom_command |= bit;
190 if (d->eeprom_bit_count == 8) {
191 int addr = (d->eeprom_command
192 & 0x7f) << 1;
193 /* printf("COMMAND=%08x\n",
194 d->eeprom_command); */
195 if (!(d->eeprom_command&0x80)) {
196 fatal("WRITES to the "
197 "EEPROM are not yet"
198 " implemented.\n");
199 exit(1);
200 }
201 /* This is a read command. */
202 d->eeprom_bit_count = 0;
203 d->eeprom_state =
204 EEPROM_STATE_READ;
205 d->eeprom_data = d->eeprom[addr]
206 * 256 + d->eeprom[addr+1];
207 }
208 break;
209 case EEPROM_STATE_READ:
210 d->reg[FE_BMPR17] = 0;
211 if (d->eeprom_data & 0x8000)
212 d->reg[FE_BMPR17] = FE_B17_DATA;
213 d->eeprom_data <<= 1;
214 d->eeprom_bit_count ++;
215 if (d->eeprom_bit_count > 16)
216 fatal("[ WARNING: more than 16"
217 " bits of EEPROM data "
218 "read? ]\n");
219 break;
220 }
221 }
222
223 (*reg_ptr) = idata;
224 }
225 break;
226
227 case FE_BMPR17:
228 /* EEPROM data */
229 if (writeflag == MEM_WRITE) {
230 if (idata & ~FE_B17_DATA) {
231 fatal("mb8696x: UNIMPLEMENTED bits when "
232 "writing to FE_BMPR17: 0x%02x\n",
233 (int)idata);
234 exit(1);
235 }
236 (*reg_ptr) = idata;
237 }
238 break;
239
240 default:
241 {
242 char *bank = "";
243 if ((d->reg[FE_DLCR7] & FE_D7_RBS) == FE_D7_RBS_MAR)
244 bank = " (bank MAR)";
245 if ((d->reg[FE_DLCR7] & FE_D7_RBS) == FE_D7_RBS_BMPR)
246 bank = " (bank BMPR)";
247 if (writeflag == MEM_READ) {
248 fatal("[ mb8696x: read from UNIMPLEMENTED reg "
249 "%i%s ]\n", (int)relative_addr, bank);
250 } else {
251 fatal("[ mb8696x: write to UNIMPLEMENTED reg "
252 "%i%s: 0x%02x ]\n", (int)relative_addr,
253 bank, (int)idata);
254 }
255
256 #ifdef MB8696X_DEBUG
257 exit(1);
258 #endif
259 }
260 }
261
262 if (writeflag == MEM_READ)
263 memory_writemax64(cpu, data, len, odata);
264
265 return 1;
266 }
267
268
269 DEVINIT(mb8696x)
270 {
271 struct machine *machine = devinit->machine;
272 struct mb8696x_data *d = malloc(sizeof(struct mb8696x_data));
273 if (d == NULL) {
274 fprintf(stderr, "out of memory\n");
275 exit(1);
276 }
277 memset(d, 0, sizeof(struct mb8696x_data));
278 d->addr_mult = devinit->addr_mult;
279
280 memory_device_register(machine->memory, devinit->name, devinit->addr,
281 MB8696X_NREGS * d->addr_mult, dev_mb8696x_access, d,
282 DM_DEFAULT, NULL);
283
284 /* NetBSD/dreamcast expects ident = 86967. */
285 d->reg[FE_DLCR7] = FE_D7_IDENT_86967;
286
287 /*
288 * Generate the MAC address, both in the first 6 bytes of the
289 * EEPROM, and in DLCR8..13:
290 */
291 net_generate_unique_mac(machine, &d->eeprom[0]);
292 memcpy(&d->reg[FE_DLCR8], &d->eeprom[0], 6);
293
294 return 1;
295 }
296

  ViewVC Help
Powered by ViewVC 1.1.26