1 // license:BSD-3-Clause
2 // copyright-holders:68bit
3 /**********************************************************************
4 
5     PIA IDE Hard Disk Interface
6 
7     Note this interface does appear to have used an 8 bit IDE data path, and
8     does appear to have discarded every second byte of storage - this does not
9     appear to be mis-implementation here. FLEX uses 256 byte sectors so half
10     of the IDE 512 byte sector give the required fit.
11 
12     Some emulators appear to have stripped out that second unused byte when
13     writing their disk images. So their disk images will need to be filled
14     when importing these images for use with this device. Also some emulators
15     appear tolerant of trailing unused data and their images might need to be
16     truncated to the length defined by the disk geomentry.
17 
18     The FLEX drivers for the PIA IDE appear to translate FLEX virtual track
19     and sector ID's into a target geometry. The disk geometry will likely need
20     to be defined and that can be done by using the MAME CHD disk format. The
21     range of FLEX tracks and sectors is limited to 0 to 255 so it needs to use
22     that full virtual range get the largest usable partitions. The drivers
23     support multiple partitions that appears as multiple disks to FLEX to make
24     use of more storage.
25 
26     A similar (compatible) interface appears to have been used by the 'PT69'
27     SBC and drivers and disks targeting the PT69 have also run with this
28     device. The 'PT69' appears to place the PIA at 0xe010 to 0xe013 and it's
29     supporting ROM based at 0xf000, in contrast to the MAME swtpc09i machine
30     which places the PIA IDE in IO6 at 0xe060 (so that the DC5 FDC can remain
31     at IO1) and places the supporting ROM at $e800. The MAME swtpc09i machine
32     has booted some PT69 disk images with some minor software changes.
33 
34 **********************************************************************/
35 
36 #include "emu.h"
37 #include "piaide.h"
38 
39 #include "machine/6821pia.h"
40 #include "machine/idectrl.h"
41 
42 //**************************************************************************
43 //  TYPE DEFINITIONS
44 //**************************************************************************
45 
46 // ======================> ss50_piaide_device
47 
48 class ss50_piaide_device : public device_t, public ss50_card_interface
49 {
50 public:
51 	// construction/destruction
ss50_piaide_device(const machine_config & mconfig,const char * tag,device_t * owner,u32 clock)52 	ss50_piaide_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
53 		: device_t(mconfig, SS50_PIAIDE, tag, owner, clock)
54 		, ss50_card_interface(mconfig, *this)
55 		, m_pia(*this, "pia")
56 		, m_ide(*this, "ide")
57 	{
58 	}
59 
60 protected:
61 	// device-specific overrides
62 	virtual void device_add_mconfig(machine_config &config) override;
63 	virtual void device_start() override;
64 
65 	// interface-specific overrides
66 	virtual uint8_t register_read(offs_t offset) override;
67 	virtual void register_write(offs_t offset, uint8_t data) override;
68 
69 private:
70 	optional_device<pia6821_device> m_pia;
71 	optional_device<ide_controller_device> m_ide;
72 
73 	uint8_t m_pia_porta;
74 	uint8_t m_pia_portb;
75 
76 	uint8_t pia_a_r();
77 	uint8_t pia_b_r();
78 	void pia_a_w(uint8_t data);
79 	void pia_b_w(uint8_t data);
80 
81 };
82 
device_start()83 void ss50_piaide_device::device_start()
84 {
85 	save_item(NAME(m_pia_porta));
86 	save_item(NAME(m_pia_portb));
87 }
88 
89 //-------------------------------------------------
90 //  device_add_mconfig - add device-specific
91 //  machine configuration
92 //-------------------------------------------------
93 
device_add_mconfig(machine_config & config)94 void ss50_piaide_device::device_add_mconfig(machine_config &config)
95 {
96 	PIA6821(config, m_pia, 0);
97 	m_pia->readpa_handler().set(FUNC(ss50_piaide_device::pia_a_r));
98 	m_pia->readpb_handler().set(FUNC(ss50_piaide_device::pia_b_r));
99 	m_pia->writepa_handler().set(FUNC(ss50_piaide_device::pia_a_w));
100 	m_pia->writepb_handler().set(FUNC(ss50_piaide_device::pia_b_w));
101 
102 	IDE_CONTROLLER(config, m_ide).options(ata_devices, "hdd", nullptr, false);
103 }
104 
105 //-------------------------------------------------
106 //  register_read - read from a port register
107 //-------------------------------------------------
108 
register_read(offs_t offset)109 uint8_t ss50_piaide_device::register_read(offs_t offset)
110 {
111 	return m_pia->read(offset & 3);
112 }
113 
114 //-------------------------------------------------
115 //  register_write - write to a port register
116 //-------------------------------------------------
117 
register_write(offs_t offset,uint8_t data)118 void ss50_piaide_device::register_write(offs_t offset, uint8_t data)
119 {
120 	m_pia->write(offset & 3, data);
121 }
122 
123 /******* MC6821 PIA on IDE Board *******/
124 /* Read/Write handlers for pia ide */
125 
pia_a_r()126 uint8_t ss50_piaide_device::pia_a_r()
127 {
128 	return m_pia_porta;
129 }
130 
pia_b_r()131 uint8_t ss50_piaide_device::pia_b_r()
132 {
133 	return m_pia_portb;
134 }
135 
pia_a_w(uint8_t data)136 void ss50_piaide_device::pia_a_w(uint8_t data)
137 {
138 	m_pia_porta = data;
139 }
140 
pia_b_w(uint8_t data)141 void ss50_piaide_device::pia_b_w(uint8_t data)
142 {
143 	uint16_t tempidedata;
144 
145 	m_pia_portb = data;
146 
147 	// Pass through a 16 bit accessor to the IDE bus.
148 	uint8_t low = (data & 0x04) >> 2;
149 	uint8_t high = (data & 0x18) >> 3;
150 	uint16_t ide_mem_mask = low ? 0xff00 : 0x00ff;
151 
152 	if ((data & 0x40)&&(!(data&0x20)))  //cs0=0 cs1=1 bit 5&6
153 	{
154 		if (!(data & 0x02))  //rd line bit 1
155 		{
156 			tempidedata = m_ide->read_cs0(high, ide_mem_mask);
157 			logerror("ide_bus_r: offset $%02X data %04X\n", (data&0x1c)>>2, tempidedata);
158 			m_pia_porta = low ? tempidedata >> 8 : tempidedata & 0x00ff;
159 		}
160 		else if (!(data & 0x01))  //wr line bit 0
161 		{
162 			uint16_t ide_data = low ? m_pia_porta << 8: m_pia_porta;
163 			m_ide->write_cs0(high, ide_data, ide_mem_mask);
164 			logerror("ide_bus_w: offset $%02X data %04X\n", (data&0x1c)>>2, m_pia_porta);
165 		}
166 	}
167 	else if ((data & 0x20)&&(!(data&0x40)))  //cs0=1 cs1=0 bit 5&6
168 	{
169 		if (!(data & 0x02))  //rd line bit 1
170 		{
171 			tempidedata = m_ide->read_cs1(high, ide_mem_mask);
172 			logerror("ide_bus_r: offset $%02X data %04X\n", (data&0x1c)>>2, tempidedata);
173 			m_pia_porta = low ? tempidedata >> 8 : tempidedata & 0x00ff;
174 		}
175 		else if (!(data & 0x01))  //wr line bit 0
176 		{
177 			uint16_t ide_data = low ? m_pia_porta << 8: m_pia_porta;
178 			m_ide->write_cs1(high, ide_data, ide_mem_mask);
179 			logerror("ide_bus_w: offset $%02X data %04X\n", (data&0x1c)>>2, m_pia_porta);
180 		}
181 	}
182 }
183 
184 // device type definition
185 DEFINE_DEVICE_TYPE_PRIVATE(SS50_PIAIDE, ss50_card_interface, ss50_piaide_device, "ss50_piaide", "PIA IDE Hard Disk Interface")
186