this repo has no description
1/*
2 IWMEVDEV.c
3
4 Copyright (C) 2006 Philip Cummins, Paul C. Pratt
5
6 You can redistribute this file and/or modify it under the terms
7 of version 2 of the GNU General Public License as published by
8 the Free Software Foundation. You should have received a copy
9 of the license along with this file; see the file COPYING.
10
11 This file is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 license for more details.
15*/
16
17/*
18 Integrated Woz Machine EMulated DEVice
19
20 Emulates the IWM found in the Mac Plus.
21
22 This code is adapted from "IWM.c" in vMac by Philip Cummins.
23*/
24
25/*
26 This is the emulation for the IWM, the Integrated Woz Machine.
27 It's basically a serial to parallel converter with some timing
28 in-built into it to perform handshaking. Emulation so far just
29 includes Status and Mode Register Accesses.
30*/
31
32#include "PICOMMON.h"
33
34#include "IWMEMDEV.h"
35
36#define IWM_dolog (dbglog_HAVE && 0)
37
38/*
39 ReportAbnormalID unused 0x0603 - 0x06FF
40*/
41
42#define kph0L 0x00 /* CA0 off (0) */
43#define kph0H 0x01 /* CA0 on (1) */
44#define kph1L 0x02 /* CA1 off (0) */
45#define kph1H 0x03 /* CA1 on (1) */
46#define kph2L 0x04 /* CA2 off (0) */
47#define kph2H 0x05 /* CA2 on (1) */
48#define kph3L 0x06 /* LSTRB off (low) */
49#define kph3H 0x07 /* LSTRB on (high) */
50#define kmtrOff 0x08 /* disk enable off */
51#define kmtrOn 0x09 /* disk enable on */
52#define kintDrive 0x0A /* select internal drive */
53#define kextDrive 0x0B /* select external drive */
54#define kq6L 0x0C /* Q6 off */
55#define kq6H 0x0D /* Q6 on */
56#define kq7L 0x0E /* Q7 off */
57#define kq7H 0x0F /* Q7 on */
58
59#define kph0 0x01
60#define kph1 0x02
61#define kph2 0x04
62#define kph3 0x08
63#define kmtr 0x10
64#define kdrv 0x20
65#define kq6 0x40
66#define kq7 0x80
67
68typedef struct
69{
70 ui3b DataIn; /* Read Data Register */
71 ui3b Handshake; /* Read Handshake Register */
72 ui3b Status; /* Read Status Register */
73 ui3b Mode;
74 /* Drive Off : Write Mode Register */
75 /* Drive On : Write Data Register */
76 ui3b DataOut; /* Write Data Register */
77 ui3b Lines; /* Used to Access Disk Drive Registers */
78} IWM_Ty;
79
80IWM_Ty IWM;
81
82GLOBALPROC IWM_Reset(void)
83{
84 IWM.DataIn = IWM.Handshake = IWM.Status = IWM.Mode =
85 IWM.DataOut = IWM.Lines = 0;
86}
87
88typedef enum {On, Off} Mode_Ty;
89
90LOCALPROC IWM_Set_Lines(ui3b line, Mode_Ty the_mode)
91{
92 if (the_mode == Off) {
93 IWM.Lines &= (0xFF - line);
94 } else {
95 IWM.Lines |= line;
96 }
97}
98
99LOCALFUNC ui3b IWM_Read_Reg(void)
100{
101 switch ((IWM.Lines & (kq6 + kq7)) >> 6) {
102 case 0 :
103#if (CurEmMd >= kEmMd_SE) && (CurEmMd <= kEmMd_IIx)
104 /* don't report */
105#else
106 ReportAbnormalID(0x0601, "IWM Data Read");
107#endif
108#if IWM_dolog
109 dbglog_WriteNote("IWM Data Read");
110#endif
111 return IWM.DataIn;
112 break;
113 case 1 :
114#if IWM_dolog
115 dbglog_WriteNote("IWM Status Read");
116#endif
117 return IWM.Status;
118 break;
119 case 2 :
120 ReportAbnormalID(0x0602, "IWM Handshake Read");
121#if IWM_dolog
122 dbglog_WriteNote("IWM Handshake Read");
123#endif
124 return IWM.Handshake;
125 break;
126 case 3 :
127 default :
128 /*
129 should alway be in 0-3,
130 but compiler warnings don't know that
131 */
132 return 0;
133 break;
134 }
135}
136
137LOCALPROC IWM_Write_Reg(ui3b in)
138{
139 if (((IWM.Lines & kmtr) >> 4) == 0) {
140#if IWM_dolog
141 dbglog_WriteNote("IWM Mode Register Write");
142#endif
143 IWM.Mode = in;
144 IWM.Status = ((IWM.Status & 0xE0) + (IWM.Mode & 0x1F));
145 }
146}
147
148GLOBALFUNC ui5b IWM_Access(ui5b Data, blnr WriteMem, CPTR addr)
149{
150#if IWM_dolog
151 dbglog_AddrAccess("IWM", Data, WriteMem, addr);
152#endif
153
154 switch (addr) {
155 case kph0L :
156 IWM_Set_Lines(kph0, Off);
157 break;
158 case kph0H :
159 IWM_Set_Lines(kph0, On);
160 break;
161 case kph1L :
162 IWM_Set_Lines(kph1, Off);
163 break;
164 case kph1H :
165 IWM_Set_Lines(kph1, On);
166 break;
167 case kph2L :
168 IWM_Set_Lines(kph2, Off);
169 break;
170 case kph2H :
171 IWM_Set_Lines(kph2, On);
172 break;
173 case kph3L :
174 IWM_Set_Lines(kph3, Off);
175 break;
176 case kph3H :
177 IWM_Set_Lines(kph3, On);
178 break;
179 case kmtrOff :
180 IWM.Status &= 0xDF;
181 IWM_Set_Lines(kmtr, Off);
182 break;
183 case kmtrOn :
184 IWM.Status |= 0x20;
185 IWM_Set_Lines(kmtr, On);
186 break;
187 case kintDrive :
188 IWM_Set_Lines(kdrv, Off);
189 break;
190 case kextDrive :
191 IWM_Set_Lines(kdrv, On);
192 break;
193 case kq6L :
194 IWM_Set_Lines(kq6, Off);
195 break;
196 case kq6H :
197 IWM_Set_Lines(kq6, On);
198 break;
199 case kq7L :
200 if (! WriteMem) {
201 Data = IWM_Read_Reg();
202 }
203 IWM_Set_Lines(kq7, Off);
204 break;
205 case kq7H :
206 if (WriteMem) {
207 IWM_Write_Reg(Data);
208 }
209 IWM_Set_Lines(kq7, On);
210 break;
211 }
212
213 return Data;
214}