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