1 /* hp_disclib.h: HP MAC/ICD disc controller simulator library declarations
2 
3    Copyright (c) 2011-2021, J. David Bryan
4    Copyright (c) 2004-2011, Robert M. Supnik
5 
6    Permission is hereby granted, free of charge, to any person obtaining a
7    copy of this software and associated documentation files (the "Software"),
8    to deal in the Software without restriction, including without limitation
9    the rights to use, copy, modify, merge, publish, distribute, sublicense,
10    and/or sell copies of the Software, and to permit persons to whom the
11    Software is furnished to do so, subject to the following conditions:
12 
13    The above copyright notice and this permission notice shall be included in
14    all copies or substantial portions of the Software.
15 
16    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19    THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20    IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 
23    Except as contained in this notice, the names of the authors shall not be
24    used in advertising or otherwise to promote the sale, use or other dealings
25    in this Software without prior written authorization from the authors.
26 
27    02-Apr-21    JDB     Changed u3-u6 synonyms to title case to avoid conflicts
28    17-Jan-17    JDB     Moved "hp2100_defs.h" inclusion to "hp2100_disclib.c"
29    13-May-16    JDB     Modified for revised SCP API function parameter types
30    24-Oct-12    JDB     Changed CNTLR_OPCODE to title case to avoid name clash
31    07-May-12    JDB     Added end-of-track delay time as a controller variable
32    02-May-12    JDB     First release
33    09-Nov-11    JDB     Created disc controller common library from DS simulator
34 
35 
36    This file defines the interface between interface simulators and the
37    simulation library for the HP 13037 and 13365 disc controllers.  It must be
38    included by the interface-specific modules (DA, DS, etc.).
39 */
40 
41 
42 
43 /* Program limits */
44 
45 #define DL_MAXDRIVE      7                              /* last valid drive number */
46 #define DL_MAXUNIT      10                              /* last legal unit number */
47 
48 #define DL_AUXUNITS      2                              /* number of MAC auxiliary units required */
49 
50 #define DL_WPSEC        128                             /* words per normal sector */
51 #define DL_WPFSEC       138                             /* words per full sector */
52 #define DL_BUFSIZE      DL_WPFSEC                       /* required buffer size in words */
53 
54 
55 /* Default controller times */
56 
57 #define DL_EOT_TIME     160                             /* end-of-track delay time */
58 #define DL_SEEK_TIME    100                             /* seek delay time (per cylinder) */
59 #define DL_SECTOR_TIME   27                             /* intersector delay time */
60 #define DL_CMD_TIME       3                             /* command start delay time */
61 #define DL_DATA_TIME      1                             /* data transfer delay time */
62 
63 #define DL_WAIT_TIME    2749200                         /* command wait timeout (1.74 seconds) */
64 
65 
66 /* Common per-unit disc drive state variables */
67 
68 #define Cyl             u3                              /* current drive cylinder */
69 #define Stat            u4                              /* current drive status (Status 2) */
70 #define Op              u5                              /* current drive operation in process */
71 #define Phase           u6                              /* current drive operation phase */
72 
73 
74 /* Unit flags and accessors */
75 
76 #define UNIT_V_MODEL    (UNIT_V_UF + 0)                 /* bits 1-0: model ID */
77 #define UNIT_V_WLK      (UNIT_V_UF + 2)                 /* bits 2-2: write locked (protect switch) */
78 #define UNIT_V_UNLOAD   (UNIT_V_UF + 3)                 /* bits 3-3: heads unloaded */
79 #define UNIT_V_FMT      (UNIT_V_UF + 4)                 /* bits 4-4: format enabled */
80 #define UNIT_V_AUTO     (UNIT_V_UF + 5)                 /* bits 5-5: autosize */
81 #define DL_V_UF         (UNIT_V_UF + 6)                 /* first free unit flag bit */
82 
83 #define UNIT_M_MODEL    03                              /* model ID mask */
84 
85 #define UNIT_MODEL      (UNIT_M_MODEL << UNIT_V_MODEL)
86 #define UNIT_WLK        (1 << UNIT_V_WLK)
87 #define UNIT_UNLOAD     (1 << UNIT_V_UNLOAD)
88 #define UNIT_FMT        (1 << UNIT_V_FMT)
89 #define UNIT_AUTO       (1 << UNIT_V_AUTO)
90 
91 #define UNIT_WPROT      (UNIT_WLK | UNIT_RO)            /* write protected if locked or read-only */
92 
93 #define GET_MODEL(t)    (((t) >> UNIT_V_MODEL) & UNIT_M_MODEL)
94 #define SET_MODEL(t)    (((t) & UNIT_M_MODEL) << UNIT_V_MODEL)
95 
96 
97 /* Status-1 accessors */
98 
99 #define DL_V_S1SPD      13                              /* bits 15-13: S/P/D flags */
100 #define DL_V_S1STAT      8                              /* bits 12- 8: controller status */
101 #define DL_V_S1UNIT      0                              /* bits  3- 0: last unit number */
102 
103 #define DL_M_S1UNIT     017                             /* unit number mask */
104 
105 #define GET_S1UNIT(v)   (((v) >> DL_V_S1UNIT) & DL_M_S1UNIT)
106 
107 #define SET_S1SPD(v)    ((v) << DL_V_S1SPD)
108 #define SET_S1STAT(v)   ((v) << DL_V_S1STAT)
109 #define SET_S1UNIT(v)   ((v) << DL_V_S1UNIT)
110 
111 
112 /* Status-2 accessors (+ = kept in unit status, - = determined dynamically) */
113 
114 #define DL_V_S2ERR      15                              /* bits 15-15: (-) any error flag */
115 #define DL_V_S2DTYP      9                              /* bits 12- 9: (-) drive type */
116 #define DL_V_S2ATN       7                              /* bits  7- 7: (+) attention flag */
117 #define DL_V_S2RO        6                              /* bits  6- 6: (-) read only flag */
118 #define DL_V_S2FMT       5                              /* bits  5- 5: (-) format enabled flag */
119 #define DL_V_S2FAULT     4                              /* bits  4- 4: (+) drive fault flag */
120 #define DL_V_S2FS        3                              /* bits  3- 3: (+) first status flag */
121 #define DL_V_S2SC        2                              /* bits  2- 2: (+) seek check flag */
122 #define DL_V_S2NR        1                              /* bits  1- 1: (-) not ready flag */
123 #define DL_V_S2BUSY      0                              /* bits  0- 1: (-) drive busy flag */
124 
125 #define DL_S2ERR        (1 << DL_V_S2ERR)
126 #define DL_S2DTYP       (1 << DL_V_S2DTYP)
127 #define DL_S2ATN        (1 << DL_V_S2ATN)
128 #define DL_S2RO         (1 << DL_V_S2RO)
129 #define DL_S2FMT        (1 << DL_V_S2FMT)
130 #define DL_S2FAULT      (1 << DL_V_S2FAULT)
131 #define DL_S2FS         (1 << DL_V_S2FS)
132 #define DL_S2SC         (1 << DL_V_S2SC)
133 #define DL_S2NR         (1 << DL_V_S2NR)
134 #define DL_S2BUSY       (1 << DL_V_S2BUSY)
135 
136 #define DL_S2STOPS      (DL_S2FAULT | DL_S2SC | DL_S2NR)                /* bits that stop drive access */
137 #define DL_S2ERRORS     (DL_S2FAULT | DL_S2SC | DL_S2NR | DL_S2BUSY)    /* bits that set S2ERR */
138 #define DL_S2CPS        (DL_S2ATN | DL_S2FAULT | DL_S2FS | DL_S2SC)     /* bits cleared by Controller Preset */
139 
140 
141 /* Drive properties.
142 
143    The controller library supports four different disc drive models with these
144    properties:
145 
146       Drive  Model  Drive  Sectors   Heads per  Cylinders  Megabytes
147       Model   ID    Type   per Head  Cylinder   per Drive  per Drive
148       -----  -----  -----  --------  ---------  ---------  ---------
149       7905     0      2       48         3         411         15
150       7906     1      0       48         4         411         20
151       7920     2      1       48         5         823         50
152       7925     3      3       64         9         823        120
153 
154    The Drive Type is reported by the controller in the second status word
155    (Status-2) returned by the Request Status command.
156 
157    Model IDs are used in the unit flags to identify the unit's model.  For the
158    autosizing feature to work, models must be assigned ascending IDs in order of
159    ascending drive sizes.
160 */
161 
162 #define D7905_MODEL       0
163 #define D7905_SECTS      48
164 #define D7905_HEADS       3
165 #define D7905_CYLS      411
166 #define D7905_TYPE      (2 << DL_V_S2DTYP)
167 #define D7905_WORDS     (D7905_SECTS * D7905_HEADS * D7905_CYLS * DL_WPSEC)
168 
169 #define D7906_MODEL       1
170 #define D7906_SECTS      48
171 #define D7906_HEADS       4
172 #define D7906_CYLS      411
173 #define D7906_TYPE      (0 << DL_V_S2DTYP)
174 #define D7906_WORDS     (D7906_SECTS * D7906_HEADS * D7906_CYLS * DL_WPSEC)
175 
176 #define D7920_MODEL       2
177 #define D7920_SECTS      48
178 #define D7920_HEADS       5
179 #define D7920_CYLS      823
180 #define D7920_TYPE      (1 << DL_V_S2DTYP)
181 #define D7920_WORDS     (D7920_SECTS * D7920_HEADS * D7920_CYLS * DL_WPSEC)
182 
183 #define D7925_MODEL       3
184 #define D7925_SECTS      64
185 #define D7925_HEADS       9
186 #define D7925_CYLS      823
187 #define D7925_TYPE      (3 << DL_V_S2DTYP)
188 #define D7925_WORDS     (D7925_SECTS * D7925_HEADS * D7925_CYLS * DL_WPSEC)
189 
190 #define MODEL_7905      SET_MODEL (D7905_MODEL)
191 #define MODEL_7906      SET_MODEL (D7906_MODEL)
192 #define MODEL_7920      SET_MODEL (D7920_MODEL)
193 #define MODEL_7925      SET_MODEL (D7925_MODEL)
194 
195 
196 /* Controller types */
197 
198 typedef enum {
199     MAC = 0,
200     ICD,
201     last_type = ICD,                                    /* last valid type */
202     type_count                                          /* count of controller types */
203     } CNTLR_TYPE;
204 
205 
206 /* Controller opcodes */
207 
208 typedef enum {
209     Cold_Load_Read         = 000,
210     Recalibrate            = 001,
211     Seek                   = 002,
212     Request_Status         = 003,
213     Request_Sector_Address = 004,
214     Read                   = 005,
215     Read_Full_Sector       = 006,
216     Verify                 = 007,
217     Write                  = 010,
218     Write_Full_Sector      = 011,
219     Clear                  = 012,
220     Initialize             = 013,
221     Address_Record         = 014,
222     Request_Syndrome       = 015,
223     Read_With_Offset       = 016,
224     Set_File_Mask          = 017,
225     Invalid_Opcode         = 020,
226     Read_Without_Verify    = 022,
227     Load_TIO_Register      = 023,
228     Request_Disc_Address   = 024,
229     End                    = 025,
230     Wakeup                 = 026,
231     Last_Opcode            = Wakeup                     /* last valid opcode */
232     } CNTLR_OPCODE;
233 
234 #define DL_OPCODE_MASK  037
235 
236 
237 /* Controller command phases */
238 
239 typedef enum {
240     start_phase = 0,
241     data_phase,
242     end_phase,
243     last_phase = end_phase                              /* last valid phase */
244     } CNTLR_PHASE;
245 
246 
247 /* Controller status.
248 
249    Not all status values are returned by the library.  The values not currently
250    returned are:
251 
252     - illegal_drive_type
253     - cylinder_miscompare
254     - head_sector_miscompare
255     - io_program_error
256     - sync_timeout
257     - correctable_data_error
258     - illegal_spare_access
259     - defective_track
260     - protected_track
261 */
262 
263 typedef enum {
264     normal_completion        = 000,
265     illegal_opcode           = 001,
266     unit_available           = 002,
267     illegal_drive_type       = 003,
268     cylinder_miscompare      = 007,
269     uncorrectable_data_error = 010,
270     head_sector_miscompare   = 011,
271     io_program_error         = 012,
272     sync_timeout             = 013,
273     end_of_cylinder          = 014,
274     data_overrun             = 016,
275     correctable_data_error   = 017,
276     illegal_spare_access     = 020,
277     defective_track          = 021,
278     access_not_ready         = 022,
279     status_2_error           = 023,
280     protected_track          = 026,
281     unit_unavailable         = 027,
282     drive_attention          = 037
283     } CNTLR_STATUS;
284 
285 
286 /* Controller execution states */
287 
288 typedef enum {
289     cntlr_idle,                                         /* idle */
290     cntlr_wait,                                         /* command wait */
291     cntlr_busy                                          /* busy */
292     } CNTLR_STATE;
293 
294 
295 /* Controller command classifications */
296 
297 typedef enum {
298     class_invalid,                                      /* invalid classification */
299     class_read,                                         /* read classification */
300     class_write,                                        /* write classification */
301     class_control,                                      /* control classification */
302     class_status                                        /* status classification */
303     } CNTLR_CLASS;
304 
305 
306 /* Controller clear types */
307 
308 typedef enum {
309     hard_clear,                                         /* power-on/preset hard clear */
310     soft_clear                                          /* programmed soft clear */
311     } CNTLR_CLEAR;
312 
313 
314 /* Controller state variables */
315 
316 typedef struct {
317     CNTLR_TYPE   type;                                  /* controller type */
318     CNTLR_STATE  state;                                 /* controller state */
319     CNTLR_OPCODE opcode;                                /* controller opcode */
320     CNTLR_STATUS status;                                /* controller status */
321     FLIP_FLOP    eoc;                                   /* end-of-cylinder flag */
322     FLIP_FLOP    eod;                                   /* end-of-data flag */
323     uint32       spd_unit;                              /* S/P/D flags and unit number */
324     uint32       file_mask;                             /* file mask */
325     uint32       retry;                                 /* retry counter */
326     uint32       cylinder;                              /* cylinder address */
327     uint32       head;                                  /* head address */
328     uint32       sector;                                /* sector address */
329     uint32       verify_count;                          /* count of sectors to verify */
330     uint32       poll_unit;                             /* last unit polled for attention */
331     uint16      *buffer;                                /* data buffer pointer */
332     uint32       index;                                 /* data buffer current index */
333     uint32       length;                                /* data buffer valid length */
334     UNIT        *aux;                                   /* MAC auxiliary units (controller and timer) */
335     int32        eot_time;                              /* end-of-track read delay time */
336     int32        seek_time;                             /* per-cylinder seek delay time */
337     int32        sector_time;                           /* intersector delay time */
338     int32        cmd_time;                              /* command response time */
339     int32        data_time;                             /* data transfer response time */
340     int32        wait_time;                             /* command wait time */
341     } CNTLR_VARS;
342 
343 
344 typedef CNTLR_VARS *CVPTR;                              /* pointer to controller state variables */
345 
346 /* Controller state variables initialization.
347 
348    The parameters are:
349 
350      ctype  - type of the controller (CNTLR_TYPE)
351      bufptr - pointer to the data buffer
352      auxptr - pointer to the auxiliary units (MAC only; NULL for ICD)
353 */
354 
355 #define CNTLR_INIT(ctype,bufptr,auxptr) \
356           (ctype), cntlr_idle, End, normal_completion, \
357           CLEAR, CLEAR, \
358           0, 0, 0, 0, 0, 0, 0, 0, \
359           (bufptr), 0, 0, (auxptr), \
360           DL_EOT_TIME, DL_SEEK_TIME, DL_SECTOR_TIME, \
361           DL_CMD_TIME, DL_DATA_TIME, DL_WAIT_TIME
362 
363 
364 
365 /* Disc library global controller routines */
366 
367 extern t_bool  dl_prepare_command    (CVPTR cvptr, UNIT *units, uint32 unit_limit);
368 extern UNIT   *dl_start_command      (CVPTR cvptr, UNIT *units, uint32 unit_limit);
369 extern void    dl_end_command        (CVPTR cvptr, CNTLR_STATUS status);
370 extern t_bool  dl_poll_drives        (CVPTR cvptr, UNIT *units, uint32 unit_limit);
371 extern t_stat  dl_service_drive      (CVPTR cvptr, UNIT *uptr);
372 extern t_stat  dl_service_controller (CVPTR cvptr, UNIT *uptr);
373 extern t_stat  dl_service_timer      (CVPTR cvptr, UNIT *uptr);
374 extern void    dl_idle_controller    (CVPTR cvptr);
375 extern t_stat  dl_clear_controller   (CVPTR cvptr, UNIT *uptr, CNTLR_CLEAR clear_type);
376 extern t_stat  dl_load_unload        (CVPTR cvptr, UNIT *uptr, t_bool load);
377 
378 /* Disc library global utility routines */
379 
380 extern CNTLR_CLASS dl_classify     (CNTLR_VARS  cntlr);
381 extern const char  *dl_opcode_name (CNTLR_TYPE  controller, CNTLR_OPCODE opcode);
382 extern const char  *dl_phase_name  (CNTLR_PHASE phase);
383 
384 /* Disc library global VM routines */
385 
386 extern t_stat dl_attach    (CVPTR cvptr, UNIT  *uptr, char *cptr);
387 extern t_stat dl_detach    (CVPTR cvptr, UNIT  *uptr);
388 extern t_stat dl_set_model (UNIT  *uptr, int32 value, char *cptr, void *desc);
389