Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* h316_fhd.c: H316/516 fixed head simulator\r |
2 | \r | |
3 | Copyright (c) 2003-2006, 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 | fhd 516-4400 fixed head disk\r | |
27 | \r | |
28 | 15-May-06 RMS Fixed bug in autosize attach (reported by David Gesswein)\r | |
29 | 04-Jan-04 RMS Changed sim_fsize calling sequence\r | |
30 | \r | |
31 | These head-per-track devices are buffered in memory, to minimize overhead.\r | |
32 | */\r | |
33 | \r | |
34 | #include "h316_defs.h"\r | |
35 | #include <math.h>\r | |
36 | \r | |
37 | /* Constants */\r | |
38 | \r | |
39 | #define FH_NUMWD 1536 /* words/track */\r | |
40 | #define FH_NUMTK 64 /* tracks/surface */\r | |
41 | #define FH_WDPSF (FH_NUMWD * FH_NUMTK) /* words/surface */ \r | |
42 | #define FH_NUMSF 16 /* surfaces/ctlr */\r | |
43 | #define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */\r | |
44 | #define UNIT_V_SF (UNIT_V_UF + 1) /* #surfaces - 1 */\r | |
45 | #define UNIT_M_SF 017\r | |
46 | #define UNIT_AUTO (1 << UNIT_V_AUTO)\r | |
47 | #define UNIT_SF (UNIT_M_SF << UNIT_V_SF)\r | |
48 | #define UNIT_GETSF(x) ((((x) >> UNIT_V_SF) & UNIT_M_SF) + 1)\r | |
49 | \r | |
50 | /* Command word 1 */\r | |
51 | \r | |
52 | #define CW1_RW 0100000 /* read vs write */\r | |
53 | #define CW1_V_SF 10 /* surface */\r | |
54 | #define CW1_M_SF 017\r | |
55 | #define CW1_GETSF(x) (((x) >> CW1_V_SF) & CW1_M_SF)\r | |
56 | #define CW1_V_TK 4 /* track */\r | |
57 | #define CW1_M_TK 077\r | |
58 | #define CW1_GETTK(x) (((x) >> CW1_V_TK) & CW1_M_TK)\r | |
59 | \r | |
60 | /* Command word 2 */\r | |
61 | \r | |
62 | #define CW2_V_CA 0 /* character addr */\r | |
63 | #define CW2_M_CA 07777\r | |
64 | #define CW2_GETCA(x) (((x) >> CW2_V_CA) & CW2_M_CA)\r | |
65 | \r | |
66 | #define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \\r | |
67 | ((double) FH_NUMWD)))\r | |
68 | \r | |
69 | /* OTA states */\r | |
70 | \r | |
71 | #define OTA_NOP 0 /* normal */\r | |
72 | #define OTA_CW1 1 /* expecting CW1 */\r | |
73 | #define OTA_CW2 2 /* expecting CW2 */\r | |
74 | \r | |
75 | extern int32 dev_int, dev_enb, chan_req;\r | |
76 | extern int32 stop_inst;\r | |
77 | extern uint32 dma_ad[DMA_MAX];\r | |
78 | \r | |
79 | uint32 fhd_cw1 = 0; /* cmd word 1 */\r | |
80 | uint32 fhd_cw2 = 0; /* cmd word 2 */\r | |
81 | uint32 fhd_buf = 0; /* buffer */\r | |
82 | uint32 fhd_otas = 0; /* state */\r | |
83 | uint32 fhd_busy = 0; /* busy */\r | |
84 | uint32 fhd_rdy = 0; /* word ready */\r | |
85 | uint32 fhd_dte = 0; /* data err */\r | |
86 | uint32 fhd_ace = 0; /* access error */\r | |
87 | uint32 fhd_dma = 0; /* DMA/DMC */\r | |
88 | uint32 fhd_eor = 0; /* end of range */\r | |
89 | uint32 fhd_csum = 0; /* parity checksum */\r | |
90 | uint32 fhd_stopioe = 1; /* stop on error */\r | |
91 | int32 fhd_time = 10; /* time per word */\r | |
92 | \r | |
93 | int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev);\r | |
94 | t_stat fhd_svc (UNIT *uptr);\r | |
95 | t_stat fhd_reset (DEVICE *dptr);\r | |
96 | t_stat fhd_attach (UNIT *uptr, char *cptr);\r | |
97 | t_stat fhd_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);\r | |
98 | void fhd_go (uint32 dma);\r | |
99 | void fhd_go1 (uint32 dat);\r | |
100 | void fhd_go2 (uint32 dat);\r | |
101 | t_bool fhd_getc (UNIT *uptr, uint32 *ch);\r | |
102 | t_bool fhd_putc (UNIT *uptr, uint32 ch);\r | |
103 | t_bool fhd_bad_wa (uint32 wa);\r | |
104 | uint32 fhd_csword (uint32 cs, uint32 ch);\r | |
105 | \r | |
106 | /* FHD data structures\r | |
107 | \r | |
108 | fhd_dev device descriptor\r | |
109 | fhd_unit unit descriptor\r | |
110 | fhd_mod unit modifiers\r | |
111 | fhd_reg register list\r | |
112 | */\r | |
113 | \r | |
114 | DIB fhd_dib = { FHD, IOBUS, 1, &fhdio };\r | |
115 | \r | |
116 | UNIT fhd_unit = { \r | |
117 | UDATA (&fhd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,\r | |
118 | FH_WDPSF)\r | |
119 | };\r | |
120 | \r | |
121 | REG fhd_reg[] = {\r | |
122 | { ORDATA (CW1, fhd_cw1, 16) },\r | |
123 | { ORDATA (CW2, fhd_cw2, 16) },\r | |
124 | { ORDATA (BUF, fhd_buf, 16) },\r | |
125 | { FLDATA (BUSY, fhd_busy, 0) },\r | |
126 | { FLDATA (RDY, fhd_rdy, 0) },\r | |
127 | { FLDATA (DTE, fhd_dte, 0) },\r | |
128 | { FLDATA (ACE, fhd_ace, 0) },\r | |
129 | { FLDATA (EOR, fhd_eor, 0) },\r | |
130 | { FLDATA (DMA, fhd_dma, 0) },\r | |
131 | { FLDATA (CSUM, fhd_csum, 7) },\r | |
132 | { FLDATA (INTREQ, dev_int, INT_V_MT) },\r | |
133 | { FLDATA (ENABLE, dev_enb, INT_V_MT) },\r | |
134 | { DRDATA (TIME, fhd_time, 31), REG_NZ + PV_LEFT },\r | |
135 | { ORDATA (OTAS, fhd_otas, 2), REG_HRO },\r | |
136 | { ORDATA (CHAN, fhd_dib.chan, 5), REG_HRO },\r | |
137 | { FLDATA (STOP_IOE, fhd_stopioe, 0) },\r | |
138 | { NULL }\r | |
139 | };\r | |
140 | \r | |
141 | MTAB fhd_mod[] = {\r | |
142 | { UNIT_SF, (0 << UNIT_V_SF), NULL, "1S", &fhd_set_size },\r | |
143 | { UNIT_SF, (1 << UNIT_V_SF), NULL, "2S", &fhd_set_size },\r | |
144 | { UNIT_SF, (2 << UNIT_V_SF), NULL, "3S", &fhd_set_size },\r | |
145 | { UNIT_SF, (3 << UNIT_V_SF), NULL, "4S", &fhd_set_size },\r | |
146 | { UNIT_SF, (4 << UNIT_V_SF), NULL, "5S", &fhd_set_size },\r | |
147 | { UNIT_SF, (5 << UNIT_V_SF), NULL, "6S", &fhd_set_size },\r | |
148 | { UNIT_SF, (6 << UNIT_V_SF), NULL, "7S", &fhd_set_size },\r | |
149 | { UNIT_SF, (7 << UNIT_V_SF), NULL, "8S", &fhd_set_size },\r | |
150 | { UNIT_SF, (8 << UNIT_V_SF), NULL, "9S", &fhd_set_size },\r | |
151 | { UNIT_SF, (9 << UNIT_V_SF), NULL, "10S", &fhd_set_size },\r | |
152 | { UNIT_SF, (10 << UNIT_V_SF), NULL, "11S", &fhd_set_size },\r | |
153 | { UNIT_SF, (11 << UNIT_V_SF), NULL, "12S", &fhd_set_size },\r | |
154 | { UNIT_SF, (12 << UNIT_V_SF), NULL, "13S", &fhd_set_size },\r | |
155 | { UNIT_SF, (13 << UNIT_V_SF), NULL, "14S", &fhd_set_size },\r | |
156 | { UNIT_SF, (14 << UNIT_V_SF), NULL, "15S", &fhd_set_size },\r | |
157 | { UNIT_SF, (15 << UNIT_V_SF), NULL, "16S", &fhd_set_size },\r | |
158 | { UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },\r | |
159 | { MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS",\r | |
160 | &io_set_iobus, NULL, NULL },\r | |
161 | { MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",\r | |
162 | &io_set_dmc, NULL, NULL },\r | |
163 | { MTAB_XTD|MTAB_VDV, 0, NULL, "DMA",\r | |
164 | &io_set_dma, NULL, NULL },\r | |
165 | { MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL,\r | |
166 | NULL, &io_show_chan, NULL },\r | |
167 | { 0 }\r | |
168 | };\r | |
169 | \r | |
170 | DEVICE fhd_dev = {\r | |
171 | "FHD", &fhd_unit, fhd_reg, fhd_mod,\r | |
172 | 1, 8, 22, 1, 8, 16,\r | |
173 | NULL, NULL, &fhd_reset,\r | |
174 | NULL, &fhd_attach, NULL,\r | |
175 | &fhd_dib, DEV_DISABLE\r | |
176 | };\r | |
177 | \r | |
178 | /* IO routines */\r | |
179 | \r | |
180 | int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev)\r | |
181 | {\r | |
182 | switch (inst) { /* case on opcode */\r | |
183 | \r | |
184 | case ioOCP: /* control */\r | |
185 | if (fnc == 04) { /* terminate output? */\r | |
186 | fhd_eor = 1; /* stop */\r | |
187 | CLR_INT (INT_FHD); /* clear int req */\r | |
188 | }\r | |
189 | else if (fnc == 003) fhd_go (1); /* start, DMA */\r | |
190 | else if (fnc == 007) fhd_go (0); /* start, IO bus */\r | |
191 | else return IOBADFNC (dat);\r | |
192 | break;\r | |
193 | \r | |
194 | case ioOTA: /* output */\r | |
195 | if (fnc) return IOBADFNC (dat); /* only fnc 0 */\r | |
196 | if (fhd_rdy) { /* ready? */\r | |
197 | fhd_buf = dat; /* store data */\r | |
198 | if (fhd_otas == OTA_CW1) fhd_go1 (dat); /* expecting CW1? */\r | |
199 | else if (fhd_otas == OTA_CW2) fhd_go2 (dat);/* expecting CW2? */\r | |
200 | else fhd_rdy = 0; /* normal, clr ready */\r | |
201 | return IOSKIP (dat);\r | |
202 | }\r | |
203 | break;\r | |
204 | \r | |
205 | case ioINA: /* input */\r | |
206 | if (fnc) return IOBADFNC (dat); /* only fnc 0 */\r | |
207 | if (fhd_rdy) { /* ready? */\r | |
208 | fhd_rdy = 0; /* clear ready */\r | |
209 | return IOSKIP (dat | fhd_buf); /* return data */\r | |
210 | }\r | |
211 | break;\r | |
212 | \r | |
213 | case ioSKS: /* sense */\r | |
214 | if (((fnc == 000) && fhd_rdy) || /* 0 = skip if ready */\r | |
215 | ((fnc == 001) && !fhd_busy) || /* 1 = skip if !busy */\r | |
216 | ((fnc == 002) && !fhd_dte) || /* 2 = skip if !data err */\r | |
217 | ((fnc == 003) && !fhd_ace) || /* 3 = skip if !access err */\r | |
218 | ((fnc == 004) && !TST_INTREQ (INT_FHD))) /* 4 = skip if !interrupt */\r | |
219 | return IOSKIP (dat);\r | |
220 | break;\r | |
221 | \r | |
222 | case ioEND:\r | |
223 | fhd_eor = 1;\r | |
224 | break;\r | |
225 | }\r | |
226 | \r | |
227 | return dat;\r | |
228 | }\r | |
229 | \r | |
230 | /* Start new operation */\r | |
231 | \r | |
232 | void fhd_go (uint32 dma)\r | |
233 | {\r | |
234 | int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */\r | |
235 | \r | |
236 | if (fhd_busy) return; /* ignore if busy */\r | |
237 | fhd_busy = 1; /* ctlr is busy */\r | |
238 | fhd_eor = 0; /* transfer not done */\r | |
239 | fhd_csum = 0; /* init checksum */\r | |
240 | fhd_dte = 0; /* clear errors */\r | |
241 | fhd_ace = 0;\r | |
242 | if (ch >= 0) fhd_dma = dma; /* DMA allowed? */\r | |
243 | else fhd_dma = 0; /* no, force IO bus */\r | |
244 | fhd_otas = OTA_CW1; /* expect CW1 */\r | |
245 | fhd_rdy = 1; /* set ready */\r | |
246 | if (fhd_dma && Q_DMA (ch)) { /* DMA and DMA channel? */\r | |
247 | SET_CH_REQ (ch); /* set channel request */\r | |
248 | dma_ad[ch] = dma_ad[ch] & ~DMA_IN; /* force output */\r | |
249 | }\r | |
250 | return;\r | |
251 | }\r | |
252 | \r | |
253 | /* Process command word 1 */\r | |
254 | \r | |
255 | void fhd_go1 (uint32 dat)\r | |
256 | {\r | |
257 | int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */\r | |
258 | \r | |
259 | fhd_cw1 = dat; /* store CW1 */\r | |
260 | fhd_otas = OTA_CW2; /* expect CW2 */\r | |
261 | fhd_rdy = 1; /* set ready */\r | |
262 | if (fhd_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */\r | |
263 | return;\r | |
264 | }\r | |
265 | \r | |
266 | /* Process command word 2 - initiate seek */\r | |
267 | \r | |
268 | void fhd_go2 (uint32 dat)\r | |
269 | {\r | |
270 | int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */\r | |
271 | uint32 sf = CW1_GETSF (fhd_cw1); /* surface */\r | |
272 | int32 t, wa;\r | |
273 | \r | |
274 | fhd_cw2 = dat; /* store CW2 */\r | |
275 | fhd_otas = OTA_NOP; /* next state */\r | |
276 | wa = CW2_GETCA (fhd_cw2) >> 1; /* word addr */\r | |
277 | if ((wa >= FH_NUMWD) || /* if bad char addr */\r | |
278 | ((fhd_unit.flags & UNIT_ATT) == 0) || /* or unattached */\r | |
279 | (sf >= UNIT_GETSF (fhd_unit.flags))) { /* or bad surface */\r | |
280 | fhd_ace = 1; /* access error */\r | |
281 | fhd_busy = 0; /* abort operation */\r | |
282 | SET_INT (INT_FHD);\r | |
283 | return;\r | |
284 | }\r | |
285 | if (fhd_cw1 & CW1_RW) { /* write? */\r | |
286 | fhd_rdy = 1; /* set ready */\r | |
287 | if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */\r | |
288 | }\r | |
289 | else {\r | |
290 | fhd_rdy = 0; /* read, clear ready */\r | |
291 | if (fhd_dma && (ch < DMC_V_DMC1)) /* read and DMA chan? */\r | |
292 | dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */\r | |
293 | }\r | |
294 | t = wa - GET_POS (fhd_time); /* delta to new loc */\r | |
295 | if (t < 0) t = t + FH_NUMWD; /* wrap around? */\r | |
296 | sim_activate (&fhd_unit, t * fhd_time); /* schedule op */\r | |
297 | return;\r | |
298 | }\r | |
299 | \r | |
300 | /* Unit service */\r | |
301 | \r | |
302 | t_stat fhd_svc (UNIT *uptr)\r | |
303 | {\r | |
304 | int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan (-1 if IO bus) */\r | |
305 | uint32 c1, c2;\r | |
306 | \r | |
307 | if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */\r | |
308 | fhd_ace = 1; /* access error */\r | |
309 | fhd_busy = 0; /* abort operation */\r | |
310 | SET_INT (INT_FHD);\r | |
311 | return IORETURN (fhd_stopioe, SCPE_UNATT);\r | |
312 | }\r | |
313 | \r | |
314 | if (fhd_eor || fhd_rdy) { /* done or ready set? */\r | |
315 | if (fhd_rdy) fhd_dte = 1; /* if ready set, data err */\r | |
316 | if (fhd_cw1 & CW1_RW) { /* write? */\r | |
317 | if (!fhd_rdy) { /* buffer full? */\r | |
318 | fhd_putc (uptr, fhd_buf >> 8); /* store last word */\r | |
319 | fhd_putc (uptr, fhd_buf);\r | |
320 | }\r | |
321 | fhd_putc (uptr, fhd_csum); /* store csum */\r | |
322 | }\r | |
323 | else { /* read */\r | |
324 | fhd_getc (uptr, &c1); /* get csum */\r | |
325 | if (fhd_csum) fhd_dte = 1; /* if csum != 0, err */\r | |
326 | }\r | |
327 | fhd_busy = 0; /* operation complete */\r | |
328 | SET_INT (INT_FHD);\r | |
329 | return SCPE_OK;\r | |
330 | }\r | |
331 | \r | |
332 | if (fhd_cw1 & CW1_RW) { /* write? */\r | |
333 | if (fhd_putc (uptr, fhd_buf >> 8)) return SCPE_OK;\r | |
334 | if (fhd_putc (uptr, fhd_buf)) return SCPE_OK;\r | |
335 | }\r | |
336 | else {\r | |
337 | if (fhd_getc (uptr, &c1)) return SCPE_OK; /* read */\r | |
338 | if (fhd_getc (uptr, &c2)) return SCPE_OK;\r | |
339 | fhd_buf = (c1 << 8) | c2;\r | |
340 | }\r | |
341 | sim_activate (uptr, fhd_time); /* next word */\r | |
342 | fhd_rdy = 1; /* set ready */\r | |
343 | if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */\r | |
344 | return SCPE_OK;\r | |
345 | }\r | |
346 | \r | |
347 | /* Read character from disk */\r | |
348 | \r | |
349 | t_bool fhd_getc (UNIT *uptr, uint32 *ch)\r | |
350 | {\r | |
351 | uint32 sf = CW1_GETSF (fhd_cw1); /* surface */\r | |
352 | uint32 tk = CW1_GETTK (fhd_cw1); /* track */\r | |
353 | uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */\r | |
354 | uint32 wa = ca >> 1; /* word addr */\r | |
355 | uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */\r | |
356 | uint16 *fbuf = uptr->filebuf; /* buffer base */\r | |
357 | uint32 wd;\r | |
358 | \r | |
359 | if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */\r | |
360 | fhd_cw2 = fhd_cw2 + 1; /* incr char addr */\r | |
361 | if (ca & 1) wd = fbuf[ba] & 0377; /* select char */\r | |
362 | else wd = (fbuf[ba] >> 8) & 0377;\r | |
363 | fhd_csum = fhd_csword (fhd_csum, wd); /* put in csum */\r | |
364 | *ch = wd; /* return */\r | |
365 | return FALSE;\r | |
366 | }\r | |
367 | \r | |
368 | /* Write character to disk */\r | |
369 | \r | |
370 | t_bool fhd_putc (UNIT *uptr, uint32 ch)\r | |
371 | {\r | |
372 | uint32 sf = CW1_GETSF (fhd_cw1); /* surface */\r | |
373 | uint32 tk = CW1_GETTK (fhd_cw1); /* track */\r | |
374 | uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */\r | |
375 | uint32 wa = ca >> 1; /* word addr */\r | |
376 | uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */\r | |
377 | uint16 *fbuf = uptr->filebuf; /* buffer base */\r | |
378 | \r | |
379 | ch = ch & 0377; /* mask char */\r | |
380 | if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */\r | |
381 | fhd_cw2 = fhd_cw2 + 1; /* incr char addr */\r | |
382 | if (ca & 1) fbuf[ba] = (fbuf[ba] & ~0377) | ch; /* odd? low char */\r | |
383 | else fbuf[ba] = (fbuf[ba] & 0377) | (ch << 8); /* even, hi char */\r | |
384 | fhd_csum = fhd_csword (fhd_csum, ch); /* put in csum */\r | |
385 | if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* update hwmark */\r | |
386 | return FALSE;\r | |
387 | }\r | |
388 | \r | |
389 | /* Check word address */\r | |
390 | \r | |
391 | t_bool fhd_bad_wa (uint32 wa)\r | |
392 | {\r | |
393 | if (wa >= FH_NUMWD) { /* bad address? */\r | |
394 | fhd_ace = 1; /* access error */\r | |
395 | fhd_busy = 0; /* abort operation */\r | |
396 | SET_INT (INT_FHD);\r | |
397 | return TRUE;\r | |
398 | }\r | |
399 | return FALSE;\r | |
400 | }\r | |
401 | \r | |
402 | /* Add character to checksum (parity) */\r | |
403 | \r | |
404 | uint32 fhd_csword (uint32 cs, uint32 ch)\r | |
405 | {\r | |
406 | while (ch) { /* count bits */\r | |
407 | ch = ch & ~(ch & (-(int32) ch));\r | |
408 | cs = cs ^ 0200; /* invert cs for each 1 */\r | |
409 | }\r | |
410 | return cs;\r | |
411 | }\r | |
412 | \r | |
413 | /* Reset routine */\r | |
414 | \r | |
415 | t_stat fhd_reset (DEVICE *dptr)\r | |
416 | {\r | |
417 | fhd_busy = 0; /* reset state */\r | |
418 | fhd_rdy = 0;\r | |
419 | fhd_ace = 0;\r | |
420 | fhd_dte = 0;\r | |
421 | fhd_eor = 0;\r | |
422 | fhd_otas = OTA_NOP;\r | |
423 | fhd_cw1 = fhd_cw2 = fhd_buf = 0;\r | |
424 | CLR_INT (INT_FHD); /* clear int, enb */\r | |
425 | CLR_ENB (INT_FHD);\r | |
426 | sim_cancel (&fhd_unit); /* cancel operation */\r | |
427 | return SCPE_OK;\r | |
428 | }\r | |
429 | \r | |
430 | /* Attach routine */\r | |
431 | \r | |
432 | t_stat fhd_attach (UNIT *uptr, char *cptr)\r | |
433 | {\r | |
434 | uint32 sz, sf;\r | |
435 | uint32 ds_bytes = FH_WDPSF * sizeof (int16);\r | |
436 | \r | |
437 | if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {\r | |
438 | sf = (sz + ds_bytes - 1) / ds_bytes;\r | |
439 | if (sf >= FH_NUMSF) sf = FH_NUMSF - 1;\r | |
440 | uptr->flags = (uptr->flags & ~UNIT_SF) |\r | |
441 | (sf << UNIT_V_SF);\r | |
442 | }\r | |
443 | uptr->capac = UNIT_GETSF (uptr->flags) * FH_WDPSF;\r | |
444 | return attach_unit (uptr, cptr);\r | |
445 | }\r | |
446 | \r | |
447 | /* Set size routine */\r | |
448 | \r | |
449 | t_stat fhd_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)\r | |
450 | {\r | |
451 | if (val < 0) return SCPE_IERR;\r | |
452 | if (uptr->flags & UNIT_ATT) return SCPE_ALATT;\r | |
453 | uptr->capac = UNIT_GETSF (val) * FH_WDPSF;\r | |
454 | return SCPE_OK;\r | |
455 | }\r |