summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/nubus/enetlc.cpp
blob: 55984f78955dccbbe8572901921de32fb8874e25 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// license:BSD-3-Clause
// copyright-holders:R. Belmont
/***************************************************************************

    Apple Ethernet LC Card (820-0443-B, ASSY 670-4443)
    Apple Ethernet LC Twisted Pair Card (820-0532-B, ASSY 630-0891-B)

    Both of these cards are original LC slot cards with a DP83932 SONIC
    Ethernet controller, a declaration ROM, and a MAC address PROM.
    Unlike the NuBus cards, these cards use SONIC's bus mastering DMA
    to go directly to and from the LC's RAM.

***************************************************************************/

#include "emu.h"
#include "enetlc.h"

#include "machine/dp83932c.h"

namespace {
class nubus_enetlctp_device :
	public device_t,
	public device_nubus_card_interface
{
public:
	nubus_enetlctp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

protected:
	nubus_enetlctp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);

	virtual void device_start() override ATTR_COLD;

	virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
	virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;

	required_device<dp83932c_device> m_sonic;

private:
	void card_map(address_map &map);
	u16 ethernet_mac_r(offs_t offset, u16 mem_mask);

	u8 m_mac[6];
	std::string m_fulltag;
};

class nubus_enetlc_device : public nubus_enetlctp_device
{
public:
	nubus_enetlc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);

protected:
	virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD;
};

ROM_START( enetlctp )
	ROM_REGION(0x8000, "declrom", 0)
	ROM_LOAD( "341-0740.bin", 0x000000, 0x008000, CRC(9d47245c) SHA1(447ce6830600f47f63fdc21dd132539decb76001) )
ROM_END

void nubus_enetlctp_device::device_add_mconfig(machine_config &config)
{
	DP83932C(config, m_sonic, 20_MHz_XTAL);
	if (((nubus_slot_device *)owner())->get_nubus_bustag() != nullptr)
	{
		m_fulltag = string_format(":%s", ((nubus_slot_device *)owner())->get_nubus_bustag());
		m_sonic->set_bus(m_fulltag.c_str(), AS_DATA);
	}
	m_sonic->out_int_cb().set(FUNC(nubus_enetlctp_device::slot_irq_w));
}

const tiny_rom_entry *nubus_enetlctp_device::device_rom_region() const
{
	return ROM_NAME( enetlctp );
}

ROM_START( enetlc )
	ROM_REGION(0x8000, "declrom", 0)
	ROM_DEFAULT_BIOS("ver11")
	ROM_SYSTEM_BIOS(0, "ver11", "Ver. 1.1 (1992)")
	ROM_SYSTEM_BIOS(1, "ver10", "Ver. 1.0 (1990)")

	// 341-0470 v1.1, Copyright (C) 1990-92 Apple Computer, Inc. All Rights Reserved.
	ROMX_LOAD( "341-0470.bin", 0x000000, 0x008000, CRC(12a05575) SHA1(574e7f15f3d074e7bf6a9687ef59d3abebfd865c), ROM_BIOS(0) )
	// 341-0842 v1.0, Copyright (C) 1990 Apple Computer, Inc.
	ROMX_LOAD( "341-0842.bin", 0x000000, 0x008000, CRC(92310cb3) SHA1(ba4fd87765104701d5e6bf7962ed3a453e3c5711), ROM_BIOS(1) )
ROM_END

const tiny_rom_entry *nubus_enetlc_device::device_rom_region() const
{
	return ROM_NAME(enetlc);
}

nubus_enetlctp_device::nubus_enetlctp_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
	nubus_enetlctp_device(mconfig, PDSLC_ENETLCTP, tag, owner, clock)
{
}

nubus_enetlctp_device::nubus_enetlctp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
	device_t(mconfig, type, tag, owner, clock),
	device_nubus_card_interface(mconfig, *this),
	m_sonic(*this, "sonic")
{
}

nubus_enetlc_device::nubus_enetlc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
	nubus_enetlctp_device(mconfig, PDSLC_ENETLC, tag, owner, clock)
{
}

void nubus_enetlctp_device::card_map(address_map &map)
{
	// LC and LC II mappings
	map(0x8000'0000, 0x8000'01ff).m(m_sonic, FUNC(dp83932c_device::map)).umask32(0xffff0000);
	map(0x8004'0000, 0x8004'01ff).r(FUNC(nubus_enetlctp_device::ethernet_mac_r));
	map(0x8040'0000, 0x8040'01ff).r(FUNC(nubus_enetlctp_device::ethernet_mac_r));

	// LC III and LC5xx mappings
	map(0xfe00'0000, 0xfe00'01ff).m(m_sonic, FUNC(dp83932c_device::map)).umask32(0xffff0000);
	map(0xfe04'0000, 0xfe04'0007).r(FUNC(nubus_enetlctp_device::ethernet_mac_r));
	map(0xfe40'0000, 0xfe40'0007).r(FUNC(nubus_enetlctp_device::ethernet_mac_r));
}

void nubus_enetlctp_device::device_start()
{
	set_pds_slot(0xe);

	nubus().install_lcpds_map(*this, &nubus_enetlctp_device::card_map);
	install_declaration_rom("declrom");

	// MAC PROM is stored with a bit swizzle (IEEE standard according to SuperMario source?)
	// and must match Apple's assigned OUI block 08:00:07
	const std::array<u8, 6> &MAC = m_sonic->get_mac();
	m_mac[0] = bitswap<8>(0x08, 0, 1, 2, 3, 7, 6, 5, 4);
	m_mac[1] = bitswap<8>(0x00, 0, 1, 2, 3, 7, 6, 5, 4);
	m_mac[2] = bitswap<8>(0x07, 0, 1, 2, 3, 7, 6, 5, 4);
	m_mac[3] = bitswap<8>(MAC[3], 0, 1, 2, 3, 7, 6, 5, 4);
	m_mac[4] = bitswap<8>(MAC[4], 0, 1, 2, 3, 7, 6, 5, 4);
	m_mac[5] = bitswap<8>(MAC[5], 0, 1, 2, 3, 7, 6, 5, 4);
	m_sonic->set_mac(&m_mac[0]);
}

u16 nubus_enetlctp_device::ethernet_mac_r(offs_t offset, u16 mem_mask)
{
	offset <<= 1;
	if (mem_mask == 0x00ff)
	{
		offset++;
	}

	// A word-wide read of the MAC address area is expected to return this magic value.  Some kind of protection?
	if (mem_mask == 0xffff)
	{
		return 0x0028;
	}

	if (offset < 6)
	{
		return m_mac[offset] | m_mac[offset] << 8;
	}
	else if (offset == 7)
	{
		u8 xor_total = 0;

		for (int i = 0; i < 6; i++)
		{
			xor_total ^= (u8)m_mac[i];
		}

		return xor_total ^ 0xff;
	}

	return 0;
}

} // anonymous namespace

DEFINE_DEVICE_TYPE_PRIVATE(PDSLC_ENETLC, device_nubus_card_interface, nubus_enetlc_device, "enetlc", "Apple Ethernet LC Card")
DEFINE_DEVICE_TYPE_PRIVATE(PDSLC_ENETLCTP, device_nubus_card_interface, nubus_enetlctp_device, "enetlctp", "Apple Ethernet LC Twisted-Pair Card")