Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* nova_dkp.c: NOVA moving head disk simulator\r |
2 | \r | |
3 | Copyright (c) 1993-2008, Robert M. Supnik\r | |
4 | \r | |
5 | Permission is hereby granted, free of charge, to any person obtaining a\r | |
6 | copy of this software and associated documentation files (the "Software"),\r | |
7 | to deal in the Software without restriction, including without limitation\r | |
8 | the rights to use, copy, modify, merge, publish, distribute, sublicense,\r | |
9 | and/or sell copies of the Software, and to permit persons to whom the\r | |
10 | Software is furnished to do so, subject to the following conditions:\r | |
11 | \r | |
12 | The above copyright notice and this permission notice shall be included in\r | |
13 | all copies or substantial portions of the Software.\r | |
14 | \r | |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r | |
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r | |
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r | |
18 | ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r | |
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r | |
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r | |
21 | \r | |
22 | Except as contained in this notice, the name of Robert M Supnik shall not be\r | |
23 | used in advertising or otherwise to promote the sale, use or other dealings\r | |
24 | in this Software without prior written authorization from Robert M Supnik.\r | |
25 | \r | |
26 | dkp moving head disk\r | |
27 | \r | |
28 | 04-Jul-04 BKR device name changed to DG's DKP from DEC's DP,\r | |
29 | DEV_SET/CLR/INTR macro use started,\r | |
30 | fixed 'P' pulse code and secret quirks,\r | |
31 | added 6097 diag and size support,\r | |
32 | fixed losing unit drive type during unit change,\r | |
33 | tightened sector size determination calculations,\r | |
34 | controller DONE flag handling fixed,\r | |
35 | fixed cylinder overflow test error,\r | |
36 | seek error code fixed,\r | |
37 | restructured dkp_go() and dkp_svc() routines\r | |
38 | (for known future fixes needed),\r | |
39 | fixed DIA status calculation,\r | |
40 | fixed DKP read/write loop to properly emulate DG cylinder and sector overflows,\r | |
41 | added trace facility,\r | |
42 | changed 'stime' calculation to force delay time if no cylinders are crossed\r | |
43 | (this fixes some DG code that assumes disk seek takes some time),\r | |
44 | fixed boot code to match DG hardware standard\r | |
45 | 04-Jan-04 RMS Changed attach routine to use sim_fsize\r | |
46 | 28-Nov-03 CEO Boot from DP now puts device address in SR\r | |
47 | 24-Nov-03 CEO Added support for disk sizing on 6099/6103\r | |
48 | 19-Nov-03 CEO Corrected major DMA Mapping bug\r | |
49 | 25-Apr-03 RMS Revised autosizing\r | |
50 | 08-Oct-02 RMS Added DIB\r | |
51 | 06-Jan-02 RMS Revised enable/disable support\r | |
52 | 30-Nov-01 RMS Added read only unit, extended SET/SHOW support\r | |
53 | 24-Nov-01 RMS Changed FLG, CAPAC to arrays\r | |
54 | 26-Apr-01 RMS Added device enable/disable support\r | |
55 | 12-Dec-00 RMS Added Eclipse support from Charles Owen\r | |
56 | 15-Oct-00 RMS Editorial changes\r | |
57 | 14-Apr-99 RMS Changed t_addr to unsigned\r | |
58 | 15-Sep-97 RMS Fixed bug in DIB/DOB for new disks\r | |
59 | 15-Sep-97 RMS Fixed bug in cylinder extraction (found by Charles Owen)\r | |
60 | 10-Sep-97 RMS Fixed bug in error reporting (found by Charles Owen)\r | |
61 | 25-Nov-96 RMS Defaulted to autosize\r | |
62 | 29-Jun-96 RMS Added unit disable support\r | |
63 | */\r | |
64 | \r | |
65 | #include "nova_defs.h"\r | |
66 | \r | |
67 | #define DKP_NUMDR 4 /* #drives */\r | |
68 | #define DKP_NUMWD 256 /* words/sector */\r | |
69 | #define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */\r | |
70 | #define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */\r | |
71 | #define UNIT_M_DTYPE 017\r | |
72 | #define UNIT_V_AUTO (UNIT_V_UF + 5) /* autosize */\r | |
73 | #define UNIT_WLK (1 << UNIT_V_WLK)\r | |
74 | #define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)\r | |
75 | #define UNIT_AUTO (1 << UNIT_V_AUTO)\r | |
76 | #define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)\r | |
77 | #define FUNC u3 /* function */\r | |
78 | #define CYL u4 /* on cylinder */\r | |
79 | #define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */\r | |
80 | \r | |
81 | /* Unit, surface, sector, count register\r | |
82 | \r | |
83 | Original format: 2b, 6b, 4b, 4b\r | |
84 | Revised format: 2b, 5b, 5b, 4b\r | |
85 | */\r | |
86 | \r | |
87 | #define USSC_V_COUNT 0 /* count */\r | |
88 | #define USSC_M_COUNT 017\r | |
89 | #define USSC_V_OSECTOR 4 /* old: sector */\r | |
90 | #define USSC_M_OSECTOR 017\r | |
91 | #define USSC_V_OSURFACE 8 /* old: surface */\r | |
92 | #define USSC_M_OSURFACE 077\r | |
93 | #define USSC_V_NSECTOR 4 /* new: sector */\r | |
94 | #define USSC_M_NSECTOR 037\r | |
95 | #define USSC_V_NSURFACE 9 /* new: surface */\r | |
96 | #define USSC_M_NSURFACE 037\r | |
97 | #define USSC_V_UNIT 14 /* unit */\r | |
98 | #define USSC_M_UNIT 03\r | |
99 | #define USSC_UNIT (USSC_M_UNIT << USSC_V_UNIT)\r | |
100 | #define GET_COUNT(x) (((x) >> USSC_V_COUNT) & USSC_M_COUNT)\r | |
101 | #define GET_SECT(x,dt) ((drv_tab[dt].newf)? \\r | |
102 | (((x) >> USSC_V_NSECTOR) & USSC_M_NSECTOR): \\r | |
103 | (((x) >> USSC_V_OSECTOR) & USSC_M_OSECTOR) )\r | |
104 | #define GET_SURF(x,dt) ((drv_tab[dt].newf)? \\r | |
105 | (((x) >> USSC_V_NSURFACE) & USSC_M_NSURFACE): \\r | |
106 | (((x) >> USSC_V_OSURFACE) & USSC_M_OSURFACE) )\r | |
107 | #define GET_UNIT(x) (((x) >> USSC_V_UNIT) & USSC_M_UNIT)\r | |
108 | \r | |
109 | /* Flags, command, cylinder register\r | |
110 | \r | |
111 | Original format: 5b, 2b, 1b + 8b (surrounding command)\r | |
112 | Revised format: 5b, 2b, 9b\r | |
113 | */\r | |
114 | \r | |
115 | #define FCCY_V_OCYL 0 /* old: cylinder */\r | |
116 | #define FCCY_M_OCYL 0377\r | |
117 | #define FCCY_V_OCMD 8 /* old: command */\r | |
118 | #define FCCY_M_OCMD 3\r | |
119 | #define FCCY_V_OCEX 10 /* old: cyl extend */\r | |
120 | #define FCCY_OCEX (1 << FCCY_V_OCEX)\r | |
121 | #define FCCY_V_NCYL 0 /* new: cylinder */\r | |
122 | #define FCCY_M_NCYL 0777\r | |
123 | #define FCCY_V_NCMD 9 /* new: command */\r | |
124 | #define FCCY_M_NCMD 3\r | |
125 | #define FCCY_READ 0\r | |
126 | #define FCCY_WRITE 1\r | |
127 | #define FCCY_SEEK 2\r | |
128 | #define FCCY_RECAL 3\r | |
129 | #define FCCY_FLAGS 0174000 /* flags */\r | |
130 | \r | |
131 | #define GET_CMD(x,dt) ((drv_tab[dt].newf)? \\r | |
132 | (((x) >> FCCY_V_NCMD) & FCCY_M_NCMD): \\r | |
133 | (((x) >> FCCY_V_OCMD) & FCCY_M_OCMD) )\r | |
134 | \r | |
135 | #define SET_CMD(x,dt) dkp_fccy = (dkp_fccy & ((drv_tab[dt].newf)? \\r | |
136 | (FCCY_M_NCMD << FCCY_V_NCMD) : (FCCY_M_OCMD << FCCY_V_OCMD))) | \\r | |
137 | ((drv_tab[dt].newf)? \\r | |
138 | (((x) & FCCY_M_NCMD) << FCCY_V_NCMD): \\r | |
139 | (((x) & FCCY_M_OCMD) << FCCY_V_OCMD) )\r | |
140 | \r | |
141 | #define GET_CYL(x,dt) ((drv_tab[dt].newf)? \\r | |
142 | (((x) >> FCCY_V_NCYL) & FCCY_M_NCYL): \\r | |
143 | ((((x) >> FCCY_V_OCYL) & FCCY_M_OCYL) | \\r | |
144 | ((dt != TYPE_D44)? 0: \\r | |
145 | (((x) & FCCY_OCEX) >> (FCCY_V_OCEX - FCCY_V_OCMD)))) )\r | |
146 | \r | |
147 | \r | |
148 | /* (Warning: no sector or surface masking is done!) */\r | |
149 | \r | |
150 | #define DKP_UPDATE_USSC( type, count, surf, sect ) \\r | |
151 | dkp_ussc = (dkp_ussc & USSC_UNIT) \\r | |
152 | | ((dkp_ussc + count) & USSC_M_COUNT) \\r | |
153 | | ((drv_tab[dtype].newf)? \\r | |
154 | ((surf << USSC_V_NSURFACE) | (sect << USSC_V_NSECTOR)): \\r | |
155 | ((surf << USSC_V_OSURFACE) | (sect << USSC_V_OSECTOR)) \\r | |
156 | );\r | |
157 | \r | |
158 | \r | |
159 | /* Status */\r | |
160 | \r | |
161 | #define STA_ERR 0000001 /* error */\r | |
162 | #define STA_DLT 0000002 /* data late */\r | |
163 | #define STA_CRC 0000004 /* crc error */\r | |
164 | #define STA_UNS 0000010 /* unsafe */\r | |
165 | #define STA_XCY 0000020 /* cross cylinder */\r | |
166 | #define STA_CYL 0000040 /* nx cylinder */\r | |
167 | #define STA_DRDY 0000100 /* drive ready */\r | |
168 | #define STA_SEEK3 0000200 /* seeking unit 3 */\r | |
169 | #define STA_SEEK2 0000400 /* seeking unit 2 */\r | |
170 | #define STA_SEEK1 0001000 /* seeking unit 1 */\r | |
171 | #define STA_SEEK0 0002000 /* seeking unit 0 */\r | |
172 | #define STA_SKDN3 0004000 /* seek done unit 3 */\r | |
173 | #define STA_SKDN2 0010000 /* seek done unit 2 */\r | |
174 | #define STA_SKDN1 0020000 /* seek done unit 1 */\r | |
175 | #define STA_SKDN0 0040000 /* seek done unit 0 */\r | |
176 | #define STA_DONE 0100000 /* operation done */\r | |
177 | \r | |
178 | #define STA_DYN (STA_DRDY | STA_CYL) /* set from unit */\r | |
179 | #define STA_EFLGS (STA_ERR | STA_DLT | STA_CRC | STA_UNS | \\r | |
180 | STA_XCY | STA_CYL) /* error flags */\r | |
181 | #define STA_DFLGS (STA_DONE | STA_SKDN0 | STA_SKDN1 | \\r | |
182 | STA_SKDN2 | STA_SKDN3) /* done flags */\r | |
183 | \r | |
184 | #define GET_SA(cy,sf,sc,t) (((((cy)*drv_tab[t].surf)+(sf))* \\r | |
185 | drv_tab[t].sect)+(sc))\r | |
186 | \r | |
187 | /* This controller supports many different disk drive types:\r | |
188 | \r | |
189 | type #sectors/ #surfaces/ #cylinders/ new format?\r | |
190 | surface cylinder drive\r | |
191 | \r | |
192 | floppy 8 1 77 no\r | |
193 | DS/DD floppy 16 2 77 yes\r | |
194 | (6097 "quad floppy")\r | |
195 | Diablo 31 12 2 203 no\r | |
196 | 6225 20 2 245 yes\r | |
197 | Century 111 6 10 203 no\r | |
198 | 4048 (same as Century 111)\r | |
199 | Diablo 44 12 4 408 no\r | |
200 | 6099 32 4 192 yes\r | |
201 | 6227 20 6 245 yes\r | |
202 | 6070 24 4 408 yes \r | |
203 | Century 114 12 20 203 no\r | |
204 | 4057 (same as Century 114)\r | |
205 | 6103 32 8 192 yes\r | |
206 | 4231 23 19 411 yes\r | |
207 | \r | |
208 | In theory, each drive can be a different type. The size field in\r | |
209 | each unit selects the drive capacity for each drive and thus the\r | |
210 | drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE.\r | |
211 | */\r | |
212 | \r | |
213 | #define TYPE_FLP 0\r | |
214 | #define SECT_FLP 8\r | |
215 | #define SURF_FLP 1\r | |
216 | #define CYL_FLP 77\r | |
217 | #define SIZE_FLP (SECT_FLP * SURF_FLP * CYL_FLP * DKP_NUMWD)\r | |
218 | #define NFMT_FLP FALSE\r | |
219 | \r | |
220 | #define TYPE_DSDD 1\r | |
221 | #define TYPE_6097 TYPE_DSDD\r | |
222 | #define SECT_DSDD 16\r | |
223 | #define SURF_DSDD 2\r | |
224 | #define CYL_DSDD 77\r | |
225 | #define SIZE_DSDD (SECT_DSDD * SURF_DSDD * CYL_DSDD * DKP_NUMWD)\r | |
226 | #define NFMT_DSDD TRUE\r | |
227 | \r | |
228 | #define TYPE_D31 2\r | |
229 | #define SECT_D31 12\r | |
230 | #define SURF_D31 2\r | |
231 | #define CYL_D31 203\r | |
232 | #define SIZE_D31 (SECT_D31 * SURF_D31 * CYL_D31 * DKP_NUMWD)\r | |
233 | #define NFMT_D31 FALSE\r | |
234 | \r | |
235 | #define TYPE_6225 3\r | |
236 | #define SECT_6225 20\r | |
237 | #define SURF_6225 2\r | |
238 | #define CYL_6225 245\r | |
239 | #define SIZE_6225 (SECT_6225 * SURF_6225 * CYL_6225 * DKP_NUMWD)\r | |
240 | #define NFMT_6225 TRUE\r | |
241 | \r | |
242 | #define TYPE_C111 4\r | |
243 | #define SECT_C111 6\r | |
244 | #define SURF_C111 10\r | |
245 | #define CYL_C111 203\r | |
246 | #define SIZE_C111 (SECT_C111 * SURF_C111 * CYL_C111 * DKP_NUMWD)\r | |
247 | #define NFMT_C111 FALSE\r | |
248 | \r | |
249 | #define TYPE_D44 5\r | |
250 | #define SECT_D44 12\r | |
251 | #define SURF_D44 4\r | |
252 | #define CYL_D44 408\r | |
253 | #define SIZE_D44 (SECT_D44 * SURF_D44 * CYL_D44 * DKP_NUMWD)\r | |
254 | #define NFMT_D44 FALSE\r | |
255 | \r | |
256 | #define TYPE_6099 6\r | |
257 | #define SECT_6099 32\r | |
258 | #define SURF_6099 4\r | |
259 | #define CYL_6099 192\r | |
260 | #define SIZE_6099 (SECT_6099 * SURF_6099 * CYL_6099 * DKP_NUMWD)\r | |
261 | #define NFMT_6099 TRUE \r | |
262 | \r | |
263 | #define TYPE_6227 7\r | |
264 | #define SECT_6227 20\r | |
265 | #define SURF_6227 6\r | |
266 | #define CYL_6227 245\r | |
267 | #define SIZE_6227 (SECT_6227 * SURF_6227 * CYL_6227 * DKP_NUMWD)\r | |
268 | #define NFMT_6227 TRUE\r | |
269 | \r | |
270 | #define TYPE_6070 8\r | |
271 | #define SECT_6070 24\r | |
272 | #define SURF_6070 4\r | |
273 | #define CYL_6070 408\r | |
274 | #define SIZE_6070 (SECT_6070 * SURF_6070 * CYL_6070 * DKP_NUMWD)\r | |
275 | #define NFMT_6070 TRUE\r | |
276 | \r | |
277 | #define TYPE_C114 9\r | |
278 | #define SECT_C114 12\r | |
279 | #define SURF_C114 20\r | |
280 | #define CYL_C114 203\r | |
281 | #define SIZE_C114 (SECT_C114 * SURF_C114 * CYL_C114 * DKP_NUMWD)\r | |
282 | #define NFMT_C114 FALSE\r | |
283 | \r | |
284 | #define TYPE_6103 10\r | |
285 | #define SECT_6103 32\r | |
286 | #define SURF_6103 8\r | |
287 | #define CYL_6103 192\r | |
288 | #define SIZE_6103 (SECT_6103 * SURF_6103 * CYL_6103 * DKP_NUMWD)\r | |
289 | #define NFMT_6103 TRUE\r | |
290 | \r | |
291 | #define TYPE_4231 11\r | |
292 | #define SECT_4231 23\r | |
293 | #define SURF_4231 19\r | |
294 | #define CYL_4231 411\r | |
295 | #define SIZE_4231 (SECT_4231 * SURF_4231 * CYL_4231 * DKP_NUMWD)\r | |
296 | #define NFMT_4231 TRUE\r | |
297 | \r | |
298 | struct drvtyp {\r | |
299 | int32 sect; /* sectors */\r | |
300 | int32 surf; /* surfaces */\r | |
301 | int32 cyl; /* cylinders */\r | |
302 | int32 size; /* #blocks */\r | |
303 | int32 newf; /* new format flag */\r | |
304 | };\r | |
305 | \r | |
306 | struct drvtyp drv_tab[] = {\r | |
307 | { SECT_FLP, SURF_FLP, CYL_FLP, SIZE_FLP, NFMT_FLP },\r | |
308 | { SECT_DSDD, SURF_DSDD, CYL_DSDD, SIZE_DSDD, NFMT_DSDD },\r | |
309 | { SECT_D31, SURF_D31, CYL_D31, SIZE_D31, NFMT_D31 },\r | |
310 | { SECT_6225, SURF_6225, CYL_6225, SIZE_6225, NFMT_6225 },\r | |
311 | { SECT_C111, SURF_C111, CYL_C111, SIZE_C111, NFMT_C111 },\r | |
312 | { SECT_D44, SURF_D44, CYL_D44, SIZE_D44, NFMT_D44 },\r | |
313 | { SECT_6099, SURF_6099, CYL_6099, SIZE_6099, NFMT_6099 },\r | |
314 | { SECT_6227, SURF_6227, CYL_6227, SIZE_6227, NFMT_6227 },\r | |
315 | { SECT_6070, SURF_6070, CYL_6070, SIZE_6070, NFMT_6070 },\r | |
316 | { SECT_C114, SURF_C114, CYL_C114, SIZE_C114, NFMT_C114 },\r | |
317 | { SECT_6103, SURF_6103, CYL_6103, SIZE_6103, NFMT_6103 },\r | |
318 | { SECT_4231, SURF_4231, CYL_4231, SIZE_4231, NFMT_4231 },\r | |
319 | { 0 }\r | |
320 | };\r | |
321 | \r | |
322 | #define DKP_TRACE(x) (dkp_trace & (1<<(x)))\r | |
323 | #define DKP_TRACE_FP stderr\r | |
324 | /* current trace bit use (bit 0 = LSB)\r | |
325 | 0 I/O instructions\r | |
326 | 1 pre-seek/read/write event setup\r | |
327 | 2 seek events\r | |
328 | 3 read/write events\r | |
329 | 4 post read/write events\r | |
330 | */\r | |
331 | \r | |
332 | extern uint16 M[];\r | |
333 | extern UNIT cpu_unit;\r | |
334 | extern int32 int_req, dev_busy, dev_done, dev_disable;\r | |
335 | extern int32 saved_PC, SR, AMASK;\r | |
336 | \r | |
337 | int32 dkp_ma = 0; /* memory address */\r | |
338 | int32 dkp_map = 0; /* DCH map 0=A 3=B */\r | |
339 | int32 dkp_ussc = 0; /* unit/sf/sc/cnt */\r | |
340 | int32 dkp_fccy = 0; /* flags/cylinder */\r | |
341 | int32 dkp_sta = 0; /* status register */\r | |
342 | int32 dkp_swait = 100; /* seek latency */\r | |
343 | int32 dkp_rwait = 100; /* rotate latency */\r | |
344 | int32 dkp_diagmode = 0; /* diagnostic mode */\r | |
345 | \r | |
346 | int32 dkp_trace = 0 ;\r | |
347 | \r | |
348 | DEVICE dkp_dev;\r | |
349 | int32 dkp (int32 pulse, int32 code, int32 AC);\r | |
350 | t_stat dkp_svc (UNIT *uptr);\r | |
351 | t_stat dkp_reset (DEVICE *dptr);\r | |
352 | t_stat dkp_boot (int32 unitno, DEVICE *dptr);\r | |
353 | t_stat dkp_attach (UNIT *uptr, char *cptr);\r | |
354 | t_stat dkp_go ( int32 pulse );\r | |
355 | t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);\r | |
356 | \r | |
357 | /* DKP data structures\r | |
358 | \r | |
359 | dkp_dev DKP device descriptor\r | |
360 | dkp_unit DKP unit list\r | |
361 | dkp_reg DKP register list\r | |
362 | dkp_mod DKP modifier list\r | |
363 | */\r | |
364 | \r | |
365 | DIB dkp_dib = { DEV_DKP, INT_DKP, PI_DKP, &dkp };\r | |
366 | \r | |
367 | UNIT dkp_unit[] = {\r | |
368 | { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+\r | |
369 | UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) },\r | |
370 | { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+\r | |
371 | UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) },\r | |
372 | { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+\r | |
373 | UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) },\r | |
374 | { UDATA (&dkp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_AUTO+\r | |
375 | UNIT_ROABLE+(TYPE_D31 << UNIT_V_DTYPE), SIZE_D31) }\r | |
376 | };\r | |
377 | \r | |
378 | REG dkp_reg[] = {\r | |
379 | { ORDATA (FCCY, dkp_fccy, 16) },\r | |
380 | { ORDATA (USSC, dkp_ussc, 16) },\r | |
381 | { ORDATA (STA, dkp_sta, 16) },\r | |
382 | { ORDATA (MA, dkp_ma, 16) },\r | |
383 | { FLDATA (INT, int_req, INT_V_DKP) },\r | |
384 | { FLDATA (BUSY, dev_busy, INT_V_DKP) },\r | |
385 | { FLDATA (DONE, dev_done, INT_V_DKP) },\r | |
386 | { FLDATA (DISABLE, dev_disable, INT_V_DKP) },\r | |
387 | { FLDATA (DIAG, dkp_diagmode, 0) },\r | |
388 | { DRDATA (TRACE, dkp_trace, 32) },\r | |
389 | { ORDATA (MAP, dkp_map, 2) },\r | |
390 | { DRDATA (STIME, dkp_swait, 24), PV_LEFT },\r | |
391 | { DRDATA (RTIME, dkp_rwait, 24), PV_LEFT },\r | |
392 | { URDATA (CAPAC, dkp_unit[0].capac, 10, T_ADDR_W, 0,\r | |
393 | DKP_NUMDR, PV_LEFT | REG_HRO) },\r | |
394 | { NULL }\r | |
395 | };\r | |
396 | \r | |
397 | MTAB dkp_mod[] = {\r | |
398 | { UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },\r | |
399 | { UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },\r | |
400 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_FLP << UNIT_V_DTYPE) + UNIT_ATT,\r | |
401 | "6030 (floppy)", NULL, NULL },\r | |
402 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_DSDD << UNIT_V_DTYPE) + UNIT_ATT,\r | |
403 | "6097 (DS/DD floppy)", NULL, NULL },\r | |
404 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_D31 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
405 | "4047 (Diablo 31)", NULL, NULL },\r | |
406 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_D44 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
407 | "4234/6045 (Diablo 44)", NULL, NULL },\r | |
408 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_C111 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
409 | "4048 (Century 111)", NULL, NULL },\r | |
410 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_C114 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
411 | "2314/4057 (Century 114)", NULL, NULL },\r | |
412 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_6225 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
413 | "6225", NULL, NULL },\r | |
414 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_6227 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
415 | "6227", NULL, NULL },\r | |
416 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_6099 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
417 | "6099", NULL, NULL },\r | |
418 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_6103 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
419 | "6103", NULL, NULL },\r | |
420 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_6070 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
421 | "6070", NULL, NULL },\r | |
422 | { (UNIT_DTYPE+UNIT_ATT), (TYPE_4231 << UNIT_V_DTYPE) + UNIT_ATT,\r | |
423 | "4231/3330", NULL, NULL },\r | |
424 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_FLP << UNIT_V_DTYPE),\r | |
425 | "6030 (floppy)", NULL, NULL },\r | |
426 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_DSDD << UNIT_V_DTYPE),\r | |
427 | "6097 (DS/DD floppy)", NULL, NULL },\r | |
428 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_D31 << UNIT_V_DTYPE),\r | |
429 | "4047 (Diablo 31)", NULL, NULL },\r | |
430 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_D44 << UNIT_V_DTYPE),\r | |
431 | "4234/6045 (Diablo 44)", NULL, NULL },\r | |
432 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_C111 << UNIT_V_DTYPE),\r | |
433 | "4048 (Century 111)", NULL, NULL },\r | |
434 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_C114 << UNIT_V_DTYPE),\r | |
435 | "2314/4057 (Century 114)", NULL, NULL },\r | |
436 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6225 << UNIT_V_DTYPE),\r | |
437 | "6225", NULL, NULL },\r | |
438 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6227 << UNIT_V_DTYPE),\r | |
439 | "6227", NULL, NULL },\r | |
440 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6099 << UNIT_V_DTYPE),\r | |
441 | "6099", NULL, NULL },\r | |
442 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6103 << UNIT_V_DTYPE),\r | |
443 | "6103", NULL, NULL },\r | |
444 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_6070 << UNIT_V_DTYPE),\r | |
445 | "6070", NULL, NULL },\r | |
446 | { (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_4231 << UNIT_V_DTYPE),\r | |
447 | "4231/3330", NULL, NULL },\r | |
448 | { (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },\r | |
449 | { UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL },\r | |
450 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_FLP << UNIT_V_DTYPE),\r | |
451 | NULL, "FLOPPY", &dkp_set_size },\r | |
452 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_FLP << UNIT_V_DTYPE),\r | |
453 | NULL, "6030", &dkp_set_size },\r | |
454 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_DSDD << UNIT_V_DTYPE),\r | |
455 | NULL, "DSDDFLOPPY", &dkp_set_size },\r | |
456 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_DSDD << UNIT_V_DTYPE),\r | |
457 | NULL, "6097", &dkp_set_size },\r | |
458 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D31 << UNIT_V_DTYPE),\r | |
459 | NULL, "D31", &dkp_set_size }, \r | |
460 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D31 << UNIT_V_DTYPE),\r | |
461 | NULL, "4047", &dkp_set_size }, \r | |
462 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D44 << UNIT_V_DTYPE),\r | |
463 | NULL, "D44", &dkp_set_size },\r | |
464 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D44 << UNIT_V_DTYPE),\r | |
465 | NULL, "4234", &dkp_set_size },\r | |
466 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_D44 << UNIT_V_DTYPE),\r | |
467 | NULL, "6045", &dkp_set_size },\r | |
468 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C111 << UNIT_V_DTYPE),\r | |
469 | NULL, "C111", &dkp_set_size },\r | |
470 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C111 << UNIT_V_DTYPE),\r | |
471 | NULL, "4048", &dkp_set_size },\r | |
472 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C114 << UNIT_V_DTYPE),\r | |
473 | NULL, "C114", &dkp_set_size },\r | |
474 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C114 << UNIT_V_DTYPE),\r | |
475 | NULL, "2314", &dkp_set_size },\r | |
476 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_C114 << UNIT_V_DTYPE),\r | |
477 | NULL, "4057", &dkp_set_size },\r | |
478 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6225 << UNIT_V_DTYPE),\r | |
479 | NULL, "6225", &dkp_set_size },\r | |
480 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6227 << UNIT_V_DTYPE),\r | |
481 | NULL, "6227", &dkp_set_size },\r | |
482 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6099 << UNIT_V_DTYPE),\r | |
483 | NULL, "6099", &dkp_set_size },\r | |
484 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6103 << UNIT_V_DTYPE),\r | |
485 | NULL, "6103", &dkp_set_size },\r | |
486 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_6070 << UNIT_V_DTYPE),\r | |
487 | NULL, "6070", &dkp_set_size },\r | |
488 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_4231 << UNIT_V_DTYPE),\r | |
489 | NULL, "4231", &dkp_set_size },\r | |
490 | { (UNIT_AUTO+UNIT_DTYPE), (TYPE_4231 << UNIT_V_DTYPE),\r | |
491 | NULL, "3330", &dkp_set_size },\r | |
492 | { 0 }\r | |
493 | };\r | |
494 | \r | |
495 | DEVICE dkp_dev = {\r | |
496 | "DKP", dkp_unit, dkp_reg, dkp_mod,\r | |
497 | DKP_NUMDR, 8, 30, 1, 8, 16,\r | |
498 | NULL, NULL, &dkp_reset,\r | |
499 | &dkp_boot, &dkp_attach, NULL,\r | |
500 | &dkp_dib, DEV_DISABLE\r | |
501 | };\r | |
502 | \r | |
503 | \r | |
504 | /* IOT routine */\r | |
505 | \r | |
506 | int32 dkp (int32 pulse, int32 code, int32 AC)\r | |
507 | {\r | |
508 | UNIT *uptr;\r | |
509 | int32 u, rval, dtype;\r | |
510 | \r | |
511 | rval = 0;\r | |
512 | uptr = dkp_dev.units + GET_UNIT (dkp_ussc); /* select unit */\r | |
513 | dtype = GET_DTYPE (uptr->flags); /* get drive type */\r | |
514 | \r | |
515 | if ( DKP_TRACE(0) )\r | |
516 | {\r | |
517 | static char * f[8] =\r | |
518 | { "NIO", "DIA", "DOA", "DIB", "DOB", "DIC", "DOC", "SKP" } ;\r | |
519 | static char * s[4] =\r | |
520 | { " ", "S", "C", "P" } ;\r | |
521 | \r | |
522 | printf( " [DKP %s%s %06o ", f[code & 0x07], s[pulse & 0x03], (AC & 0xFFFF) ) ;\r | |
523 | }\r | |
524 | \r | |
525 | switch (code) { /* decode IR<5:7> */\r | |
526 | \r | |
527 | case ioDIA: /* DIA */\r | |
528 | dkp_sta = dkp_sta & (~STA_DRDY) ; /* keep error flags */\r | |
529 | if (uptr->flags & UNIT_ATT) /* update ready */\r | |
530 | dkp_sta = dkp_sta | STA_DRDY;\r | |
531 | if (uptr->CYL >= drv_tab[dtype].cyl)\r | |
532 | dkp_sta = dkp_sta | STA_CYL; /* bad cylinder? */\r | |
533 | if (dkp_sta & STA_EFLGS)\r | |
534 | dkp_sta = dkp_sta | STA_ERR;\r | |
535 | rval = dkp_sta;\r | |
536 | break;\r | |
537 | \r | |
538 | case ioDOA: /* DOA */\r | |
539 | if (AC & 0100000) /* clear rw done? */\r | |
540 | dkp_sta = dkp_sta & ~(STA_CYL|STA_XCY|STA_UNS|STA_CRC);\r | |
541 | if ((dev_busy & INT_DKP) == 0) {\r | |
542 | dkp_fccy = AC; /* save cmd, cyl */\r | |
543 | dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS);\r | |
544 | }\r | |
545 | DEV_CLR_DONE( INT_DKP ) ; /* assume done flags 0 */\r | |
546 | if ( dkp_sta & STA_DFLGS ) /* done flags = 0? */\r | |
547 | DEV_SET_DONE( INT_DKP ) ; /* nope - set done */\r | |
548 | DEV_UPDATE_INTR ; /* update intr */\r | |
549 | break;\r | |
550 | \r | |
551 | case ioDIB: /* DIB */\r | |
552 | rval = dkp_ma & 077777 ; /* return buf addr */\r | |
553 | /* with B0 clear (no DCH B map support) */\r | |
554 | break;\r | |
555 | \r | |
556 | case ioDOB: /* DOB */\r | |
557 | if ((dev_busy & INT_DKP) == 0) {\r | |
558 | dkp_ma = AC & (drv_tab[dtype].newf? DMASK: AMASK);\r | |
559 | if (AC & 0100000)\r | |
560 | dkp_map = 3; /* high bit is map */\r | |
561 | else\r | |
562 | dkp_map = 0;\r | |
563 | }\r | |
564 | break;\r | |
565 | \r | |
566 | case ioDIC: /* DIC */\r | |
567 | rval = dkp_ussc; /* return unit, sect */\r | |
568 | break;\r | |
569 | \r | |
570 | case ioDOC: /* DOC */\r | |
571 | if ((dev_busy & INT_DKP) == 0) /* if device is not busy */\r | |
572 | dkp_ussc = AC ; /* save unit, sect */\r | |
573 | if (((dtype == TYPE_6099) || /* (BKR: don't forget 6097) */\r | |
574 | (dtype == TYPE_6097) || /* for 6099 and 6103 */\r | |
575 | (dtype == TYPE_6103)) && /* if data<0> set, */\r | |
576 | (AC & 010000) )\r | |
577 | dkp_diagmode = 1; /* set diagnostic mode */\r | |
578 | break;\r | |
579 | } /* end switch code */\r | |
580 | \r | |
581 | u = GET_UNIT(dkp_ussc); /* update current unit */\r | |
582 | uptr = dkp_dev.units + u ; /* select unit */\r | |
583 | dtype = GET_DTYPE (uptr->flags); /* get drive type */\r | |
584 | \r | |
585 | if ( DKP_TRACE(0) )\r | |
586 | {\r | |
587 | if ( code & 1 )\r | |
588 | printf( " [%06o] ", (rval & 0xFFFF) ) ;\r | |
589 | printf( "] \n" ) ;\r | |
590 | }\r | |
591 | \r | |
592 | switch (pulse) { /* decode IR<8:9> */\r | |
593 | \r | |
594 | case iopS: /* start */\r | |
595 | DEV_SET_BUSY( INT_DKP ) ; /* set busy */\r | |
596 | DEV_CLR_DONE( INT_DKP ) ; /* clear done */\r | |
597 | DEV_UPDATE_INTR ; /* update ints */\r | |
598 | if (dkp_diagmode) { /* in diagnostic mode? */\r | |
599 | dkp_diagmode = 0; /* reset it */\r | |
600 | if (dtype == TYPE_6097) dkp_ussc = 010001; /* (BKR - quad floppy) */\r | |
601 | if (dtype == TYPE_6099) dkp_ussc = 010002; /* return size bits */\r | |
602 | if (dtype == TYPE_6103) dkp_ussc = 010003; /* for certain types */\r | |
603 | } \r | |
604 | else { /* normal mode ... */\r | |
605 | if (dkp_go (pulse)) /* do command */\r | |
606 | break ; /* break if no error */\r | |
607 | }\r | |
608 | DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */\r | |
609 | DEV_SET_DONE( INT_DKP ) ; /* set done */\r | |
610 | DEV_UPDATE_INTR ; /* update ints */\r | |
611 | dkp_sta = dkp_sta | STA_DONE; /* set controller done */\r | |
612 | break;\r | |
613 | \r | |
614 | case iopC: /* clear */\r | |
615 | DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */\r | |
616 | DEV_CLR_DONE( INT_DKP ) ; /* set done */\r | |
617 | DEV_UPDATE_INTR ; /* update ints */\r | |
618 | dkp_sta = dkp_sta & ~(STA_DFLGS + STA_EFLGS); /* clear controller flags */\r | |
619 | if (dkp_unit[u].FUNC != FCCY_SEEK)\r | |
620 | sim_cancel (&dkp_unit[u]); /* cancel any r/w op */\r | |
621 | break;\r | |
622 | \r | |
623 | case iopP: /* pulse */\r | |
624 | if ( dkp_diagmode )\r | |
625 | {\r | |
626 | dkp_diagmode = 0 ; /* clear DG diagnostic mode */\r | |
627 | }\r | |
628 | else\r | |
629 | {\r | |
630 | DEV_CLR_DONE( INT_DKP ) ; /* clear done */\r | |
631 | DEV_UPDATE_INTR ;\r | |
632 | \r | |
633 | /* DG "undocumented feature": 'P' pulse can not start a read/write operation!\r | |
634 | * Diagnostic routines will use this crock to do 'crazy things' to size a disk\r | |
635 | * and many assume that a recal is done, other assume that they can stop the\r | |
636 | * read operation before any damage is done. Must also [re]calculate unit, function\r | |
637 | * and type because DOx instruction may have updated the controller info after\r | |
638 | * start of this procedure and before our 'P' handler. BKR\r | |
639 | */\r | |
640 | if (dkp_go(pulse))\r | |
641 | break; /* no error - do not set done and status */\r | |
642 | }\r | |
643 | \r | |
644 | DEV_SET_DONE( INT_DKP ) ; /* set done */\r | |
645 | DEV_UPDATE_INTR ; /* update ints */\r | |
646 | dkp_sta = dkp_sta | (STA_SKDN0 >> u); /* set controller seek done */\r | |
647 | break;\r | |
648 | } /* end case pulse */\r | |
649 | \r | |
650 | return rval;\r | |
651 | }\r | |
652 | \r | |
653 | \r | |
654 | /* New command, start vs pulse handled externally\r | |
655 | Returns true if command ok, false if error\r | |
656 | */\r | |
657 | \r | |
658 | t_stat dkp_go ( int32 pulse )\r | |
659 | {\r | |
660 | UNIT * uptr;\r | |
661 | int32 oldCyl, u, dtype;\r | |
662 | \r | |
663 | dkp_sta = dkp_sta & ~STA_EFLGS; /* clear errors */\r | |
664 | u = GET_UNIT (dkp_ussc); /* get unit number */\r | |
665 | uptr = dkp_dev.units + u; /* get unit */\r | |
666 | if (((uptr->flags & UNIT_ATT) == 0) || sim_is_active (uptr)) {\r | |
667 | dkp_sta = dkp_sta | STA_ERR; /* attached or busy? */\r | |
668 | return FALSE;\r | |
669 | }\r | |
670 | \r | |
671 | if (dkp_diagmode) { /* diagnostic mode? */\r | |
672 | dkp_sta = (dkp_sta | STA_DONE); /* Set error bit only */\r | |
673 | DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */\r | |
674 | DEV_SET_DONE( INT_DKP ) ; /* set done */\r | |
675 | DEV_UPDATE_INTR ; /* update interrupts */\r | |
676 | return ( TRUE ) ; /* do not do function */\r | |
677 | }\r | |
678 | \r | |
679 | oldCyl = uptr->CYL ; /* get old cylinder */\r | |
680 | dtype = GET_DTYPE (uptr->flags); /* get drive type */\r | |
681 | uptr->FUNC = GET_CMD (dkp_fccy, dtype) ; /* save command */\r | |
682 | uptr->CYL = GET_CYL (dkp_fccy, dtype) ;\r | |
683 | \r | |
684 | if ( DKP_TRACE(1) )\r | |
685 | {\r | |
686 | int32 xSect ;\r | |
687 | int32 xSurf ;\r | |
688 | int32 xCyl ;\r | |
689 | int32 xCnt ;\r | |
690 | \r | |
691 | xSect = GET_SECT(dkp_ussc, dtype) ;\r | |
692 | xSurf = GET_SURF(dkp_ussc, dtype) ;\r | |
693 | xCyl = GET_CYL (dkp_fccy, dtype) ;\r | |
694 | xCnt = 16 - (GET_COUNT(dkp_ussc)) ;\r | |
695 | \r | |
696 | fprintf( DKP_TRACE_FP,\r | |
697 | " [%s:%c %-5s: %3d / %2d / %2d %2d %06o ] \r\n",\r | |
698 | "DKP",\r | |
699 | (char) (u + '0'),\r | |
700 | ((uptr->FUNC == FCCY_READ) ?\r | |
701 | "read"\r | |
702 | : ((uptr->FUNC == FCCY_WRITE) ?\r | |
703 | "write"\r | |
704 | : ((uptr->FUNC == FCCY_SEEK) ?\r | |
705 | "seek"\r | |
706 | : "<???>"\r | |
707 | )\r | |
708 | )\r | |
709 | ),\r | |
710 | (unsigned) xCyl,\r | |
711 | (unsigned) xSurf,\r | |
712 | (unsigned) xSect,\r | |
713 | (unsigned) (16 - xCnt),\r | |
714 | (unsigned) (dkp_ma & 0xFFFF) /* show all 16-bits in case DCH B */\r | |
715 | ) ;\r | |
716 | }\r | |
717 | \r | |
718 | \r | |
719 | switch (uptr->FUNC) { /* decode command */\r | |
720 | \r | |
721 | case FCCY_READ:\r | |
722 | case FCCY_WRITE:\r | |
723 | if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */\r | |
724 | ((uptr->flags & UNIT_WPRT) && (uptr->FUNC == FCCY_WRITE)))\r | |
725 | {\r | |
726 | dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */\r | |
727 | }\r | |
728 | else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder */\r | |
729 | {\r | |
730 | dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_CYL ;\r | |
731 | }\r | |
732 | else if ( GET_SURF(dkp_ussc, dtype) >= drv_tab[dtype].surf ) /* bad surface */\r | |
733 | {\r | |
734 | dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /* older drives may not even do this... */\r | |
735 | /* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /- newer disks give this error */\r | |
736 | }\r | |
737 | else if ( GET_SECT(dkp_ussc, dtype) >= drv_tab[dtype].sect ) /* or bad sector? */\r | |
738 | {\r | |
739 | /* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /- older drives may not even do this... */\r | |
740 | dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /* newer disks give this error */\r | |
741 | }\r | |
742 | if ( (pulse != iopS) || (dkp_sta & STA_ERR) )\r | |
743 | {\r | |
744 | return ( FALSE ) ;\r | |
745 | }\r | |
746 | sim_activate (uptr, dkp_rwait); /* schedule read or write request */\r | |
747 | break;\r | |
748 | \r | |
749 | case FCCY_RECAL: /* recalibrate */\r | |
750 | uptr->FUNC = FCCY_SEEK ; /* save command */\r | |
751 | uptr->CYL = 0 ;\r | |
752 | \r | |
753 | case FCCY_SEEK: /* seek */\r | |
754 | if ( ! (uptr->flags & UNIT_ATT) ) /* not attached? */\r | |
755 | {\r | |
756 | dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */\r | |
757 | }\r | |
758 | else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder? */\r | |
759 | {\r | |
760 | dkp_sta = dkp_sta | STA_ERR | STA_CYL;\r | |
761 | }\r | |
762 | if ( (pulse != iopP) || (dkp_sta & STA_ERR) )\r | |
763 | {\r | |
764 | return ( FALSE ) ; /* only 'P' pulse start seeks! */\r | |
765 | }\r | |
766 | \r | |
767 | /* do the seek */\r | |
768 | /* must check for "do we support seeking bits" flag before setting SEEK0'ish bits! */\r | |
769 | dkp_sta = dkp_sta | (STA_SEEK0 >> u); /* set seeking */\r | |
770 | oldCyl = abs(oldCyl - uptr->CYL) ;\r | |
771 | if ( (dkp_swait) && (! (oldCyl)) ) /* enforce minimum wait if req */\r | |
772 | oldCyl = 1 ;\r | |
773 | sim_activate ( uptr, (dkp_swait * oldCyl) ) ;\r | |
774 | break;\r | |
775 | } /* end case command */\r | |
776 | \r | |
777 | return ( TRUE ) ; /* no error */\r | |
778 | }\r | |
779 | \r | |
780 | \r | |
781 | /* Unit service\r | |
782 | \r | |
783 | If seek done, put on cylinder;\r | |
784 | else, do read or write\r | |
785 | If controller was busy, clear busy, set done, interrupt\r | |
786 | \r | |
787 | Memory access: sectors are read into/written from an intermediate\r | |
788 | buffer to allow word-by-word mapping of memory addresses on the\r | |
789 | Eclipse. This allows each word written to memory to be tested\r | |
790 | for out of range.\r | |
791 | */\r | |
792 | \r | |
793 | t_stat dkp_svc (UNIT *uptr)\r | |
794 | {\r | |
795 | int32 sa, bda;\r | |
796 | int32 dx, pa, u;\r | |
797 | int32 dtype, err, newsect, newsurf;\r | |
798 | uint32 awc;\r | |
799 | t_stat rval;\r | |
800 | static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */\r | |
801 | \r | |
802 | \r | |
803 | rval = SCPE_OK;\r | |
804 | dtype = GET_DTYPE (uptr->flags); /* get drive type */\r | |
805 | u = uptr - dkp_dev.units; /* get unit number */\r | |
806 | \r | |
807 | if (uptr->FUNC == FCCY_SEEK) { /* seek? */\r | |
808 | if ( ! (uptr->flags & UNIT_ATT) ) /* not attached? */\r | |
809 | {\r | |
810 | dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error (changed during queue time?) */\r | |
811 | }\r | |
812 | else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder? */\r | |
813 | {\r | |
814 | dkp_sta = dkp_sta | STA_ERR | STA_CYL;\r | |
815 | }\r | |
816 | DEV_SET_DONE( INT_DKP ) ;\r | |
817 | DEV_UPDATE_INTR ;\r | |
818 | dkp_sta = (dkp_sta | (STA_SKDN0 >> u)) /* set seek done */\r | |
819 | & ~(STA_SEEK0 >> u); /* clear seeking */\r | |
820 | if ( DKP_TRACE(2) )\r | |
821 | {\r | |
822 | fprintf( DKP_TRACE_FP,\r | |
823 | " [%s:%c seek : %4d ] \r\n",\r | |
824 | "DKP",\r | |
825 | (char) (u + '0'),\r | |
826 | (unsigned) (uptr->CYL)\r | |
827 | ) ;\r | |
828 | }\r | |
829 | return SCPE_OK;\r | |
830 | }\r | |
831 | \r | |
832 | /* read or write */\r | |
833 | \r | |
834 | if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */\r | |
835 | ((uptr->flags & UNIT_WPRT) && (uptr->FUNC == FCCY_WRITE)))\r | |
836 | {\r | |
837 | dkp_sta = dkp_sta | STA_DONE | STA_ERR; /* error */\r | |
838 | }\r | |
839 | else if ( uptr->CYL >= drv_tab[dtype].cyl ) /* bad cylinder */\r | |
840 | {\r | |
841 | dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_CYL ;\r | |
842 | dkp_sta = dkp_sta | STA_ERR | STA_CYL;\r | |
843 | DEV_SET_DONE( INT_DKP ) ;\r | |
844 | DEV_UPDATE_INTR ;\r | |
845 | return SCPE_OK ;\r | |
846 | }\r | |
847 | else if ( GET_SURF(dkp_ussc, dtype) >= drv_tab[dtype].surf ) /* bad surface */\r | |
848 | {\r | |
849 | dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /* older drives may not even do this... */\r | |
850 | /* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /- newer disks give this error */\r | |
851 | /* set sector to some bad value and wait then exit? */\r | |
852 | }\r | |
853 | else if ( GET_SECT(dkp_ussc, dtype) >= drv_tab[dtype].sect ) /* or bad sector? */\r | |
854 | {\r | |
855 | /* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /- older DG drives do not even give error(!), but we do */\r | |
856 | dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /* newer disks give this error */\r | |
857 | }\r | |
858 | else {\r | |
859 | err = 0 ;\r | |
860 | do {\r | |
861 | if ( DKP_TRACE(3) )\r | |
862 | {\r | |
863 | fprintf( DKP_TRACE_FP,\r | |
864 | " [%s:%c %-5s: %3d / %2d / %2d %06o ] \r\n",\r | |
865 | "DKP",\r | |
866 | (char) (u + '0'),\r | |
867 | ((uptr->FUNC == FCCY_READ) ?\r | |
868 | "read"\r | |
869 | : ((uptr->FUNC == FCCY_WRITE) ?\r | |
870 | "write"\r | |
871 | : "<???>")\r | |
872 | ),\r | |
873 | (unsigned) (uptr->CYL),\r | |
874 | (unsigned) (GET_SURF(dkp_ussc, dtype)),\r | |
875 | (unsigned) (GET_SECT(dkp_ussc, dtype)),\r | |
876 | (unsigned) (dkp_ma & 0xFFFF) /* show all 16-bits in case DCH B */\r | |
877 | ) ;\r | |
878 | }\r | |
879 | \r | |
880 | \r | |
881 | if ( GET_SECT(dkp_ussc, dtype) >= drv_tab[dtype].sect ) /* or bad sector? */\r | |
882 | {\r | |
883 | /* sector overflows to 0 ;\r | |
884 | * surface gets incremented\r | |
885 | */\r | |
886 | newsurf = GET_SURF(dkp_ussc, dtype) + 1 ;\r | |
887 | newsurf = newsurf & ((drv_tab[dtype].newf) ? USSC_M_NSURFACE : USSC_M_OSURFACE) ;\r | |
888 | DKP_UPDATE_USSC( type, 0, newsurf, 0 )\r | |
889 | \r | |
890 | if ( (GET_SURF(dkp_ussc, dtype)) >= drv_tab[dtype].surf )\r | |
891 | {\r | |
892 | /* dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_UNS; /- older drives may not even do this... */\r | |
893 | dkp_sta = dkp_sta | STA_DONE | STA_ERR | STA_XCY ; /* newer disks give this error */\r | |
894 | /* DG retains overflowed surface number,\r | |
895 | * other vendors have different/expanded options\r | |
896 | */\r | |
897 | break ;\r | |
898 | }\r | |
899 | }\r | |
900 | sa = GET_SA (uptr->CYL, GET_SURF (dkp_ussc, dtype),\r | |
901 | GET_SECT (dkp_ussc, dtype), dtype); /* get disk block */\r | |
902 | bda = sa * DKP_NUMWD * sizeof(uint16) ; /* to words, bytes */\r | |
903 | err = fseek (uptr->fileref, bda, SEEK_SET); /* position drive */\r | |
904 | \r | |
905 | if (uptr->FUNC == FCCY_READ) { /* read? */\r | |
906 | awc = fxread (tbuf, sizeof(uint16), DKP_NUMWD, uptr->fileref);\r | |
907 | for ( ; awc < DKP_NUMWD; awc++) tbuf[awc] = 0;\r | |
908 | if (err = ferror (uptr->fileref)) break;\r | |
909 | for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */\r | |
910 | pa = MapAddr (dkp_map, (dkp_ma & AMASK));\r | |
911 | if (MEM_ADDR_OK (pa)) M[pa] = tbuf[dx];\r | |
912 | dkp_ma = (dkp_ma + 1) & AMASK;\r | |
913 | }\r | |
914 | }\r | |
915 | else if (uptr->FUNC == FCCY_WRITE) { /* write? */\r | |
916 | for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop into buffer */\r | |
917 | pa = MapAddr (dkp_map, (dkp_ma & AMASK));\r | |
918 | tbuf[dx] = M[pa];\r | |
919 | dkp_ma = (dkp_ma + 1) & AMASK;\r | |
920 | }\r | |
921 | fxwrite (tbuf, sizeof(int16), DKP_NUMWD, uptr->fileref);\r | |
922 | if (err = ferror (uptr->fileref)) break;\r | |
923 | }\r | |
924 | \r | |
925 | if (err != 0) {\r | |
926 | perror ("DKP I/O error");\r | |
927 | clearerr (uptr->fileref);\r | |
928 | rval = SCPE_IOERR;\r | |
929 | break ;\r | |
930 | }\r | |
931 | \r | |
932 | newsect = GET_SECT (dkp_ussc, dtype) + 1 ; /* update next sector */\r | |
933 | newsurf = GET_SURF (dkp_ussc, dtype) ; /* and next head */\r | |
934 | /* (count set below) */\r | |
935 | DKP_UPDATE_USSC( type, 1, newsurf, newsect )\r | |
936 | } /* end read/write loop */\r | |
937 | \r | |
938 | while ( (GET_COUNT(dkp_ussc)) ) ;\r | |
939 | dkp_sta = dkp_sta | STA_DONE; /* set status */\r | |
940 | \r | |
941 | if ( DKP_TRACE(4) )\r | |
942 | {\r | |
943 | fprintf( DKP_TRACE_FP,\r | |
944 | " [%s:%c %-5s: %3d / %2d / %2d %06o ] \r\n",\r | |
945 | "DKP",\r | |
946 | (char) (u + '0'),\r | |
947 | "post",\r | |
948 | (unsigned) (uptr->CYL),\r | |
949 | (unsigned) (GET_SURF(dkp_ussc, dtype)),\r | |
950 | (unsigned) (GET_SECT(dkp_ussc, dtype)),\r | |
951 | (unsigned) (dkp_ma & 0xFFFF) /* show all 16-bits in case DCH B */\r | |
952 | ) ;\r | |
953 | }\r | |
954 | }\r | |
955 | \r | |
956 | DEV_CLR_BUSY( INT_DKP ) ;\r | |
957 | DEV_SET_DONE( INT_DKP ) ;\r | |
958 | DEV_UPDATE_INTR ;\r | |
959 | return rval;\r | |
960 | }\r | |
961 | \r | |
962 | /* Reset routine */\r | |
963 | \r | |
964 | t_stat dkp_reset (DEVICE *dptr)\r | |
965 | {\r | |
966 | int32 u;\r | |
967 | UNIT *uptr;\r | |
968 | \r | |
969 | DEV_CLR_BUSY( INT_DKP ) ; /* clear busy */\r | |
970 | DEV_CLR_DONE( INT_DKP ) ; /* clear done */\r | |
971 | DEV_UPDATE_INTR ; /* update ints */\r | |
972 | dkp_fccy = dkp_ussc = dkp_ma = dkp_sta = 0; /* clear registers */\r | |
973 | dkp_diagmode = 0; /* clear diagnostic mode */\r | |
974 | dkp_map = 0;\r | |
975 | for (u = 0; u < DKP_NUMDR; u++) { /* loop thru units */\r | |
976 | uptr = dkp_dev.units + u;\r | |
977 | sim_cancel (uptr); /* cancel activity */\r | |
978 | uptr->CYL = uptr->FUNC = 0;\r | |
979 | }\r | |
980 | return SCPE_OK;\r | |
981 | }\r | |
982 | \r | |
983 | /* Attach routine (with optional autosizing) */\r | |
984 | \r | |
985 | t_stat dkp_attach (UNIT *uptr, char *cptr)\r | |
986 | {\r | |
987 | int32 i, p;\r | |
988 | t_stat r;\r | |
989 | \r | |
990 | uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; /* restore capac */\r | |
991 | r = attach_unit (uptr, cptr); /* attach */\r | |
992 | if ((r != SCPE_OK) || !(uptr->flags & UNIT_AUTO)) return r;\r | |
993 | if ((p = sim_fsize (uptr->fileref)) == 0) return SCPE_OK; /* get file size */\r | |
994 | for (i = 0; drv_tab[i].sect != 0; i++) {\r | |
995 | if (p <= (drv_tab[i].size * (int32) sizeof (uint16))) {\r | |
996 | uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE);\r | |
997 | uptr->capac = drv_tab[i].size;\r | |
998 | return SCPE_OK;\r | |
999 | }\r | |
1000 | }\r | |
1001 | return SCPE_OK;\r | |
1002 | }\r | |
1003 | \r | |
1004 | /* Set size command validation routine */\r | |
1005 | \r | |
1006 | t_stat dkp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)\r | |
1007 | {\r | |
1008 | if (uptr->flags & UNIT_ATT) return SCPE_ALATT;\r | |
1009 | uptr->capac = drv_tab[GET_DTYPE (val)].size;\r | |
1010 | return SCPE_OK;\r | |
1011 | }\r | |
1012 | \r | |
1013 | /* Bootstrap routine */\r | |
1014 | \r | |
1015 | #if defined(_OLD_CODE_)\r | |
1016 | \r | |
1017 | #define BOOT_START 02000\r | |
1018 | #define BOOT_UNIT 02021\r | |
1019 | #define BOOT_SEEK 02022\r | |
1020 | #define BOOT_LEN (sizeof(boot_rom) / sizeof(int32))\r | |
1021 | \r | |
1022 | static const int32 boot_rom[] = {\r | |
1023 | 0060233, /* NIOC 0,DKP ; clear disk */\r | |
1024 | 0020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */\r | |
1025 | 0063033, /* DOC 0,DKP ; select disk */\r | |
1026 | 0020417, /* LDA 0,SEKCMD ; command, cylinder */\r | |
1027 | 0061333, /* DOAP 0,DKP ; start seek */\r | |
1028 | 0024415, /* LDA 1,SEKDN */\r | |
1029 | 0060433, /* DIA 0,DKP ; get status */\r | |
1030 | 0123415, /* AND# 1,0,SZR ; skip if done */\r | |
1031 | 0000776, /* JMP .-2 */\r | |
1032 | 0102400, /* SUB 0,0 ; mem addr = 0 */\r | |
1033 | 0062033, /* DOB 0,DKP */\r | |
1034 | 0020411, /* LDA 0,REDCMD ; command, cylinder */\r | |
1035 | 0061133, /* DOAS 0,DKP ; start read */\r | |
1036 | 0060433, /* DIA 0, DKP ; get status */\r | |
1037 | 0101113, /* MOVL# 0,0,SNC ; skip if done */\r | |
1038 | 0000776, /* JMP .-2 */\r | |
1039 | 0000377, /* JMP 377 */\r | |
1040 | 0000016, /* USSC: 0.B1+0.B7+0.B11+16 */\r | |
1041 | 0175000, /* SEKCMD: 175000 */\r | |
1042 | 0074000, /* SEKDN: 074000 */\r | |
1043 | 0174000 /* REDCMD: 174000 */\r | |
1044 | };\r | |
1045 | \r | |
1046 | \r | |
1047 | t_stat dkp_boot (int32 unitno, DEVICE *dptr)\r | |
1048 | {\r | |
1049 | int32 i, dtype;\r | |
1050 | extern int32 saved_PC, SR;\r | |
1051 | \r | |
1052 | for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];\r | |
1053 | unitno = unitno & USSC_M_UNIT;\r | |
1054 | dtype = GET_DTYPE (dkp_unit[unitno].flags);\r | |
1055 | M[BOOT_UNIT] = M[BOOT_UNIT] | (unitno << USSC_V_UNIT);\r | |
1056 | if (drv_tab[dtype].newf) M[BOOT_SEEK] = 0176000;\r | |
1057 | saved_PC = BOOT_START;\r | |
1058 | SR = 0100000 + DEV_DKP;\r | |
1059 | return SCPE_OK;\r | |
1060 | }\r | |
1061 | \r | |
1062 | #endif /* _OLD_CODE_ */\r | |
1063 | \r | |
1064 | \r | |
1065 | \r | |
1066 | #define BOOT_START 0375\r | |
1067 | #define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))\r | |
1068 | \r | |
1069 | static const int32 boot_rom[] = {\r | |
1070 | 0062677 /* IORST ; reset the I/O system */\r | |
1071 | , 0060133 /* NIOS DKP ; start the disk */\r | |
1072 | , 0000377 /* JMP 377 ; wait for the world */\r | |
1073 | } ;\r | |
1074 | \r | |
1075 | \r | |
1076 | t_stat dkp_boot (int32 unitno, DEVICE *dptr)\r | |
1077 | {\r | |
1078 | int32 i;\r | |
1079 | \r | |
1080 | for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = (uint16) boot_rom[i];\r | |
1081 | saved_PC = BOOT_START;\r | |
1082 | SR = 0100000 + DEV_DKP;\r | |
1083 | return SCPE_OK;\r | |
1084 | }\r |