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