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
|
// license:BSD-3-Clause
// copyright-holders:
/**************************************************************************************************
Adaptec AHA-2940AU PCI
Based off AIC-7860/7861
References:
- https://github.com/torvalds/linux/tree/master/drivers/scsi/aic7xxx
TODO:
- Stub, enough to make it surpass initial POST and nothing else;
- Lack specific documentation for AIC-7860, we base on AIC-7890 for now;
**************************************************************************************************/
#include "emu.h"
#include "aha2940au.h"
#define LOG_WARN (1U << 1)
#define VERBOSE (LOG_GENERAL | LOG_WARN)
//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"
#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
DEFINE_DEVICE_TYPE(AHA2940AU, aha2940au_scsi_device, "aha2940au", "Adaptec AHA-2940AU SCSI controller")
aha2940au_scsi_device::aha2940au_scsi_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: pci_card_device(mconfig, type, tag, owner, clock)
, m_eeprom(*this, "eeprom")
, m_scsi_rom(*this, "scsi_rom")
{
// TODO: unknown revision
// class code should be 0x01'0000 as per AIC-7890 manual
set_ids(0x90046178, 0x00, 0x010000, 0x90046178);
}
aha2940au_scsi_device::aha2940au_scsi_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: aha2940au_scsi_device(mconfig, AHA2940AU, tag, owner, clock)
{
}
// NOTE: BIOS is FAT compressed, decompress as 8bios.bin under the hood.
ROM_START( aha2940au )
ROM_REGION32_LE( 0x8000, "scsi_rom", ROMREGION_ERASEFF )
ROM_SYSTEM_BIOS( 0, "v1.30", "AHA-2940AU (v1.30)" )
// "589247-00_c_bios_2400_(C)1996_v1.30.u3"
ROMX_LOAD( "589247-00.u3", 0x0000, 0x8000, CRC(de00492b) SHA1(a6015bcd51e51015a5710d7ac1929e28bf033db4), ROM_BIOS(0) )
// default eeprom contents, to be verified
ROM_REGION16_LE( 0x80, "eeprom", ROMREGION_ERASEFF )
ROM_LOAD( "93c46.u1", 0x00, 0x80, CRC(c82242ce) SHA1(93311b8c02e87492a40c1df6ea4eb60628bb2825) )
ROM_END
const tiny_rom_entry *aha2940au_scsi_device::device_rom_region() const
{
return ROM_NAME(aha2940au);
}
void aha2940au_scsi_device::device_add_mconfig(machine_config &config)
{
// AIC-7860Q
EEPROM_93C46_16BIT(config, m_eeprom);
}
void aha2940au_scsi_device::device_start()
{
pci_card_device::device_start();
// TODO: BAR setup from AIC-7890, verify
add_map( 256, M_IO, FUNC(aha2940au_scsi_device::io_map));
// TODO: enables M_64A on demand
add_map( 4096, M_MEM, FUNC(aha2940au_scsi_device::mem_map));
add_rom((u8 *)m_scsi_rom->base(), 0x8000);
expansion_rom_base = 0xc8000;
// TODO: BIST capable
// INTA#
intr_pin = 1;
// TODO: definitely uses PCI regs 0x3e/0x3f
// max_lat = 0x19, min_gnt = 0x27 for AIC-7890
// others may be different
}
void aha2940au_scsi_device::device_reset()
{
pci_card_device::device_reset();
command = 0x0000;
// Can be bus master (bit 2), can use Memory Write and Invalidate (bit 4)
command_mask = 0x17;
// cap list (bit 4), fast back-to-back (bit 7), medium DEVSEL#
status = 0x0290;
remap_cb();
}
u8 aha2940au_scsi_device::capptr_r()
{
return 0xdc;
}
void aha2940au_scsi_device::config_map(address_map &map)
{
pci_card_device::config_map(map);
// map(0x40, 0x40) DEVCONFIG
// map(0x41, 0x41) DEVSTATUS0
// map(0x42, 0x42) DEVSTATUS1
// map(0x43, 0x43) PCIERRGEN
// PME 1.0
map(0xdc, 0xdf).lr32(NAME([] { return 0x0001'0001; }));
// map(0xe0, 0xe1) PM_CSR
// map(0xe2, 0xe2) PMCSR_BSE
// map(0xe3, 0xe3) PM_DATA
// map(0xff, 0xff) IDENREG
}
void aha2940au_scsi_device::io_map(address_map &map)
{
// SEECTL
map(0x1e, 0x1e).lrw8(
NAME([this] (offs_t offset) {
return 0x10 | m_eeprom->do_read();
}),
NAME([this] (offs_t offset, u8 data) {
LOG("SEECTL %02x\n", data);
m_eeprom->di_write(BIT(data, 1));
m_eeprom->clk_write(BIT(data, 2));
m_eeprom->cs_write(BIT(data, 3));
})
);
// HCNTRL
map(0x87, 0x87).lr8(NAME([] () { return 0xff; }));
}
void aha2940au_scsi_device::mem_map(address_map &map)
{
}
|