dev_mb8696x.cc Source File

Back to the index.

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: */
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 &&
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 |
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))
169 
170  /* Switching to select state? */
171  if (!((*reg_ptr) & FE_B16_SELECT) &&
172  idata & FE_B16_SELECT)
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:
182  d->eeprom_bit_count = 0;
183  break;
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 =
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 
275 
277  devinit->addr, MB8696X_NREGS * d->addr_mult, dev_mb8696x_access, d,
278  DM_DEFAULT, NULL);
279 
280  /* NetBSD/dreamcast expects ident = 86967. */
282 
283  /*
284  * Generate the MAC address, both in the first 6 bytes of the
285  * EEPROM, and in DLCR8..13:
286  */
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 Mar 24 2020 14:04:48 for GXemul by doxygen 1.8.17