1 /*****************************************************************************
2 ** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/Memory/romMapperRsIDE.c,v $
3 **
4 ** $Revision: 1.0 $
5 **
6 ** $Date: 2008-03-31 19:42:22 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik, Tomas Karlsson
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #include "romMapperSvi328RsIDE.h"
29 #include "HarddiskIDE.h"
30 #include "MediaDb.h"
31 #include "SlotManager.h"
32 #include "DeviceManager.h"
33 #include "DebugDeviceManager.h"
34 #include "SaveState.h"
35 #include "IoPort.h"
36 #include "I8255.h"
37 #include "Disk.h"
38 #include "Language.h"
39 #include <stdlib.h>
40 #include <string.h>
41 #include <stdio.h>
42 
43 /*
44 PPI    NAME   IDE PIN     PPI    NAME   IDE PIN
45 ---    ----   -------     ---    ----   -------
46 PA0    HD0    17 D0       PB0    HD0    17 D0
47 PA1    HD1    15 D1       PB1    HD1    15 D1
48 PA2    HD2    13 D2       PB2    HD2    13 D2
49 PA3    HD3    11 D3       PB3    HD3    11 D3
50 PA4    HD4     9 D4       PB4    HD4     9 D4
51 PA5    HD5     7 D5       PB5    HD5     7 D5
52 PA6    HD6     5 D6       PB6    HD6     5 D6
53 PA7    HD7     3 D7       PB7    HD7     3 D7
54 
55 PB0    HD8     4 D8       PC0    HD8     4 D8
56 PB1    HD9     6 D9       PC1    HD9     6 D9
57 PB2    HD10    8 D10      PC2    HD10    8 D10
58 PB3    HD11   10 D11      PC3    HD11   10 D11
59 PB4    HD12   12 D12      PC4    HD12   12 D12
60 PB5    HD13   14 D13      PC5    HD13   14 D13
61 PB6    HD14   16 D14      PC6    HD14   16 D14
62 PB7    HD15   18 D15      PC7    HD15   18 D15
63 
64 PC0    HA0    35 A0       PA0    HA0    35 A0
65 PC1    HA1    33 A1       PA1    HA1    33 A1
66 PC2    HA2    36 A2       PA2    HA2    36 A2
67 PC3    N/A                PA3    HCS0   37 CS0
68 PC4    N/A                PA4    HCS1   38 CS1
69 PC5    HCS    37 /CS0     PA5    HWR    23 IOWR
70 PC6    HWR    23 /IOWR    PA6    HRD    25 IORD
71 PC7    HRD    25 /IORD    PA7    HRST   1   RST
72 */
73 
74 typedef struct {
75     int deviceHandle;
76     int debugHandle;
77     HarddiskIde* hdide;
78     I8255* i8255;
79     UInt8 ideAddress;
80     UInt8 ideIoRead;
81     UInt8 ideIoWrite;
82     UInt16 ideData;
83 } RomMapperRsIde;
84 
saveState(RomMapperRsIde * rm)85 static void saveState(RomMapperRsIde* rm)
86 {
87     SaveState* state = saveStateOpenForWrite("RomMapperRsIde");
88 
89     saveStateSet(state, "ideAddress", rm->ideAddress);
90     saveStateSet(state, "ideIoRead", rm->ideIoRead);
91     saveStateSet(state, "ideIoWrite", rm->ideIoWrite);
92     saveStateSet(state, "ideData", rm->ideData);
93 
94     saveStateClose(state);
95 
96     harddiskIdeSaveState(rm->hdide);
97     i8255SaveState(rm->i8255);
98 }
99 
loadState(RomMapperRsIde * rm)100 static void loadState(RomMapperRsIde* rm)
101 {
102     SaveState* state = saveStateOpenForRead("RomMapperRsIde");
103 
104     rm->ideAddress = (UInt8)saveStateGet(state, "ideAddress", 0);
105     rm->ideIoRead = (UInt8)saveStateGet(state, "ideIoRead", 0);
106     rm->ideIoWrite = (UInt8)saveStateGet(state, "ideIoWrite", 0);
107     rm->ideData = (UInt8)saveStateGet(state, "ideData", 0);
108 
109     saveStateClose(state);
110 
111     harddiskIdeLoadState(rm->hdide);
112     i8255LoadState(rm->i8255);
113 }
114 
destroy(RomMapperRsIde * rm)115 static void destroy(RomMapperRsIde* rm)
116 {
117     ioPortUnregister(0x14);
118     ioPortUnregister(0x15);
119     ioPortUnregister(0x16);
120     ioPortUnregister(0x17);
121 
122     deviceManagerUnregister(rm->deviceHandle);
123     debugDeviceUnregister(rm->debugHandle);
124 
125     harddiskIdeDestroy(rm->hdide);
126     i8255Destroy(rm->i8255);
127 
128     free(rm);
129 }
130 
peekIo(RomMapperRsIde * rm,UInt16 ioPort)131 static UInt8 peekIo(RomMapperRsIde* rm, UInt16 ioPort)
132 {
133     return 0xff;
134 }
135 
readB(RomMapperRsIde * rm)136 static UInt8 readB(RomMapperRsIde* rm)
137 {
138     return (UInt8)rm->ideData;
139 }
140 
readCLo(RomMapperRsIde * rm)141 static UInt8 readCLo(RomMapperRsIde* rm)
142 {
143     return (UInt8)(rm->ideData >> 8);
144 }
145 
readCHi(RomMapperRsIde * rm)146 static UInt8 readCHi(RomMapperRsIde* rm)
147 {
148     return (UInt8)(rm->ideData >> 8);
149 }
150 
writeA(RomMapperRsIde * rm,UInt8 value)151 static void writeA(RomMapperRsIde* rm, UInt8 value)
152 {
153     rm->ideAddress = value & 0x07;
154     rm->ideIoRead = value & 0x40 ? 0:1;
155     rm->ideIoWrite = value & 0x20 ? 0:1;
156 
157     if (rm->ideIoRead)
158     {
159         switch (rm->ideAddress)
160         {
161         case 0:
162             rm->ideData = harddiskIdeRead(rm->hdide);
163             break;
164         default:
165             rm->ideData = harddiskIdeReadRegister(rm->hdide, rm->ideAddress);
166             break;
167         }
168     }
169 
170     if (rm->ideIoWrite)
171     {
172         switch (rm->ideAddress)
173         {
174         case 0:
175             harddiskIdeWrite(rm->hdide, rm->ideData);
176             break;
177         default:
178             harddiskIdeWriteRegister(rm->hdide, rm->ideAddress, (UInt8)rm->ideData);
179             break;
180         }
181     }
182 }
183 
writeB(RomMapperRsIde * rm,UInt8 value)184 static void writeB(RomMapperRsIde* rm, UInt8 value)
185 {
186     rm->ideData &= 0xff00;
187     rm->ideData |= value;
188 }
189 
writeCLo(RomMapperRsIde * rm,UInt8 value)190 static void writeCLo(RomMapperRsIde* rm, UInt8 value)
191 {
192     rm->ideData &= 0x00ff;
193     rm->ideData |= value<<8;
194 }
195 
writeCHi(RomMapperRsIde * rm,UInt8 value)196 static void writeCHi(RomMapperRsIde* rm, UInt8 value)
197 {
198     rm->ideData &= 0x00ff;
199     rm->ideData |= value<<8;
200 }
201 
reset(RomMapperRsIde * rm)202 static void reset(RomMapperRsIde* rm)
203 {
204     harddiskIdeReset(rm->hdide);
205 
206     i8255Reset(rm->i8255);
207 }
208 
getDebugInfo(RomMapperRsIde * rm,DbgDevice * dbgDevice)209 static void getDebugInfo(RomMapperRsIde* rm, DbgDevice* dbgDevice)
210 {
211     DbgIoPorts* ioPorts;
212     int i;
213 
214     ioPorts = dbgDeviceAddIoPorts(dbgDevice, langDbgDevIdeSviRs(), 4);
215     for (i = 0; i < 4; i++) {
216         dbgIoPortsAddPort(ioPorts, i, 0x14 + i, DBG_IO_READWRITE, i8255Peek(rm->i8255, 0x14 + i));
217     }
218 }
219 
romMapperSvi328RsIdeCreate(int hdId)220 int romMapperSvi328RsIdeCreate(int hdId)
221 {
222     DeviceCallbacks callbacks = { destroy, reset, saveState, loadState };
223     DebugCallbacks dbgCallbacks = { getDebugInfo, NULL, NULL, NULL };
224     RomMapperRsIde* rm;
225 
226     rm = malloc(sizeof(RomMapperRsIde));
227 
228     rm->deviceHandle = deviceManagerRegister(ROM_SVI328RSIDE, &callbacks, rm);
229     rm->debugHandle = debugDeviceRegister(DBGTYPE_PORT, langDbgDevIdeSviRs(), &dbgCallbacks, rm);
230 
231     rm->i8255 = i8255Create( NULL, NULL,    writeA,
232                              NULL, readB,   writeB,
233                              NULL, readCLo, writeCLo,
234                              NULL, readCHi, writeCHi,
235                              rm);
236 
237     ioPortRegister(0x14, i8255Read, i8255Write, rm->i8255); // PPI Port A
238     ioPortRegister(0x15, i8255Read, i8255Write, rm->i8255); // PPI Port B
239     ioPortRegister(0x16, i8255Read, i8255Write, rm->i8255); // PPI Port C
240     ioPortRegister(0x17, i8255Read, i8255Write, rm->i8255); // PPI Mode
241 
242     rm->hdide = harddiskIdeCreate(diskGetHdDriveId(hdId, 0));
243 
244     reset(rm);
245 
246     return 1;
247 }
248