Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1 | /* i7094_io.c: IBM 7094 I/O subsystem (channels)
|
| 2 |
|
Bob Supnik | a37e928 | 2017-03-20 07:46:28 -0700 | [diff] [blame] | 3 | Copyright (c) 2003-2017, Robert M. Supnik
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 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 | chana..chanh I/O channels
|
Mark Pizzolato | 6e813b8 | 2012-03-24 19:46:37 -0700 | [diff] [blame] | 27 |
|
Bob Supnik | a37e928 | 2017-03-20 07:46:28 -0700 | [diff] [blame] | 28 | 13-Mar-17 RMS Annotated fall through in switch
|
Mark Pizzolato | 6e813b8 | 2012-03-24 19:46:37 -0700 | [diff] [blame] | 29 | 19-Mar-12 RMS Fixed declaration of breakpoint variables (Mark Pizzolato)
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 30 |
|
| 31 | Notes on channels and CTSS.
|
| 32 |
|
| 33 | - CTSS B-core is supported by the addition of a 16th bit to the current
|
| 34 | address field of the channel command. Both the channel location counter
|
| 35 | and the channel current address register are widened to 16b. Thus,
|
| 36 | channel programs can run in B-core, and channel transfers can access B-core.
|
| 37 | CTSS assumes that a channel command which starts a transfer in B-core
|
| 38 | will not access A-core; the 16th bit does not increment.
|
| 39 | - The channel start commands (RCHx and LCHx) incorporate the A-core/B-core
|
| 40 | select as part of effective address generation. CTSS does not relocate
|
| 41 | RCHx and LCHx target addresses; because the relocation indicator is
|
| 42 | always zero, it's impossible to tell whether the protection indicator
|
| 43 | affects address generation.
|
| 44 | - The CTSS protection RPQ does not cover channel operations. Thus, CTSS
|
| 45 | must inspect and vet all channel programs initiated by user mode programs,
|
| 46 | notably the background processor FMS. CTSS inspects in-progress 7607
|
| 47 | channel programs to make sure than either the nostore bit or the B-core
|
| 48 | bit is set; thus, SCHx must store all 16b of the current address.
|
| 49 | */
|
| 50 |
|
| 51 | #include "i7094_defs.h"
|
| 52 |
|
| 53 | #define CHAMASK ((cpu_model & I_CT)? PAMASK: AMASK) /* chan addr mask */
|
| 54 | #define CHAINC(x) (((x) & ~AMASK) | (((x) + 1) & AMASK))
|
| 55 |
|
| 56 | typedef struct {
|
Mark Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 57 | const char *name;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 58 | uint32 flags;
|
| 59 | } DEV_CHAR;
|
| 60 |
|
| 61 | uint32 ch_sta[NUM_CHAN]; /* channel state */
|
| 62 | uint32 ch_dso[NUM_CHAN]; /* data select op */
|
| 63 | uint32 ch_dsu[NUM_CHAN]; /* data select unit */
|
| 64 | uint32 ch_ndso[NUM_CHAN]; /* non-data select op */
|
| 65 | uint32 ch_ndsu[NUM_CHAN]; /* non-data select unit */
|
| 66 | uint32 ch_flags[NUM_CHAN]; /* flags */
|
| 67 | uint32 ch_clc[NUM_CHAN]; /* chan loc ctr */
|
| 68 | uint32 ch_op[NUM_CHAN]; /* channel op */
|
| 69 | uint32 ch_wc[NUM_CHAN]; /* word count */
|
| 70 | uint32 ch_ca[NUM_CHAN]; /* core address */
|
| 71 | uint32 ch_lcc[NUM_CHAN]; /* control cntr (7909) */
|
| 72 | uint32 ch_cnd[NUM_CHAN]; /* cond reg (7909) */
|
| 73 | uint32 ch_sms[NUM_CHAN]; /* cond mask reg (7909) */
|
| 74 | t_uint64 ch_ar[NUM_CHAN]; /* assembly register */
|
| 75 | uint32 ch_idf[NUM_CHAN]; /* channel input data flags */
|
| 76 | DEVICE *ch2dev[NUM_CHAN] = { NULL };
|
| 77 | uint32 ch_tpoll = 5; /* channel poll */
|
| 78 |
|
| 79 | extern t_uint64 *M;
|
| 80 | extern uint32 cpu_model, data_base;
|
| 81 | extern uint32 hst_ch;
|
| 82 | extern uint32 ch_req;
|
| 83 | extern uint32 chtr_inht, chtr_inhi, chtr_enab;
|
| 84 | extern uint32 ind_ioc;
|
| 85 | extern uint32 chtr_clk;
|
| 86 | extern DEVICE cdr_dev, cdp_dev;
|
| 87 | extern DEVICE lpt_dev;
|
| 88 | extern DEVICE mt_dev[NUM_CHAN];
|
| 89 | extern DEVICE drm_dev;
|
| 90 | extern DEVICE dsk_dev;
|
| 91 | extern DEVICE com_dev;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 92 |
|
| 93 | t_stat ch_reset (DEVICE *dptr);
|
| 94 | t_stat ch6_svc (UNIT *uptr);
|
Mark Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 95 | t_stat ch_set_enable (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
| 96 | t_stat ch_set_disable (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
| 97 | t_stat ch_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 98 | DEVICE *ch_find_dev (uint32 ch, uint32 unit);
|
| 99 | t_stat ch6_sel (uint32 ch, uint32 sel, uint32 unit, uint32 sta);
|
| 100 | t_bool ch6_rd_putw (uint32 ch);
|
| 101 | t_stat ch6_wr_getw (uint32 ch, t_bool eorz);
|
| 102 | t_stat ch6_new_cmd (uint32 ch, t_bool ch_ld);
|
| 103 | t_stat ch6_ioxt (uint32 ch);
|
| 104 | void ch6_iosp_cclr (uint32 ch);
|
| 105 | t_stat ch9_new_cmd (uint32 ch);
|
| 106 | t_stat ch9_exec_cmd (uint32 ch, t_uint64 ir);
|
| 107 | t_stat ch9_sel (uint32 ch, uint32 sel);
|
| 108 | t_stat ch9_wr (uint32 ch, t_uint64 dat, uint32 fl);
|
| 109 | t_stat ch9_rd_putw (uint32 ch);
|
| 110 | t_stat ch9_wr_getw (uint32 ch);
|
| 111 | void ch9_eval_int (uint32 ch, uint32 iflags);
|
| 112 | DEVICE *ch_map_flags (uint32 ch, int32 fl);
|
| 113 |
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 114 | extern t_stat ch_bkpt (uint32 ch, uint32 clc);
|
| 115 |
|
| 116 | const uint32 col_masks[12] = { /* row 9,8,..,0,11,12 */
|
| 117 | 00001, 00002, 00004,
|
| 118 | 00010, 00020, 00040,
|
| 119 | 00100, 00200, 00400,
|
| 120 | 01000, 02000, 04000
|
| 121 | };
|
| 122 |
|
| 123 | const t_uint64 bit_masks[36] = {
|
| 124 | 0000000000001, 0000000000002, 0000000000004,
|
| 125 | 0000000000010, 0000000000020, 0000000000040,
|
| 126 | 0000000000100, 0000000000200, 0000000000400,
|
| 127 | 0000000001000, 0000000002000, 0000000004000,
|
| 128 | 0000000010000, 0000000020000, 0000000040000,
|
| 129 | 0000000100000, 0000000200000, 0000000400000,
|
| 130 | 0000001000000, 0000002000000, 0000004000000,
|
| 131 | 0000010000000, 0000020000000, 0000040000000,
|
| 132 | 0000100000000, 0000200000000, 0000400000000,
|
| 133 | 0001000000000, 0002000000000, 0004000000000,
|
Mark Pizzolato | c93658f | 2013-04-05 12:34:37 -0700 | [diff] [blame] | 134 | INT64_C(0010000000000), INT64_C(0020000000000), INT64_C(0040000000000),
|
| 135 | INT64_C(0100000000000), INT64_C(0200000000000), INT64_C(0400000000000)
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 136 | };
|
| 137 |
|
| 138 | const DEV_CHAR dev_table[] = {
|
| 139 | { "729", 0 },
|
| 140 | { "TAPE", 0 },
|
| 141 | { "7289", DEV_7289 },
|
| 142 | { "DRUM", DEV_7289 },
|
| 143 | { "7631", DEV_7909|DEV_7631 },
|
| 144 | { "FILE", DEV_7909|DEV_7631 },
|
| 145 | { "7750", DEV_7909|DEV_7750 },
|
| 146 | { "COMM", DEV_7909|DEV_7750 },
|
| 147 | { NULL },
|
| 148 | };
|
| 149 |
|
| 150 | const char *sel_name[] = {
|
| 151 | "UNK", "RDS", "WRS", "SNS", "CTL", "FMT", "UNK", "UNK",
|
| 152 | "WEF", "WBT", "BSR", "BSF", "REW", "RUN", "SDN", "UNK"
|
| 153 | };
|
| 154 |
|
| 155 | /* Channel data structures */
|
| 156 |
|
| 157 | UNIT ch_unit[NUM_CHAN] = {
|
| 158 | { UDATA (&ch6_svc, 0, 0) },
|
| 159 | { UDATA (&ch6_svc, 0, 0) },
|
| 160 | { UDATA (&ch6_svc, 0, 0) },
|
| 161 | { UDATA (&ch6_svc, 0, 0) },
|
| 162 | { UDATA (&ch6_svc, 0, 0) },
|
| 163 | { UDATA (&ch6_svc, 0, 0) },
|
| 164 | { UDATA (&ch6_svc, 0, 0) },
|
| 165 | { UDATA (&ch6_svc, 0, 0) }
|
| 166 | };
|
| 167 |
|
| 168 | MTAB ch_mod[] = {
|
| 169 | { MTAB_XTD|MTAB_VDV, 0, "TYPE", NULL,
|
| 170 | NULL, &ch_show_type, NULL },
|
| 171 | { MTAB_XTD|MTAB_VDV, 0, NULL, "ENABLED",
|
| 172 | &ch_set_enable, NULL, NULL },
|
| 173 | { MTAB_XTD|MTAB_VDV, 0, NULL, "DISABLED",
|
| 174 | &ch_set_disable, NULL, NULL },
|
| 175 | { 0 }
|
| 176 | };
|
| 177 |
|
| 178 | REG cha_reg[] = {
|
| 179 | { ORDATA (STA, ch_sta[CH_A], 8) },
|
| 180 | { ORDATA (DSC, ch_dso[CH_A], 4) },
|
| 181 | { ORDATA (DSU, ch_dsu[CH_A], 9) },
|
| 182 | { ORDATA (NDSC, ch_ndso[CH_A], 4) },
|
| 183 | { ORDATA (NDSU, ch_ndsu[CH_A], 9) },
|
| 184 | { ORDATA (FLAGS, ch_flags[CH_A], 30) },
|
| 185 | { ORDATA (IDF, ch_idf[CH_A], 2) },
|
| 186 | { ORDATA (OP, ch_op[CH_A], 5) },
|
| 187 | { ORDATA (CLC, ch_clc[CH_A], 16) },
|
| 188 | { ORDATA (WC, ch_wc[CH_A], 15) },
|
| 189 | { ORDATA (CA, ch_ca[CH_A], 16) },
|
| 190 | { ORDATA (AR, ch_ar[CH_A], 36) },
|
| 191 | { ORDATA (CND, ch_cnd[CH_A], 6), REG_HRO },
|
| 192 | { ORDATA (LCC, ch_lcc[CH_A], 6), REG_HRO },
|
| 193 | { ORDATA (SMS, ch_sms[CH_A], 7), REG_HRO },
|
| 194 | { 0 }
|
| 195 | };
|
| 196 |
|
| 197 | REG chb_reg[] = {
|
| 198 | { ORDATA (STATE, ch_sta[CH_B], 8) },
|
| 199 | { ORDATA (DSC, ch_dso[CH_B], 4) },
|
| 200 | { ORDATA (DSU, ch_dsu[CH_B], 9) },
|
| 201 | { ORDATA (NDSC, ch_ndso[CH_B], 4) },
|
| 202 | { ORDATA (NDSU, ch_ndsu[CH_B], 9) },
|
| 203 | { ORDATA (FLAGS, ch_flags[CH_B], 30) },
|
| 204 | { ORDATA (IDF, ch_idf[CH_B], 2) },
|
| 205 | { ORDATA (OP, ch_op[CH_B], 5) },
|
| 206 | { ORDATA (CLC, ch_clc[CH_B], 16) },
|
| 207 | { ORDATA (WC, ch_wc[CH_B], 15) },
|
| 208 | { ORDATA (CA, ch_ca[CH_B], 16) },
|
| 209 | { ORDATA (AR, ch_ar[CH_B], 36) },
|
| 210 | { ORDATA (CND, ch_cnd[CH_B], 6) },
|
| 211 | { ORDATA (LCC, ch_lcc[CH_B], 6) },
|
| 212 | { ORDATA (SMS, ch_sms[CH_B], 7) },
|
| 213 | { 0 }
|
| 214 | };
|
| 215 |
|
| 216 | REG chc_reg[] = {
|
| 217 | { ORDATA (STATE, ch_sta[CH_C], 8) },
|
| 218 | { ORDATA (DSC, ch_dso[CH_C], 4) },
|
| 219 | { ORDATA (DSU, ch_dsu[CH_C], 9) },
|
| 220 | { ORDATA (NDSC, ch_ndso[CH_C], 4) },
|
| 221 | { ORDATA (NDSU, ch_ndsu[CH_C], 9) },
|
| 222 | { ORDATA (FLAGS, ch_flags[CH_C], 30) },
|
| 223 | { ORDATA (IDF, ch_idf[CH_C], 2) },
|
| 224 | { ORDATA (OP, ch_op[CH_C], 5) },
|
| 225 | { ORDATA (CLC, ch_clc[CH_C], 16) },
|
| 226 | { ORDATA (WC, ch_wc[CH_C], 15) },
|
| 227 | { ORDATA (CA, ch_ca[CH_C], 16) },
|
| 228 | { ORDATA (AR, ch_ar[CH_C], 36) },
|
| 229 | { ORDATA (CND, ch_cnd[CH_C], 6) },
|
| 230 | { ORDATA (LCC, ch_lcc[CH_C], 6) },
|
| 231 | { ORDATA (SMS, ch_sms[CH_C], 7) },
|
| 232 | { 0 }
|
| 233 | };
|
| 234 |
|
| 235 | REG chd_reg[] = {
|
| 236 | { ORDATA (STATE, ch_sta[CH_D], 8) },
|
| 237 | { ORDATA (DSC, ch_dso[CH_D], 4) },
|
| 238 | { ORDATA (DSU, ch_dsu[CH_D], 9) },
|
| 239 | { ORDATA (NDSC, ch_ndso[CH_D], 4) },
|
| 240 | { ORDATA (NDSU, ch_ndsu[CH_D], 9) },
|
| 241 | { ORDATA (FLAGS, ch_flags[CH_D], 30) },
|
| 242 | { ORDATA (IDF, ch_idf[CH_D], 2) },
|
| 243 | { ORDATA (OP, ch_op[CH_D], 5) },
|
| 244 | { ORDATA (CLC, ch_clc[CH_D], 16) },
|
| 245 | { ORDATA (WC, ch_wc[CH_D], 15) },
|
| 246 | { ORDATA (CA, ch_ca[CH_D], 16) },
|
| 247 | { ORDATA (AR, ch_ar[CH_D], 36) },
|
| 248 | { ORDATA (CND, ch_cnd[CH_D], 6) },
|
| 249 | { ORDATA (LCC, ch_lcc[CH_D], 6) },
|
| 250 | { ORDATA (SMS, ch_sms[CH_D], 7) },
|
| 251 | { 0 }
|
| 252 | };
|
| 253 |
|
| 254 | REG che_reg[] = {
|
| 255 | { ORDATA (STATE, ch_sta[CH_E], 8) },
|
| 256 | { ORDATA (DSC, ch_dso[CH_E], 4) },
|
| 257 | { ORDATA (DSU, ch_dsu[CH_E], 9) },
|
| 258 | { ORDATA (NDSC, ch_ndso[CH_E], 4) },
|
| 259 | { ORDATA (NDSU, ch_ndsu[CH_E], 9) },
|
| 260 | { ORDATA (FLAGS, ch_flags[CH_E], 30) },
|
| 261 | { ORDATA (IDF, ch_idf[CH_E], 2) },
|
| 262 | { ORDATA (OP, ch_op[CH_E], 5) },
|
| 263 | { ORDATA (CLC, ch_clc[CH_E], 16) },
|
| 264 | { ORDATA (WC, ch_wc[CH_E], 15) },
|
| 265 | { ORDATA (CA, ch_ca[CH_E], 16) },
|
| 266 | { ORDATA (AR, ch_ar[CH_E], 36) },
|
| 267 | { ORDATA (CND, ch_cnd[CH_E], 6) },
|
| 268 | { ORDATA (LCC, ch_lcc[CH_E], 6) },
|
| 269 | { ORDATA (SMS, ch_sms[CH_E], 7) },
|
| 270 | { 0 }
|
| 271 | };
|
| 272 |
|
| 273 | REG chf_reg[] = {
|
| 274 | { ORDATA (STATE, ch_sta[CH_F], 8) },
|
| 275 | { ORDATA (DSC, ch_dso[CH_F], 4) },
|
| 276 | { ORDATA (DSU, ch_dsu[CH_F], 9) },
|
| 277 | { ORDATA (NDSC, ch_ndso[CH_F], 4) },
|
| 278 | { ORDATA (NDSU, ch_ndsu[CH_F], 9) },
|
| 279 | { ORDATA (FLAGS, ch_flags[CH_F], 30) },
|
| 280 | { ORDATA (IDF, ch_idf[CH_F], 2) },
|
| 281 | { ORDATA (OP, ch_op[CH_F], 5) },
|
| 282 | { ORDATA (CLC, ch_clc[CH_F], 16) },
|
| 283 | { ORDATA (WC, ch_wc[CH_F], 15) },
|
| 284 | { ORDATA (CA, ch_ca[CH_F], 16) },
|
| 285 | { ORDATA (AR, ch_ar[CH_F], 36) },
|
| 286 | { ORDATA (CND, ch_cnd[CH_F], 6) },
|
| 287 | { ORDATA (LCC, ch_lcc[CH_F], 6) },
|
| 288 | { ORDATA (SMS, ch_sms[CH_F], 7) },
|
| 289 | { 0 }
|
| 290 | };
|
| 291 |
|
| 292 | REG chg_reg[] = {
|
| 293 | { ORDATA (STATE, ch_sta[CH_G], 8) },
|
| 294 | { ORDATA (DSC, ch_dso[CH_G], 4) },
|
| 295 | { ORDATA (DSU, ch_dsu[CH_G], 9) },
|
| 296 | { ORDATA (NDSC, ch_ndso[CH_G], 4) },
|
| 297 | { ORDATA (NDSU, ch_ndsu[CH_G], 9) },
|
| 298 | { ORDATA (FLAGS, ch_flags[CH_G], 30) },
|
| 299 | { ORDATA (IDF, ch_idf[CH_G], 2) },
|
| 300 | { ORDATA (OP, ch_op[CH_G], 5) },
|
| 301 | { ORDATA (CLC, ch_clc[CH_G], 16) },
|
| 302 | { ORDATA (WC, ch_wc[CH_G], 15) },
|
| 303 | { ORDATA (CA, ch_ca[CH_G], 16) },
|
| 304 | { ORDATA (AR, ch_ar[CH_G], 36) },
|
| 305 | { ORDATA (CND, ch_cnd[CH_G], 6) },
|
| 306 | { ORDATA (LCC, ch_lcc[CH_G], 6) },
|
| 307 | { ORDATA (SMS, ch_sms[CH_G], 7) },
|
| 308 | { 0 }
|
| 309 | };
|
| 310 |
|
| 311 | REG chh_reg[] = {
|
| 312 | { ORDATA (STATE, ch_sta[CH_H], 8) },
|
| 313 | { ORDATA (DSC, ch_dso[CH_H], 4) },
|
| 314 | { ORDATA (DSU, ch_dsu[CH_H], 9) },
|
| 315 | { ORDATA (NDSC, ch_ndso[CH_H], 4) },
|
| 316 | { ORDATA (NDSU, ch_ndsu[CH_H],9) },
|
| 317 | { ORDATA (FLAGS, ch_flags[CH_H], 30) },
|
| 318 | { ORDATA (IDF, ch_idf[CH_H], 2) },
|
| 319 | { ORDATA (OP, ch_op[CH_H], 5) },
|
| 320 | { ORDATA (CLC, ch_clc[CH_H], 16) },
|
| 321 | { ORDATA (WC, ch_wc[CH_H], 15) },
|
| 322 | { ORDATA (CA, ch_ca[CH_H], 16) },
|
| 323 | { ORDATA (AR, ch_ar[CH_H], 36) },
|
| 324 | { ORDATA (CND, ch_cnd[CH_H], 6) },
|
| 325 | { ORDATA (LCC, ch_lcc[CH_H], 6) },
|
| 326 | { ORDATA (SMS, ch_sms[CH_H], 7) },
|
| 327 | { 0 }
|
| 328 | };
|
| 329 |
|
| 330 | DEVICE ch_dev[NUM_CHAN] = {
|
| 331 | {
|
| 332 | "CHANA", &ch_unit[CH_A], cha_reg, ch_mod,
|
| 333 | 1, 8, 8, 1, 8, 8,
|
| 334 | NULL, NULL, &ch_reset,
|
| 335 | NULL, NULL, NULL,
|
| 336 | NULL, 0
|
| 337 | },
|
| 338 | {
|
| 339 | "CHANB", &ch_unit[CH_B], chb_reg, ch_mod,
|
| 340 | 1, 8, 8, 1, 8, 8,
|
| 341 | NULL, NULL, &ch_reset,
|
| 342 | NULL, NULL, NULL,
|
| 343 | NULL, DEV_DISABLE | DEV_DIS
|
| 344 | },
|
| 345 | {
|
| 346 | "CHANC", &ch_unit[CH_C], chc_reg, ch_mod,
|
| 347 | 1, 8, 8, 1, 8, 8,
|
| 348 | NULL, NULL, &ch_reset,
|
| 349 | NULL, NULL, NULL,
|
| 350 | NULL, DEV_DISABLE | DEV_DIS
|
| 351 | },
|
| 352 | {
|
| 353 | "CHAND", &ch_unit[CH_D], chd_reg, ch_mod,
|
| 354 | 1, 8, 8, 1, 8, 8,
|
| 355 | NULL, NULL, &ch_reset,
|
| 356 | NULL, NULL, NULL,
|
| 357 | NULL, DEV_DISABLE | DEV_DIS
|
| 358 | },
|
| 359 | {
|
| 360 | "CHANE", &ch_unit[CH_E], che_reg, ch_mod,
|
| 361 | 1, 8, 8, 1, 8, 8,
|
| 362 | NULL, NULL, &ch_reset,
|
| 363 | NULL, NULL, NULL,
|
| 364 | NULL, DEV_DISABLE | DEV_DIS
|
| 365 | },
|
| 366 | {
|
| 367 | "CHANF", &ch_unit[CH_F], chf_reg, ch_mod,
|
| 368 | 1, 8, 8, 1, 8, 8,
|
| 369 | NULL, NULL, &ch_reset,
|
| 370 | NULL, NULL, NULL,
|
| 371 | NULL, DEV_DISABLE | DEV_DIS
|
| 372 | },
|
| 373 | {
|
| 374 | "CHANG", &ch_unit[CH_G], chg_reg, ch_mod,
|
| 375 | 1, 8, 8, 1, 8, 8,
|
| 376 | NULL, NULL, &ch_reset,
|
| 377 | NULL, NULL, NULL,
|
| 378 | NULL, DEV_DISABLE | DEV_DIS
|
| 379 | },
|
| 380 | {
|
| 381 | "CHANH", &ch_unit[CH_H], chh_reg, ch_mod,
|
| 382 | 1, 8, 8, 1, 8, 8,
|
| 383 | NULL, NULL, &ch_reset,
|
| 384 | NULL, NULL, NULL,
|
| 385 | NULL, DEV_DISABLE | DEV_DIS
|
| 386 | }
|
| 387 | };
|
| 388 |
|
| 389 | /* 7607 channel overview
|
| 390 |
|
| 391 | Channel variables:
|
| 392 |
|
| 393 | ch_sta channel state
|
| 394 | ch_dso, ch_dsu operation and unit for current data select
|
| 395 | ch_ndso, ch_ndsu operation and unit for current non-data select
|
| 396 | ch_clc current location counter
|
| 397 | ch_ca memory addres
|
| 398 | ch_wc word count
|
| 399 | ch_op channel opcode (bits <S,1:2,19>)
|
| 400 | ch_flags channel flags
|
| 401 |
|
| 402 | States of a channel
|
| 403 |
|
| 404 | IDLE - channel is not in operation
|
| 405 |
|
| 406 | RDS, WDS: -> DSW if device is idle, schedule device
|
| 407 | device timeout drives next transition
|
| 408 | -> stall if device is busy
|
| 409 | repeat until device is idle
|
| 410 | other I/O: -> NDS if device is idle, schedule device
|
| 411 | device timeout drives next transition
|
| 412 | -> stall if device is busy
|
| 413 | repeat until device is idle
|
| 414 | chan reset: -> IDLE
|
| 415 |
|
| 416 | PDS (PNDS) - channel is polling device to start data (non-data) select
|
| 417 |
|
| 418 | chan timeout: -> DSW (NDS) if device is idle
|
| 419 | device timeout drives next transition
|
| 420 | -> no change if device is busy, schedule channel
|
| 421 | chan reset: -> IDLE
|
| 422 |
|
| 423 | DSW - channel is waiting for channel start command
|
| 424 |
|
| 425 | dev timeout: -> IDLE if no stacked non-data select
|
| 426 | -> PNDS if stacked non-data select
|
| 427 | channel timeout drives next transition
|
| 428 | start chan: -> DSX if chan program transfers data
|
| 429 | device timeout drives next transition
|
| 430 | -> IDLE if channel disconnects, no stacked NDS
|
| 431 | -> PNDS if channel disconnects, stacked NDS
|
| 432 | channel timeout drives next transition
|
| 433 | chan reset: -> IDLE
|
| 434 |
|
| 435 | DSX - channel is executing data select
|
| 436 |
|
| 437 | dev timeout: -> DSX if transfer not complete, reschedule device
|
| 438 | device timeout drives next transition
|
| 439 | -> DSW if channel command completes, CHF_LDW set
|
| 440 | -> IDLE if transfer complete, no stacked NDS, or
|
| 441 | if channel command completes, CHF_LDW clear
|
| 442 | -> PNDS if channel disconnects, stacked NDS
|
| 443 | channel timeout drives next transition
|
| 444 | start chan: -> DSX with CHF_LDW, CPU stall
|
| 445 | chan reset: -> IDLE
|
| 446 |
|
| 447 | NDS - channel is executing non-data select
|
| 448 |
|
| 449 | dev timeout: -> IDLE if transfer complete, no stacked DS
|
| 450 | -> PDS if channel disconnects, stacked DS
|
| 451 | channel timeout drives next transition
|
| 452 | chan reset: -> IDLE
|
| 453 |
|
| 454 | The channel has two interfaces to a device. The select routine:
|
| 455 |
|
| 456 | dev_select (uint32 ch, uint32 sel, uint32 unit)
|
| 457 |
|
| 458 | Returns can include device errors and ERR_STALL. If ERR_STALL, the
|
| 459 | device is busy. For I/O instructions, ERR_STALL stalls execution of
|
| 460 | the instruction until the device is not busy. For stacked command
|
| 461 | polls, ERR_STALL causes the poll to be repeated after a delay.
|
| 462 |
|
| 463 | The device write routine is used to place output data in the device
|
| 464 | write buffer.
|
| 465 |
|
| 466 | Channel transfers are driven by the channel. When a device needs to
|
| 467 | read or write data, it sets a channel request in ch_req. The channel
|
| 468 | process transfers the data and updates channel control parameters
|
| 469 | accordingly. Note that the channel may disconnect; in this case, the
|
| 470 | transfer completes 'correctly' from the point of view of the device.
|
| 471 |
|
| 472 | The channel transfer commands (IOxT) require the channel to 'hold'
|
| 473 | a new channel command in anticipation of the current transfer. If
|
| 474 | the channel is currently executing (CH6S_DSX) and a channel start
|
| 475 | is issued by the CPU, a 'start pending' flag is set and the CPU is
|
| 476 | stalled. When the channel reaches the end of an IOxT command, it
|
| 477 | checks the 'start pending' flag. If the flag is set, the channel
|
| 478 | sets itself to waiting and then requeues itself for one cycle later.
|
| 479 | The CPU tries the channel start, sees that the channel is waiting,
|
| 480 | and issues the new channel command.
|
| 481 |
|
| 482 | state op device channel
|
| 483 |
|
| 484 | IDLE RDS,WDS start I/O ->DSW
|
| 485 |
|
| 486 | DSW LCHx (timed wait) ->DSX
|
| 487 |
|
| 488 | DSX -- timeout, req svc
|
| 489 | (timed wait) transfer word
|
| 490 | timeout, req svc
|
| 491 | (timed wait)
|
| 492 | LCHx, stalls :
|
| 493 | timeout, EOR/EOC IOxT: ->DSW, resched
|
| 494 | DSW LCHx (timed wait) ->DSX, etc
|
| 495 |
|
| 496 | 7909 channel overview
|
| 497 |
|
| 498 | Channel variables:
|
| 499 |
|
| 500 | ch_sta channel state
|
| 501 | ch_clc current location counter
|
| 502 | ch_ca memory addres
|
| 503 | ch_wc word count
|
| 504 | ch_op channel opcode (bits <S,1:3,19>)
|
| 505 | ch_sms status mask
|
| 506 | ch_cond interrupt conditions
|
| 507 | ch_lcc control counter
|
| 508 | ch_flags channel flags
|
| 509 |
|
| 510 | States of a channel
|
| 511 |
|
| 512 | IDLE - channel is not in operation
|
| 513 |
|
| 514 | RDCx, SDCx, interrupt -> DSX
|
| 515 |
|
| 516 | DSX - channel is executing data select
|
| 517 |
|
| 518 | TWT, WTR -> IDLE
|
| 519 |
|
| 520 | The 7909 is more capable than the 7607 but also simpler in some ways.
|
| 521 | It has many more instructions, built in counters and status checking,
|
| 522 | and interrupts. But it has only two states and no concept of records.
|
| 523 |
|
| 524 | The 7909 read process is driven by the device:
|
| 525 |
|
| 526 | channel CTLR/SNS: send select
|
| 527 | device: schedule timeout
|
| 528 | device timeout: device to AR, request channel
|
| 529 | channel: AR to memory
|
| 530 | device timeout: device to AR, request channel
|
| 531 | channel: AR to memory
|
| 532 | :
|
| 533 | device timeout: set end, request channel
|
| 534 | channel: disconnect on CPYD, send STOP
|
| 535 |
|
| 536 | The 7909 write process is also driven by the device:
|
| 537 |
|
| 538 | channel CTL/CTLW: send select
|
| 539 | device: schedule timeout, request channel
|
| 540 | channel: memory to output buffer
|
| 541 | device timeout: output buffer to device, request channel
|
| 542 | channel: memory to output buffer
|
| 543 | device timeout: output buffer to device, request channel
|
| 544 | :
|
| 545 | channel: memory to output buffer
|
| 546 | device timeout: output buffer to device, set end, request channel
|
| 547 | channel: disconnect on CPYD, send STOP
|
| 548 |
|
| 549 | For both reads and writes, devices must implement an 'interblock' or
|
| 550 | 'interrecord' state that is long enough for the channel to see the
|
| 551 | end, disconnect, and send a stop signal.
|
| 552 | */
|
| 553 |
|
| 554 | /* Data select - called by RDS or WDS instructions - 7607/7289 only
|
| 555 |
|
| 556 | - Channel is from address and has been corrected
|
| 557 | - Channel must be an enabled 7607
|
| 558 | - If data select already in use, stall CPU
|
| 559 | - If non-data select is a write end-of-file, stall CPU
|
| 560 | - If channel is busy, stack command
|
| 561 | - Otherwise, start IO, set channel to waiting */
|
| 562 |
|
| 563 | t_stat ch_op_ds (uint32 ch, uint32 ds, uint32 unit)
|
| 564 | {
|
| 565 | t_stat r;
|
| 566 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 567 | if (ch >= NUM_CHAN) /* invalid arg? */
|
| 568 | return STOP_NXCHN;
|
| 569 | if (ch_dev[ch].flags & DEV_DIS) /* disabled? stop */
|
| 570 | return STOP_NXCHN;
|
| 571 | if (ch_dev[ch].flags & DEV_7909) /* 7909? stop */
|
| 572 | return STOP_7909;
|
| 573 | if (ch_dso[ch]) /* DS in use? */
|
| 574 | return ERR_STALL;
|
| 575 | if (ch_ndso[ch] == CHSL_WEF) /* NDS = WEF? */
|
| 576 | return ERR_STALL;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 577 | if (ch_sta[ch] == CHXS_IDLE) { /* chan idle? */
|
| 578 | r = ch6_sel (ch, ds, unit, CH6S_DSW); /* select device */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 579 | if (r != SCPE_OK)
|
| 580 | return r;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 581 | }
|
| 582 | ch_dso[ch] = ds; /* set command, unit */
|
| 583 | ch_dsu[ch] = unit;
|
| 584 | ch_flags[ch] &= ~(CHF_LDW|CHF_EOR|CHF_CMD); /* clear flags */
|
| 585 | ch_idf[ch] = 0;
|
| 586 | return SCPE_OK;
|
| 587 | }
|
| 588 |
|
| 589 | /* Non-data select - called by BSR, BSF, WEF, REW, RUN, SDS instructions - 7607 only
|
| 590 |
|
| 591 | - Channel is from address and has been corrected
|
| 592 | - Channel must be an enabled 7607
|
| 593 | - If non-data select already in use, stall CPU
|
| 594 | - If data select is card or printer, stall CPU
|
| 595 | - If channel is busy, stack command
|
| 596 | - Otherwise, start IO, set channel to waiting */
|
| 597 |
|
| 598 | t_stat ch_op_nds (uint32 ch, uint32 nds, uint32 unit)
|
| 599 | {
|
| 600 | DEVICE *dptr;
|
| 601 | t_stat r;
|
| 602 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 603 | if (ch >= NUM_CHAN) /* invalid arg? */
|
| 604 | return STOP_NXCHN;
|
| 605 | if (ch_dev[ch].flags & DEV_DIS) /* disabled? stop */
|
| 606 | return STOP_NXCHN;
|
| 607 | if (ch_dev[ch].flags & DEV_7909) /* 7909? stop */
|
| 608 | return STOP_7909;
|
| 609 | if (ch_ndso[ch]) /* NDS in use? */
|
| 610 | return ERR_STALL;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 611 | if (ch_dso[ch] && (dptr = ch_find_dev (ch, ch_dsu[ch])) /* DS, cd or lpt? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 612 | && (dptr->flags & DEV_CDLP))
|
| 613 | return ERR_STALL;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 614 | if (ch_sta[ch] == CHXS_IDLE) { /* chan idle? */
|
| 615 | r = ch6_sel (ch, nds, unit, CH6S_NDS); /* select device */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 616 | if (r != SCPE_OK)
|
| 617 | return r;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 618 | }
|
| 619 | ch_ndso[ch] = nds; /* set command, unit */
|
| 620 | ch_ndsu[ch] = unit;
|
| 621 | return SCPE_OK;
|
| 622 | }
|
| 623 |
|
| 624 | /* End of data select - called from channel - 7607/7289 only
|
| 625 |
|
| 626 | - If executing, set command trap flag
|
| 627 | - Set channel idle
|
| 628 | - If stacked nds, set up immediate channel timeout */
|
| 629 |
|
| 630 | t_stat ch6_end_ds (uint32 ch)
|
| 631 | {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 632 | if (ch >= NUM_CHAN) /* invalid arg? */
|
| 633 | return STOP_NXCHN;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 634 | ch_dso[ch] = ch_dsu[ch] = 0; /* no data select */
|
| 635 | if (ch_ndso[ch]) { /* stacked non-data sel? */
|
| 636 | sim_activate (ch_dev[ch].units, 0); /* immediate poll */
|
| 637 | ch_sta[ch] = CH6S_PNDS; /* state = polling */
|
| 638 | }
|
| 639 | else ch_sta[ch] = CHXS_IDLE; /* else state = idle */
|
| 640 | return SCPE_OK;
|
| 641 | }
|
| 642 |
|
| 643 | /* End of non-data select - called from I/O device completion - 7607/7289 only
|
| 644 |
|
| 645 | - Set channel idle
|
| 646 | - If stacked ds, set up immediate channel timeout */
|
| 647 |
|
| 648 | t_stat ch6_end_nds (uint32 ch)
|
| 649 | {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 650 | if (ch >= NUM_CHAN) /* invalid arg? */
|
| 651 | return STOP_NXCHN;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 652 | ch_ndso[ch] = ch_ndsu[ch] = 0; /* no non-data select */
|
| 653 | if (ch_dso[ch]) { /* stacked data sel? */
|
| 654 | sim_activate (ch_dev[ch].units, 0); /* immediate poll */
|
| 655 | ch_sta[ch] = CH6S_PDS; /* state = polling */
|
| 656 | }
|
| 657 | else ch_sta[ch] = CHXS_IDLE; /* else state = idle */
|
| 658 | return SCPE_OK;
|
| 659 | }
|
| 660 |
|
| 661 | /* Send select to device - 7607/7289 only */
|
| 662 |
|
| 663 | t_stat ch6_sel (uint32 ch, uint32 sel, uint32 unit, uint32 sta)
|
| 664 | {
|
| 665 | DEVICE *dptr;
|
| 666 | DIB *dibp;
|
| 667 | t_stat r;
|
| 668 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 669 | if (ch >= NUM_CHAN) /* invalid arg? */
|
| 670 | return STOP_NXCHN;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 671 | dptr = ch_find_dev (ch, unit); /* find device */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 672 | if (dptr == NULL) /* invalid device? */
|
| 673 | return STOP_NXDEV;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 674 | dibp = (DIB *) dptr->ctxt;
|
| 675 | r = dibp->chsel (ch, sel, unit); /* select device */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 676 | if (r == SCPE_OK) /* set status */
|
| 677 | ch_sta[ch] = sta;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 678 | return r;
|
| 679 | }
|
| 680 |
|
| 681 | /* Channel unit service - called to start stacked command - 7607 only */
|
| 682 |
|
| 683 | t_stat ch6_svc (UNIT *uptr)
|
| 684 | {
|
| 685 | uint32 ch = uptr - &ch_unit[0]; /* get channel */
|
| 686 | t_stat r;
|
| 687 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 688 | if (ch >= NUM_CHAN) /* invalid chan? */
|
| 689 | return SCPE_IERR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 690 | switch (ch_sta[ch]) { /* case on state */
|
| 691 |
|
| 692 | case CH6S_PDS: /* polling for ds */
|
| 693 | r = ch6_sel (ch, ch_dso[ch], ch_dsu[ch], CH6S_DSW);
|
| 694 | break;
|
| 695 |
|
| 696 | case CH6S_PNDS: /* polling for nds */
|
| 697 | r = ch6_sel (ch, ch_ndso[ch], ch_ndsu[ch], CH6S_NDS);
|
| 698 | break;
|
| 699 |
|
| 700 | default:
|
| 701 | return SCPE_OK;
|
| 702 | }
|
| 703 |
|
| 704 | if (r == ERR_STALL) { /* stalled? */
|
| 705 | sim_activate (uptr, ch_tpoll); /* continue poll */
|
| 706 | return SCPE_OK;
|
| 707 | }
|
| 708 | return r;
|
| 709 | }
|
| 710 |
|
| 711 | /* Map channel and unit number to device - all channels */
|
| 712 |
|
| 713 | DEVICE *ch_find_dev (uint32 ch, uint32 unit)
|
| 714 | {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 715 | if (ch >= NUM_CHAN) /* invalid arg? */
|
| 716 | return NULL;
|
| 717 | if (ch_dev[ch].flags & (DEV_7909|DEV_7289))
|
| 718 | return ch2dev[ch];
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 719 | unit = unit & 0777;
|
| 720 | if (((unit >= U_MTBCD) && (unit <= (U_MTBCD + MT_NUMDR))) ||
|
| 721 | ((unit >= U_MTBIN) && (unit <= (U_MTBIN + MT_NUMDR))))
|
| 722 | return ch2dev[ch];
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 723 | if (ch != 0)
|
| 724 | return NULL;
|
| 725 | if (unit == U_CDR)
|
| 726 | return &cdr_dev;
|
| 727 | if (unit == U_CDP)
|
| 728 | return &cdp_dev;
|
| 729 | if ((unit == U_LPBCD) || (unit == U_LPBIN))
|
| 730 | return &lpt_dev;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 731 | return NULL;
|
| 732 | }
|
| 733 |
|
| 734 | /* Start channel - channel is from opcode
|
| 735 |
|
| 736 | 7607: channel should have a data select operation pending (DSW state)
|
| 737 | 7909: channel should be idle (IDLE state) */
|
| 738 |
|
| 739 | t_stat ch_op_start (uint32 ch, uint32 clc, t_bool reset)
|
| 740 | {
|
| 741 | t_uint64 ir;
|
| 742 | t_stat r;
|
| 743 |
|
| 744 | clc = clc | data_base; /* add A/B select */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 745 | if (ch >= NUM_CHAN) /* invalid argument? */
|
| 746 | return STOP_NXCHN;
|
| 747 | if (ch_dev[ch].flags & DEV_DIS) /* disabled? stop */
|
| 748 | return STOP_NXCHN;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 749 | if (ch_dev[ch].flags & DEV_7909) { /* 7909? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 750 | if (ch_sta[ch] != CHXS_IDLE) /* must be idle */
|
| 751 | return ERR_STALL;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 752 | if (reset) { /* RDCx? */
|
| 753 | ch_cnd[ch] = 0; /* clear conditions */
|
| 754 | ch_clc[ch] = clc; /* set clc */
|
| 755 | }
|
| 756 | else { /* SDCx */
|
| 757 | if (BIT_TST (chtr_enab, CHTR_V_TWT + ch) && /* pending trap? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 758 | (ch_flags[ch] & CHF_TWT))
|
| 759 | return ERR_STALL;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 760 | ch_clc[ch] = ch_ca[ch] & CHAMASK; /* finish WTR, TWT */
|
| 761 | }
|
| 762 | ch_flags[ch] &= ~CHF_CLR_7909; /* clear flags, not IP */
|
| 763 | ch_idf[ch] = 0;
|
| 764 | ch_sta[ch] = CHXS_DSX; /* set state */
|
| 765 | return ch9_new_cmd (ch); /* start executing */
|
| 766 | }
|
| 767 | /* 7607, 7289 */
|
| 768 | if (reset) { /* reset? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 769 | if (ch_sta[ch] == CHXS_DSX)
|
| 770 | ch_sta[ch] = CH6S_DSW;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 771 | ch_flags[ch] &= ~(CHF_LDW|CHF_EOR|CHF_TRC|CHF_CMD);
|
| 772 | ch_idf[ch] = 0;
|
| 773 | }
|
| 774 |
|
| 775 | switch (ch_sta[ch]) { /* case on chan state */
|
| 776 |
|
| 777 | case CHXS_IDLE: /* idle */
|
| 778 | ind_ioc = 1; /* IO check */
|
| 779 | ir = ReadP (clc); /* get chan word */
|
| 780 | ch_clc[ch] = CHAINC (clc); /* incr chan pc */
|
| 781 | ch_wc[ch] = GET_DEC (ir); /* get word cnt */
|
| 782 | ch_ca[ch] = ((uint32) ir) & CHAMASK; /* get address */
|
| 783 | ch_op[ch] = (GET_OPD (ir) << 1) | /* get opcode */
|
| 784 | ((((uint32) ir) & CH6I_NST)? 1: 0); /* plus 'no store' */
|
| 785 | break;
|
| 786 |
|
| 787 | case CH6S_PNDS: /* NDS polling */
|
| 788 | case CH6S_PDS: /* DS polling */
|
| 789 | case CH6S_NDS: /* NDS executing */
|
| 790 | return ERR_STALL; /* wait it out */
|
| 791 |
|
| 792 | case CH6S_DSW: /* expecting command */
|
| 793 | ch_sta[ch] = CHXS_DSX; /* update state */
|
| 794 | if (ch_dev[ch].flags & DEV_7289) { /* drum channel? */
|
| 795 | ir = ReadP (clc); /* read addr */
|
| 796 | ch_clc[ch] = CHAINC (clc); /* incr chan pc */
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 797 | if ((r = ch9_wr (ch, ir, 0))) /* write to dev */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 798 | return r;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 799 | }
|
| 800 | else ch_clc[ch] = clc; /* set clc */
|
| 801 | return ch6_new_cmd (ch, TRUE); /* start channel */
|
| 802 |
|
| 803 | case CHXS_DSX: /* executing */
|
| 804 | ch_flags[ch] = ch_flags[ch] | CHF_LDW; /* flag pending LCH */
|
| 805 | return ERR_STALL; /* stall */
|
| 806 | }
|
| 807 |
|
| 808 | return SCPE_OK;
|
| 809 | }
|
| 810 |
|
| 811 | /* Store channel
|
| 812 |
|
| 813 | 7607/7289 stores op,ca,nostore,clc
|
| 814 | 7909 stores clc,,ca */
|
| 815 |
|
| 816 | t_stat ch_op_store (uint32 ch, t_uint64 *dat)
|
| 817 | {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 818 | if ((ch >= NUM_CHAN) || (ch_dev[ch].flags & DEV_DIS))
|
| 819 | return STOP_NXCHN;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 820 | if (ch_dev[ch].flags & DEV_7909)
|
| 821 | *dat = (((t_uint64) ch_ca[ch] & CHAMASK) << INST_V_DEC) |
|
| 822 | (((t_uint64) ch_clc[ch] & CHAMASK) << INST_V_ADDR);
|
| 823 | else *dat = (((t_uint64) ch_clc[ch] & CHAMASK) << INST_V_DEC) |
|
| 824 | (((t_uint64) ch_ca[ch] & CHAMASK) << INST_V_ADDR) |
|
| 825 | (((t_uint64) (ch_op[ch] & 1)) << 16) |
|
| 826 | (((t_uint64) (ch_op[ch] & 016)) << 32);
|
| 827 | return SCPE_OK;
|
| 828 | }
|
| 829 |
|
| 830 | /* Store channel diagnostic
|
| 831 |
|
| 832 | 7607 is undefined
|
| 833 | 7289 stores IOC+???
|
| 834 | 7909 stores 7909 lcc+flags */
|
| 835 |
|
| 836 | t_stat ch_op_store_diag (uint32 ch, t_uint64 *dat)
|
| 837 | {
|
Mark Pizzolato | 6e813b8 | 2012-03-24 19:46:37 -0700 | [diff] [blame] | 838 | extern t_uint64 drm_sdc (uint32 ch);
|
| 839 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 840 | if ((ch >= NUM_CHAN) || (ch_dev[ch].flags & DEV_DIS))
|
| 841 | return STOP_NXCHN;
|
| 842 | if (ch_flags[ch] & DEV_7289)
|
Mark Pizzolato | 6e813b8 | 2012-03-24 19:46:37 -0700 | [diff] [blame] | 843 | *dat = drm_sdc (ch);
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 844 | else if (ch_flags[ch] & DEV_7909)
|
| 845 | *dat = (((t_uint64) (ch_lcc[ch] & CHF_M_LCC)) << CHF_V_LCC) |
|
| 846 | (ch_flags[ch] & CHF_SDC_7909);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 847 | else *dat = 0;
|
| 848 | return SCPE_OK;
|
| 849 | }
|
| 850 |
|
| 851 | /* Reset data channel
|
| 852 |
|
| 853 | 7607 responds to RDC
|
| 854 | 7909 responds to RIC */
|
| 855 |
|
| 856 | t_stat ch_op_reset (uint32 ch, t_bool ch7909)
|
| 857 | {
|
| 858 | DEVICE *dptr;
|
| 859 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 860 | if (ch >= NUM_CHAN) /* invalid argument? */
|
| 861 | return STOP_NXCHN;
|
| 862 | if (ch_dev[ch].flags & DEV_DIS) /* disabled? ok */
|
| 863 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 864 | if (ch_dev[ch].flags & DEV_7909) { /* 7909? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 865 | if (!ch7909) /* wrong reset is NOP */
|
| 866 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 867 | dptr = ch2dev[ch]; /* get device */
|
| 868 | }
|
| 869 | else { /* 7607, 7289 */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 870 | if (ch7909) /* wrong reset is err */
|
| 871 | return STOP_NT7909;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 872 | dptr = ch_find_dev (ch, ch_ndsu[ch]); /* find device */
|
| 873 | }
|
| 874 | ch_reset (&ch_dev[ch]); /* reset channel */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 875 | if (dptr && dptr->reset) /* reset device */
|
| 876 | dptr->reset (dptr);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 877 | return SCPE_OK;
|
| 878 | }
|
| 879 |
|
| 880 | /* Channel process - called from main CPU loop. If the channel is unable
|
| 881 | to get a valid command, it will reschedule itself for the next cycle.
|
| 882 |
|
| 883 | The read process is basically synchronous with the device timeout routine.
|
| 884 | The device requests the channel and supplies the word to be stored in memory.
|
| 885 | In the next time slot, the channel stores the word in memory. */
|
| 886 |
|
| 887 | t_stat ch_proc (uint32 ch)
|
| 888 | {
|
| 889 | t_stat r;
|
| 890 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 891 | if (ch >= NUM_CHAN) /* bad channel? */
|
| 892 | return SCPE_IERR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 893 | ch_req &= ~REQ_CH (ch); /* clear request */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 894 | if (ch_dev[ch].flags & DEV_DIS) /* disabled? */
|
| 895 | return SCPE_IERR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 896 | if (ch_dev[ch].flags & DEV_7909) { /* 7909 */
|
| 897 |
|
| 898 | t_uint64 sr;
|
| 899 | uint32 csel, sc, tval, mask, ta;
|
| 900 | t_bool xfr;
|
| 901 |
|
| 902 | if (ch_flags[ch] & CHF_IRQ) { /* interrupt? */
|
| 903 | ta = CHINT_CHA_SAV + (ch << 1); /* save location */
|
| 904 | if (ch_sta[ch] == CHXS_IDLE) /* waiting? */
|
| 905 | sr = (((t_uint64) ch_ca[ch] & CHAMASK) << INST_V_DEC) |
|
| 906 | ((t_uint64) ch_clc[ch] & CHAMASK); /* save CLC */
|
| 907 | else sr = (((t_uint64) ch_ca[ch] & CHAMASK) << INST_V_DEC) |
|
| 908 | ((t_uint64) CHAINC (ch_clc[ch])); /* no, save CLC+1 */
|
| 909 | ch_sta[ch] = CHXS_DSX; /* set running */
|
| 910 | ch_flags[ch] = (ch_flags[ch] | CHF_INT) & /* set intr state */
|
| 911 | ~(CHF_IRQ|CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS); /* clr flags */
|
| 912 | WriteP (ta, sr); /* write ca,,clc */
|
| 913 | sr = ReadP (ta + 1); /* get chan cmd */
|
| 914 | return ch9_exec_cmd (ch, sr); /* exec cmd */
|
| 915 | }
|
| 916 |
|
| 917 | switch (ch_op[ch] & CH9_OPMASK) { /* switch on op */
|
| 918 |
|
| 919 | case CH9_TWT: /* transfer of TWT */
|
| 920 | case CH9_WTR: /* transfer of WTR */
|
| 921 | case CH9_TCH: /* transfer */
|
| 922 | ch_clc[ch] = ch_ca[ch] & CHAMASK; /* change CLC */
|
| 923 | break;
|
| 924 |
|
| 925 | case CH9_TDC: /* decr & transfer */
|
| 926 | if (ch_lcc[ch] != 0) { /* counter != 0? */
|
| 927 | ch_lcc[ch]--; /* decr counter */
|
| 928 | ch_clc[ch] = ch_ca[ch] & CHAMASK; /* change CLC */
|
| 929 | }
|
| 930 | break;
|
| 931 |
|
| 932 | case CH9_TCM: /* transfer on cond */
|
| 933 | csel = CH9D_COND (ch_wc[ch]);
|
| 934 | mask = CH9D_MASK (ch_wc[ch]);
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 935 | if (csel == 7) /* C = 7? mask mbz */
|
| 936 | xfr = (mask == 0);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 937 | else { /* C = 0..6 */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 938 | if (csel == 0) /* C = 0? test cond */
|
| 939 | tval = ch_cnd[ch];
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 940 | else tval = (uint32) (ch_ar[ch] >> (6 * (6 - csel))) & 077;
|
| 941 | if (ch_wc[ch] & CH9D_B11)
|
| 942 | xfr = ((tval & mask) == mask);
|
| 943 | else xfr = (tval == mask);
|
| 944 | }
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 945 | if (xfr) /* change CLC */
|
| 946 | ch_clc[ch] = ch_ca[ch] & CHAMASK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 947 | break;
|
| 948 |
|
| 949 | case CH9_LIP: /* leave interrupt */
|
| 950 | ta = CHINT_CHA_SAV + (ch << 1); /* save location */
|
| 951 | ch_flags[ch] &= ~(CHF_INT|CHF_IRQ); /* clear intr */
|
| 952 | ch_cnd[ch] = 0; /* clear channel cond */
|
| 953 | ch_clc[ch] = (uint32) ReadP (ta) & CHAMASK;
|
| 954 | break;
|
| 955 |
|
| 956 | case CH9_LIPT: /* leave intr, transfer */
|
| 957 | ch_flags[ch] &= ~(CHF_INT|CHF_IRQ); /* clear intr */
|
| 958 | ch_cnd[ch] = 0; /* clear channel cond */
|
| 959 | ch_clc[ch] = ch_ca[ch] & CHAMASK; /* change CLC */
|
| 960 | break;
|
| 961 |
|
| 962 | case CH9_LAR: /* load assembly reg */
|
| 963 | ch_ar[ch] = ReadP (ch_ca[ch]);
|
| 964 | break;
|
| 965 |
|
| 966 | case CH9_SAR: /* store assembly reg */
|
| 967 | WriteP (ch_ca[ch], ch_ar[ch]);
|
| 968 | break;
|
| 969 |
|
| 970 | case CH9_SMS: /* load SMS reg */
|
| 971 | ch_sms[ch] = CH9A_SMS (ch_ca[ch]); /* from eff addr */
|
| 972 | if (!(ch_sms[ch] & CHSMS_IATN1) && /* atn inhbit off */
|
| 973 | (ch_flags[ch] & CHF_ATN1)) /* and atn pending? */
|
| 974 | ch9_eval_int (ch, 0); /* force int eval */
|
| 975 | break;
|
| 976 |
|
| 977 | case CH9_LCC: /* load control cntr */
|
| 978 | ch_lcc[ch] = CH9A_LCC (ch_ca[ch]); /* from eff addr */
|
| 979 | break;
|
| 980 |
|
| 981 | case CH9_ICC: /* insert control cntr */
|
| 982 | case CH9_ICCA:
|
| 983 | csel = CH9D_COND (ch_wc[ch]); /* get C */
|
| 984 | if (csel == 0) ch_ar[ch] = /* C = 0? read SMS */
|
Mark Pizzolato | c93658f | 2013-04-05 12:34:37 -0700 | [diff] [blame] | 985 | (ch_ar[ch] & INT64_C(0777777770000)) | ((t_uint64) ch_sms[ch]);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 986 | else if (csel < 7) { /* else read cond cntr */
|
| 987 | sc = 6 * (6 - csel);
|
| 988 | ch_ar[ch] = (ch_ar[ch] & ~(((t_uint64) 077) << sc)) |
|
| 989 | (((t_uint64) ch_lcc[ch]) << sc);
|
| 990 | }
|
| 991 | break;
|
| 992 |
|
| 993 | case CH9_XMT: /* transmit */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 994 | if (ch_wc[ch] == 0)
|
| 995 | break;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 996 | sr = ReadP (ch_clc[ch]); /* next word */
|
| 997 | WriteP (ch_ca[ch], sr);
|
| 998 | ch_clc[ch] = CHAINC (ch_clc[ch]); /* incr pointers */
|
| 999 | ch_ca[ch] = CHAINC (ch_ca[ch]);
|
| 1000 | ch_wc[ch] = ch_wc[ch] - 1; /* decr count */
|
| 1001 | ch_req |= REQ_CH (ch); /* go again */
|
| 1002 | return SCPE_OK;
|
| 1003 |
|
| 1004 | case CH9_SNS: /* sense */
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1005 | if ((r = ch9_sel (ch, CHSL_SNS))) /* send sense to dev */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1006 | return r;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1007 | ch_flags[ch] |= CHF_PRD; /* prepare to read */
|
| 1008 | break; /* next command */
|
| 1009 |
|
| 1010 | case CH9_CTL:
|
| 1011 | case CH9_CTLR:
|
| 1012 | case CH9_CTLW: /* control */
|
| 1013 | if (((ch_wc[ch] & CH9D_NST) == 0) && /* N = 0 and */
|
| 1014 | !(ch_flags[ch] & CHF_EOR)) { /* end not set? */
|
| 1015 | sr = ReadP (ch_ca[ch]);
|
| 1016 | ch_ca[ch] = CHAINC (ch_ca[ch]); /* incr ca */
|
| 1017 | return ch9_wr (ch, sr, 0); /* write ctrl wd */
|
| 1018 | }
|
| 1019 | ch_flags[ch] &= ~CHF_EOR; /* clear end */
|
| 1020 | if (ch_op[ch] == CH9_CTLR) { /* CTLR? */
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1021 | if ((r = ch9_sel (ch, CHSL_RDS))) /* send read sel */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1022 | return r;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1023 | ch_flags[ch] |= CHF_PRD; /* prep to read */
|
| 1024 | ch_idf[ch] = 0;
|
| 1025 | }
|
| 1026 | else if (ch_op[ch] == CH9_CTLW) { /* CTLW? */
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1027 | if ((r = ch9_sel (ch, CHSL_WRS))) /* end write sel */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1028 | return r;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1029 | ch_flags[ch] |= CHF_PWR; /* prep to write */
|
| 1030 | }
|
| 1031 | break;
|
| 1032 |
|
| 1033 | case CH9_CPYD: /* copy & disc */
|
| 1034 | if ((ch_wc[ch] == 0) || (ch_flags[ch] & CHF_EOR)) { /* wc == 0 or EOR? */
|
| 1035 | if (ch_flags[ch] & (CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS)) {
|
| 1036 | ch_flags[ch] &= ~(CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS);
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1037 | if ((r = ch9_wr (ch, 0, CH9DF_STOP))) /* send stop */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1038 | return r;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1039 | }
|
| 1040 | if (ch_flags[ch] & CHF_EOR) { /* EOR? */
|
| 1041 | ch_flags[ch] &= ~CHF_EOR; /* clear flag */
|
| 1042 | break; /* new command */
|
| 1043 | }
|
| 1044 | return SCPE_OK; /* wait for end */
|
| 1045 | }
|
| 1046 | if (ch_flags[ch] & CHF_RDS) /* read? */
|
| 1047 | return ch9_rd_putw (ch);
|
| 1048 | return ch9_wr_getw (ch); /* no, write */
|
| 1049 |
|
| 1050 | case CH9_CPYP: /* anything to do? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1051 | if (ch_wc[ch] == 0) /* (new, wc = 0) next */
|
| 1052 | break;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1053 | if (ch_flags[ch] & CHF_EOR) /* end? */
|
| 1054 | ch_flags[ch] &= ~CHF_EOR; /* ignore */
|
| 1055 | else if (ch_flags[ch] & CHF_RDS) /* read? */
|
| 1056 | ch9_rd_putw (ch);
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1057 | else if ((r = ch9_wr_getw (ch))) /* no, write */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1058 | return r;
|
| 1059 | if (ch_wc[ch] == 0) /* done? get next */
|
| 1060 | break;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1061 | return SCPE_OK; /* more to do */
|
| 1062 |
|
| 1063 | default:
|
| 1064 | return STOP_ILLIOP;
|
| 1065 | }
|
| 1066 |
|
| 1067 | return ch9_new_cmd (ch); /* next command */
|
| 1068 | }
|
| 1069 |
|
| 1070 | else if (ch_flags[ch] & CHF_RDS) { /* 7607 read? */
|
| 1071 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1072 | if (ch_sta[ch] != CHXS_DSX) /* chan exec? no, disc */
|
| 1073 | return ch6_end_ds (ch);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1074 | switch (ch_op[ch] & CH6_OPMASK) { /* switch on op */
|
| 1075 |
|
| 1076 | case CH6_TCH: /* transfer */
|
| 1077 | ch_clc[ch] = ch_ca[ch] & CHAMASK; /* change clc */
|
| 1078 | return ch6_new_cmd (ch, FALSE); /* unpack new cmd */
|
| 1079 |
|
| 1080 | case CH6_IOCD: /* IOCD */
|
| 1081 | if (ch_wc[ch]) { /* wc > 0? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1082 | if (ch6_rd_putw (ch)) /* store; more? cont */
|
| 1083 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1084 | }
|
| 1085 | return ch6_end_ds (ch); /* no, disconnect */
|
| 1086 |
|
| 1087 | case CH6_IOCP: /* IOCP */
|
| 1088 | if (ch_wc[ch]) { /* wc > 0? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1089 | if (ch6_rd_putw (ch)) /* store; more? cont */
|
| 1090 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1091 | }
|
| 1092 | return ch6_new_cmd (ch, FALSE); /* unpack new cmd */
|
| 1093 |
|
| 1094 | case CH6_IOCT: /* IOCT */
|
| 1095 | if (ch_wc[ch]) { /* wc > 0? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1096 | if (ch6_rd_putw (ch)) /* store; more? cont */
|
| 1097 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1098 | }
|
| 1099 | return ch6_ioxt (ch); /* unstall or disc */
|
| 1100 |
|
| 1101 | case CH6_IOSP: /* IOSP */
|
| 1102 | if (ch_flags[ch] & CHF_EOR) { /* (new) EOR set? */
|
| 1103 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear flag */
|
| 1104 | return ch6_new_cmd (ch, FALSE); /* get next cmd */
|
| 1105 | }
|
| 1106 | if (ch_wc[ch]) { /* wc > 0? */
|
| 1107 | if (ch6_rd_putw (ch) && !(ch_flags[ch] & CHF_EOR))
|
| 1108 | return SCPE_OK; /* yes, store; more? */
|
| 1109 | ch6_iosp_cclr (ch); /* cond clear eor */
|
| 1110 | }
|
| 1111 | return ch6_new_cmd (ch, FALSE); /* next cmd */
|
| 1112 |
|
| 1113 | case CH6_IOST: /* IOST */
|
| 1114 | if (ch_flags[ch] & CHF_EOR) { /* (new) EOR set? */
|
| 1115 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear flag */
|
| 1116 | return ch6_ioxt (ch); /* get next cmd */
|
| 1117 | }
|
| 1118 | if (ch_wc[ch]) { /* wc > 0? */
|
| 1119 | if (ch6_rd_putw (ch) && !(ch_flags[ch] & CHF_EOR))
|
| 1120 | return SCPE_OK; /* yes, store; more? */
|
| 1121 | ch6_iosp_cclr (ch); /* cond clear eor */
|
| 1122 | }
|
| 1123 | return ch6_ioxt (ch); /* unstall or disc */
|
| 1124 |
|
| 1125 | case CH6_IORP: /* IORP */
|
| 1126 | if (ch_flags[ch] & CHF_EOR) { /* (new) EOR set? */
|
| 1127 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear flag */
|
| 1128 | return ch6_new_cmd (ch, FALSE); /* get next cmd */
|
| 1129 | }
|
| 1130 | ch6_rd_putw (ch); /* store wd; ignore wc */
|
| 1131 | if (ch_flags[ch] & CHF_EOR) { /* EOR? */
|
| 1132 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear flag */
|
| 1133 | return ch6_new_cmd (ch, FALSE); /* get next cmd */
|
| 1134 | }
|
| 1135 | return SCPE_OK; /* done */
|
| 1136 |
|
| 1137 | case CH6_IORT: /* IORT */
|
| 1138 | if (ch_flags[ch] & CHF_EOR) { /* (new) EOR set? */
|
| 1139 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear flag */
|
| 1140 | return ch6_ioxt (ch); /* get next cmd */
|
| 1141 | }
|
| 1142 | ch6_rd_putw (ch); /* store wd; ignore wc */
|
| 1143 | if (ch_flags[ch] & CHF_EOR) { /* EOR? */
|
| 1144 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear flag */
|
| 1145 | return ch6_ioxt (ch); /* unstall or disc */
|
| 1146 | }
|
| 1147 | return SCPE_OK; /* done */
|
| 1148 |
|
| 1149 | default:
|
| 1150 | return SCPE_IERR;
|
| 1151 | } /* end case */
|
| 1152 | } /* end if read */
|
| 1153 |
|
| 1154 | else { /* 7607 write */
|
| 1155 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1156 | if (ch_sta[ch] != CHXS_DSX) /* chan exec? no, disc */
|
| 1157 | return ch6_end_ds (ch);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1158 | switch (ch_op[ch] & CH6_OPMASK) { /* switch on op */
|
| 1159 |
|
| 1160 | case CH6_TCH: /* transfer */
|
| 1161 | ch_clc[ch] = ch_ca[ch] & CHAMASK; /* change clc */
|
| 1162 | return ch6_new_cmd (ch, FALSE); /* unpack new cmd */
|
| 1163 |
|
| 1164 | case CH6_IOCD: /* IOCD */
|
| 1165 | if (ch_wc[ch]) { /* wc > 0? */
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1166 | if ((r = ch6_wr_getw (ch, TRUE))) /* send wd to dev; err? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1167 | return r;
|
| 1168 | if (ch_wc[ch]) /* more to do? */
|
| 1169 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1170 | }
|
| 1171 | return ch6_end_ds (ch); /* disconnect */
|
| 1172 |
|
| 1173 | case CH6_IOCP: /* IOCP */
|
| 1174 | case CH6_IOSP: /* IOSP */
|
| 1175 | if (ch_wc[ch]) { /* wc > 0? */
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1176 | if ((r = ch6_wr_getw (ch, FALSE))) /* send wd to dev; err? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1177 | return r;
|
| 1178 | if (ch_wc[ch]) /* more to do? */
|
| 1179 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1180 | }
|
| 1181 | return ch6_new_cmd (ch, FALSE); /* get next cmd */
|
| 1182 |
|
| 1183 | case CH6_IOCT: /* IOCT */
|
| 1184 | case CH6_IOST: /* IOST */
|
| 1185 | if (ch_wc[ch]) { /* wc > 0? */
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1186 | if ((r = ch6_wr_getw (ch, FALSE))) /* send wd to dev; err? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1187 | return r;
|
| 1188 | if (ch_wc[ch]) /* more to do? */
|
| 1189 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1190 | }
|
| 1191 | return ch6_ioxt (ch); /* get next cmd */
|
| 1192 |
|
| 1193 | case CH6_IORP: /* IORP */
|
| 1194 | if (!(ch_flags[ch] & CHF_EOR) && ch_wc[ch]) { /* not EOR? (cdp, lpt) */
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1195 | if ((r = ch6_wr_getw (ch, TRUE))) /* send wd to dev; err? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1196 | return r;
|
| 1197 | if (ch_wc[ch]) /* more to do? */
|
| 1198 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1199 | }
|
| 1200 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear EOR */
|
| 1201 | return ch6_new_cmd (ch, FALSE); /* get next cmd */
|
| 1202 |
|
| 1203 | case CH6_IORT: /* IORT */
|
| 1204 | if (!(ch_flags[ch] & CHF_EOR) && ch_wc[ch]) { /* not EOR? (cdp, lpt) */
|
Mark Pizzolato | 0f8e6cf | 2012-04-29 11:59:44 -0700 | [diff] [blame] | 1205 | if ((r = ch6_wr_getw (ch, TRUE))) /* send wd to dev; err? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1206 | return r;
|
| 1207 | if (ch_wc[ch]) /* more to do? */
|
| 1208 | return SCPE_OK;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1209 | }
|
| 1210 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear EOR */
|
| 1211 | return ch6_ioxt (ch); /* unstall or disc */
|
| 1212 |
|
| 1213 | default:
|
| 1214 | return SCPE_IERR;
|
| 1215 | } /* end switch */
|
| 1216 | } /* end else write */
|
| 1217 | }
|
| 1218 |
|
| 1219 | /* 7607 channel support routines */
|
| 1220 |
|
| 1221 | /* 7607 channel input routine - put one word to memory */
|
| 1222 |
|
| 1223 | t_bool ch6_rd_putw (uint32 ch)
|
| 1224 | {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1225 | if (ch_idf[ch] & CH6DF_EOR) /* eor from dev? */
|
| 1226 | ch_flags[ch] |= CHF_EOR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1227 | else ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* set/clr chan eor */
|
| 1228 | ch_idf[ch] = 0; /* clear eor, valid */
|
| 1229 | if (ch_wc[ch]) { /* wc > 0? */
|
| 1230 | if ((ch_op[ch] & 1) == 0) { /* do store? */
|
| 1231 | WriteP (ch_ca[ch], ch_ar[ch]);
|
| 1232 | ch_ca[ch] = CHAINC (ch_ca[ch]); /* incr ca */
|
| 1233 | }
|
| 1234 | ch_wc[ch] = ch_wc[ch] - 1;
|
| 1235 | }
|
| 1236 | return (ch_wc[ch]? TRUE: FALSE);
|
| 1237 | }
|
| 1238 |
|
| 1239 | /* 7607 channel output routine - get one word from memory */
|
| 1240 |
|
| 1241 | t_stat ch6_wr_getw (uint32 ch, t_bool eorz)
|
| 1242 | {
|
| 1243 | DEVICE *dptr;
|
| 1244 | DIB *dibp;
|
| 1245 | uint32 eorfl;
|
| 1246 |
|
| 1247 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clr eor */
|
| 1248 | if (ch_wc[ch]) {
|
| 1249 | ch_ar[ch] = ReadP (ch_ca[ch]); /* get word */
|
| 1250 | ch_ca[ch] = CHAINC (ch_ca[ch]); /* incr ca */
|
| 1251 | ch_wc[ch] = ch_wc[ch] - 1;
|
| 1252 | }
|
| 1253 | else ch_ar[ch] = 0;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1254 | if (eorz && (ch_wc[ch] == 0)) /* eor on wc = 0? */
|
| 1255 | eorfl = 1;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1256 | else eorfl = 0;
|
| 1257 | dptr = ch_find_dev (ch, ch_dsu[ch]); /* find device */
|
| 1258 | if (dptr && /* valid device? */
|
| 1259 | (dibp = (DIB *) dptr->ctxt) && /* with DIB? */
|
| 1260 | dibp->write) /* and write routine? */
|
| 1261 | return dibp->write (ch, ch_ar[ch], eorfl);
|
| 1262 | return SCPE_IERR; /* huh? */
|
| 1263 | }
|
| 1264 |
|
| 1265 | /* 7607 channel new command - on channel load, check for disconnects
|
| 1266 |
|
| 1267 | The protocol for new commands is as follows:
|
| 1268 | - If IOCD 0,,0, disconnect immediately
|
| 1269 | - If IOCT 0,,0 or IOST 0,,0 and loaded by RCHA, disconnect immediately
|
| 1270 | - If an effective NOP (TCH, IOCx 0,,0, IOSx 0,,0), force a channel
|
| 1271 | cycle to retire the channel comand as quickly as possible.
|
| 1272 | - If an IORx and EOR is set, force a channel cycle to retire the
|
| 1273 | channel command as quickly as possible.
|
| 1274 | */
|
| 1275 |
|
| 1276 | t_stat ch6_new_cmd (uint32 ch, t_bool ch_ld)
|
| 1277 | {
|
| 1278 | t_uint64 ir;
|
| 1279 | uint32 op, t;
|
| 1280 |
|
| 1281 | ir = ReadP (t = ch_clc[ch]); /* read cmd */
|
| 1282 | ch_wc[ch] = GET_DEC (ir); /* get word cnt */
|
| 1283 | ch_ca[ch] = ((uint32) ir) & CHAMASK; /* get address */
|
| 1284 | op = GET_OPD (ir) << 1; /* get opcode */
|
| 1285 | ch_op[ch] = op | ((((uint32) ir) & CH6I_NST)? 1: 0); /* plus 'no store' */
|
| 1286 | if ((ir & CHI_IND) && (ch_wc[ch] || /* indirect? */
|
| 1287 | ((op != CH6_IOCP) && (op != CH6_IOSP)))) { /* wc >0, or !IOxP? */
|
| 1288 | t_uint64 sr = ReadP (ch_ca[ch] & AMASK); /* read indirect */
|
| 1289 | ch_ca[ch] = ((uint32) sr) & ((cpu_model & I_CT)? PAMASK: AMASK);
|
| 1290 | }
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1291 | if (hst_ch)
|
| 1292 | cpu_ent_hist (ch_clc[ch] | ((ch + 1) << HIST_V_CH), ch_ca[ch], ir, 0);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1293 | ch_clc[ch] = (ch_clc[ch] + 1) & AMASK; /* incr chan pc */
|
| 1294 |
|
| 1295 | switch (op) { /* case on opcode */
|
| 1296 |
|
| 1297 | case CH6_IOCD: /* IOCD */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1298 | if (ch_wc[ch] == 0) /* wc 0? end now */
|
| 1299 | ch6_end_ds (ch);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1300 | break;
|
| 1301 |
|
| 1302 | case CH6_IOST: /* IOST */
|
| 1303 | if (ch_flags[ch] & CHF_EOR) /* EOR set? immed ch req */
|
| 1304 | ch_req |= REQ_CH (ch);
|
Bob Supnik | a37e928 | 2017-03-20 07:46:28 -0700 | [diff] [blame] | 1305 | /* fall through */
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1306 | case CH6_IOCT: /* IOCT */
|
| 1307 | if (ch_wc[ch] == 0) { /* wc 0? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1308 | if (ch_ld) /* load? end now */
|
| 1309 | ch6_end_ds (ch);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1310 | else ch_req |= REQ_CH (ch); /* else immed ch req */
|
| 1311 | }
|
| 1312 | break;
|
| 1313 |
|
| 1314 | case CH6_IOSP: /* IOSP */
|
| 1315 | if (ch_flags[ch] & CHF_EOR) /* EOR set? immed ch req */
|
| 1316 | ch_req |= REQ_CH (ch);
|
Bob Supnik | a37e928 | 2017-03-20 07:46:28 -0700 | [diff] [blame] | 1317 | /* fall through */
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1318 | case CH6_IOCP: /* IOCP */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1319 | if (ch_wc[ch] == 0) /* wc 0? immed ch req */
|
| 1320 | ch_req |= REQ_CH (ch);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1321 | break;
|
| 1322 |
|
| 1323 | case CH6_IORT: /* IORT */
|
| 1324 | case CH6_IORP: /* IORP */
|
| 1325 | if (ch_flags[ch] & CHF_EOR) /* EOR set? immed ch req */
|
| 1326 | ch_req |= REQ_CH (ch);
|
| 1327 | break;
|
| 1328 |
|
| 1329 | case CH6_TCH: /* TCH */
|
| 1330 | ch_req |= REQ_CH (ch); /* immed ch req */
|
| 1331 | break;
|
| 1332 |
|
| 1333 | default: /* all others */
|
| 1334 | break;
|
| 1335 | } /* end case */
|
| 1336 |
|
| 1337 | if (sim_brk_summ && sim_brk_test (t, SWMASK ('E')))
|
| 1338 | return ch_bkpt (ch, t);
|
| 1339 | return SCPE_OK;
|
| 1340 | }
|
| 1341 |
|
| 1342 | /* 7607 channel IOxT: if LCH stall, set state back to DSW; else disconnect and trap */
|
| 1343 |
|
| 1344 | t_stat ch6_ioxt (uint32 ch)
|
| 1345 | {
|
| 1346 | if (ch_flags[ch] & CHF_LDW) { /* LCH cmd pending? */
|
| 1347 | ch_flags[ch] &= ~CHF_LDW; /* clr pending flag */
|
| 1348 | ch_sta[ch] = CH6S_DSW; /* unstall pending LCH */
|
| 1349 | }
|
| 1350 | else {
|
| 1351 | ch_flags[ch] |= CHF_CMD; /* set cmd trap flag */
|
| 1352 | ch6_end_ds (ch); /* disconnect */
|
| 1353 | }
|
| 1354 | return SCPE_OK;
|
| 1355 | }
|
| 1356 |
|
| 1357 | /* 7607 conditionally clear EOR on IOSx completion */
|
| 1358 |
|
| 1359 | void ch6_iosp_cclr (uint32 ch)
|
| 1360 | {
|
| 1361 | uint32 i, op;
|
| 1362 |
|
| 1363 | if (ch_wc[ch] == 0) { /* wc = 0? */
|
| 1364 | uint32 ccnt = 5; /* allow 5 for CPU */
|
| 1365 | for (i = 0; i < NUM_CHAN; i++) { /* test channels */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1366 | if (ch_sta[ch] != CHXS_DSX) /* idle? skip */
|
| 1367 | continue;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1368 | op = ch_op[ch] & ~1; /* get op */
|
| 1369 | ccnt++; /* 1 per active ch */
|
| 1370 | if ((op == CH6_IOCP) || (op == CH6_IORP) || /* 1 per proceed */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1371 | (op == CH6_IOSP))
|
| 1372 | ccnt++;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1373 | }
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1374 | if (ccnt <= 11) /* <= 11? ok */
|
| 1375 | return;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1376 | }
|
| 1377 | ch_flags[ch] = ch_flags[ch] & ~CHF_EOR; /* clear eor */
|
| 1378 | return;
|
| 1379 | }
|
| 1380 |
|
| 1381 | /* 7607 external interface routines */
|
| 1382 |
|
| 1383 | /* Input - store word, request channel input service */
|
| 1384 |
|
| 1385 | t_stat ch6_req_rd (uint32 ch, uint32 unit, t_uint64 val, uint32 fl)
|
| 1386 | {
|
| 1387 | if (ch6_qconn (ch, unit)) { /* ch conn to caller? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1388 | if (ch_idf[ch] & CH6DF_VLD) /* overrun? */
|
| 1389 | ind_ioc = 1;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1390 | ch_idf[ch] = CH6DF_VLD; /* set ar valid */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1391 | if (fl) /* set eor if requested */
|
| 1392 | ch_idf[ch] |= CH6DF_EOR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1393 | ch_req |= REQ_CH (ch); /* request chan */
|
| 1394 | ch_flags[ch] |= CHF_RDS;
|
| 1395 | ch_ar[ch] = val & DMASK; /* save data */
|
| 1396 | }
|
| 1397 | return SCPE_OK;
|
| 1398 | }
|
| 1399 |
|
| 1400 | /* Disconnect on error */
|
| 1401 |
|
| 1402 | t_stat ch6_err_disc (uint32 ch, uint32 unit, uint32 fl)
|
| 1403 | {
|
| 1404 | if (ch6_qconn (ch, unit)) { /* ch conn to caller? */
|
| 1405 | ch_flags[ch] |= fl; /* set flag */
|
| 1406 | return ch6_end_ds (ch); /* disconnect */
|
| 1407 | }
|
| 1408 | return SCPE_OK;
|
| 1409 | }
|
| 1410 |
|
| 1411 | /* Output - request channel output service */
|
| 1412 |
|
| 1413 | t_bool ch6_req_wr (uint32 ch, uint32 unit)
|
| 1414 | {
|
| 1415 | if (ch6_qconn (ch, unit)) { /* ch conn to caller? */
|
| 1416 | ch_req |= REQ_CH (ch);
|
| 1417 | ch_flags[ch] &= ~CHF_RDS;
|
| 1418 | }
|
| 1419 | return SCPE_OK;
|
| 1420 | }
|
| 1421 |
|
| 1422 | /* Set/read channel flags */
|
| 1423 |
|
| 1424 | uint32 ch6_set_flags (uint32 ch, uint32 unit, uint32 flags)
|
| 1425 | {
|
| 1426 | if (ch6_qconn (ch, unit)) { /* ch conn to caller? */
|
| 1427 | ch_flags[ch] = ch_flags[ch] | flags;
|
| 1428 | return ch_flags[ch];
|
| 1429 | }
|
| 1430 | return 0;
|
| 1431 | }
|
| 1432 |
|
| 1433 | /* Channel connected to unit? */
|
| 1434 |
|
| 1435 | t_bool ch6_qconn (uint32 ch, uint32 unit)
|
| 1436 | {
|
| 1437 | if ((ch < NUM_CHAN) && /* valid chan */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1438 | (ch_dsu[ch] == unit)) /* for right unit? */
|
| 1439 | return TRUE;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1440 | return FALSE;
|
| 1441 | }
|
| 1442 |
|
| 1443 | /* 7909 channel support routines */
|
| 1444 |
|
| 1445 | /* 7909 channel input routine - put one word to memory */
|
| 1446 |
|
| 1447 | t_stat ch9_rd_putw (uint32 ch)
|
| 1448 | {
|
| 1449 | ch_idf[ch] = 0; /* invalidate */
|
| 1450 | if (ch_wc[ch]) { /* wc > 0? */
|
| 1451 | WriteP (ch_ca[ch], ch_ar[ch]);
|
| 1452 | ch_ca[ch] = CHAINC (ch_ca[ch]);
|
| 1453 | ch_wc[ch] = ch_wc[ch] - 1;
|
| 1454 | }
|
| 1455 | return SCPE_OK;
|
| 1456 | }
|
| 1457 |
|
| 1458 | /* 7909 channel output routine - get one word from memory */
|
| 1459 |
|
| 1460 | t_stat ch9_wr_getw (uint32 ch)
|
| 1461 | {
|
| 1462 | if (ch_wc[ch]) {
|
| 1463 | ch_ar[ch] = ReadP (ch_ca[ch]); /* get word */
|
| 1464 | ch_ca[ch] = CHAINC (ch_ca[ch]);
|
| 1465 | ch_wc[ch] = ch_wc[ch] - 1;
|
| 1466 | }
|
| 1467 | else ch_ar[ch] = 0;
|
| 1468 | return ch9_wr (ch, ch_ar[ch], 0); /* write to device */
|
| 1469 | }
|
| 1470 |
|
| 1471 | /* 7909 send select to device */
|
| 1472 |
|
| 1473 | t_stat ch9_sel (uint32 ch, uint32 sel)
|
| 1474 | {
|
| 1475 | DEVICE *dptr = ch2dev[ch];
|
| 1476 | DIB *dibp;
|
| 1477 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1478 | if (dptr == NULL)
|
| 1479 | return SCPE_IERR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1480 | dibp = (DIB *) dptr->ctxt;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1481 | if (dibp && dibp->chsel)
|
| 1482 | return dibp->chsel (ch, sel, 0);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1483 | return SCPE_IERR;
|
| 1484 | }
|
| 1485 |
|
| 1486 | /* 7909 send word to device */
|
| 1487 |
|
| 1488 | t_stat ch9_wr (uint32 ch, t_uint64 dat, uint32 fl)
|
| 1489 | {
|
| 1490 | DEVICE *dptr = ch2dev[ch];
|
| 1491 | DIB *dibp;
|
| 1492 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1493 | if (dptr == NULL)
|
| 1494 | return SCPE_IERR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1495 | dibp = (DIB *) dptr->ctxt;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1496 | if (dibp && dibp->write)
|
| 1497 | return dibp->write (ch, dat, fl);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1498 | return SCPE_IERR;
|
| 1499 | }
|
| 1500 |
|
| 1501 | /* 7909 channel new command */
|
| 1502 |
|
| 1503 | t_stat ch9_new_cmd (uint32 ch)
|
| 1504 | {
|
| 1505 | t_uint64 ir;
|
| 1506 | uint32 t;
|
| 1507 | t_stat r;
|
| 1508 |
|
| 1509 | ir = ReadP (t = ch_clc[ch]); /* read cmd */
|
| 1510 | r = ch9_exec_cmd (ch, ir); /* exec cmd */
|
| 1511 | if (ch_sta[ch] != CHXS_IDLE) /* chan running? */
|
| 1512 | ch_clc[ch] = CHAINC (ch_clc[ch]); /* incr chan pc */
|
| 1513 | if ((r == SCPE_OK) && sim_brk_summ && sim_brk_test (t, SWMASK ('E')))
|
| 1514 | return ch_bkpt (ch, t);
|
| 1515 | return r;
|
| 1516 | }
|
| 1517 |
|
| 1518 | t_stat ch9_exec_cmd (uint32 ch, t_uint64 ir)
|
| 1519 | {
|
| 1520 | uint32 op;
|
| 1521 |
|
| 1522 | ch_wc[ch] = GET_DEC (ir); /* get word cnt */
|
| 1523 | ch_ca[ch] = ((uint32) ir) & CHAMASK; /* get address */
|
| 1524 | op = (GET_OPD (ir) << 2); /* get opcode */
|
| 1525 | ch_op[ch] = op | ((((uint32) ir) & 0200000)? 1: 0) | /* plus bit<19> */
|
| 1526 | (((op & 010) && (ch_wc[ch] & 040000))? 2: 0); /* plus bit 3 if used */
|
| 1527 | if (ir & CHI_IND) { /* indirect? */
|
| 1528 | t_uint64 sr = ReadP (ch_ca[ch] & CHAMASK); /* read indirect */
|
| 1529 | ch_ca[ch] = ((uint32) sr) & CHAMASK; /* get address */
|
| 1530 | }
|
| 1531 | if (hst_ch)
|
| 1532 | cpu_ent_hist (ch_clc[ch] | ((ch + 1) << HIST_V_CH), ch_ca[ch], ir, 0);
|
| 1533 |
|
| 1534 | switch (ch_op[ch]) { /* check initial cond */
|
| 1535 |
|
| 1536 | case CH9_LAR: /* misc processing */
|
| 1537 | case CH9_SAR:
|
| 1538 | case CH9_ICC:
|
| 1539 | case CH9_ICCA:
|
| 1540 | case CH9_XMT:
|
| 1541 | case CH9_LCC:
|
| 1542 | case CH9_SMS:
|
| 1543 | if (ch_flags[ch] & (CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS))
|
| 1544 | ch9_eval_int (ch, CHINT_SEQC); /* not during data */
|
Bob Supnik | a37e928 | 2017-03-20 07:46:28 -0700 | [diff] [blame] | 1545 | /* fall through */
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1546 | case CH9_TCM: /* jumps */
|
| 1547 | case CH9_TCH:
|
| 1548 | case CH9_TDC:
|
| 1549 | case CH9_LIPT:
|
| 1550 | case CH9_LIP:
|
| 1551 | ch_req |= REQ_CH (ch); /* process in chan */
|
| 1552 | break;
|
| 1553 |
|
| 1554 | case CH9_CTL: /* control */
|
| 1555 | case CH9_CTLR:
|
| 1556 | case CH9_CTLW:
|
| 1557 | if (ch_flags[ch] & (CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS))
|
| 1558 | ch9_eval_int (ch, CHINT_SEQC); /* not during data */
|
| 1559 | ch_flags[ch] &= ~CHF_EOR;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1560 | if (ch_wc[ch] & CH9D_NST) /* N set? proc in chan */
|
| 1561 | ch_req |= REQ_CH (ch);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1562 | else return ch9_sel (ch, CHSL_CTL); /* sel, dev sets ch_req! */
|
| 1563 | break;
|
| 1564 |
|
| 1565 | case CH9_SNS: /* sense */
|
| 1566 | if (ch_flags[ch] & (CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS))
|
| 1567 | ch9_eval_int (ch, CHINT_SEQC);
|
| 1568 | ch_flags[ch] &= ~CHF_EOR;
|
| 1569 | ch_req |= REQ_CH (ch); /* process in chan */
|
| 1570 | break;
|
| 1571 |
|
| 1572 | case CH9_CPYD: /* data transfers */
|
| 1573 | case CH9_CPYP:
|
| 1574 | if ((ch_flags[ch] & (CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS)) == 0)
|
| 1575 | ch9_eval_int (ch, CHINT_SEQC); /* not unless data */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1576 | if (ch_flags[ch] & CHF_PRD)
|
| 1577 | ch_flags[ch] |= CHF_RDS;
|
| 1578 | else if (ch_flags[ch] & CHF_PWR)
|
| 1579 | ch_flags[ch] |= CHF_WRS;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1580 | ch_flags[ch] &= ~(CHF_EOR|CHF_PRD|CHF_PWR);
|
| 1581 | if ((ch_op[ch] == CH9_CPYP) && (ch_wc[ch] == 0))
|
| 1582 | ch_req |= REQ_CH (ch); /* CPYP x,,0? */
|
| 1583 | break; /* dev sets ch_req! */
|
| 1584 |
|
| 1585 | case CH9_WTR: /* wait */
|
| 1586 | ch_sta[ch] = CHXS_IDLE; /* stop */
|
| 1587 | break;
|
| 1588 |
|
| 1589 | case CH9_TWT: /* trap and wait */
|
| 1590 | ch_sta[ch] = CHXS_IDLE; /* stop */
|
| 1591 | ch_flags[ch] |= CHF_TWT; /* set trap */
|
| 1592 | break;
|
| 1593 |
|
| 1594 | default:
|
| 1595 | return STOP_ILLIOP;
|
| 1596 | }
|
| 1597 |
|
| 1598 | return SCPE_OK;
|
| 1599 | }
|
| 1600 |
|
| 1601 | /* 7909 external interface routines */
|
| 1602 |
|
| 1603 | /* Input - store word, request channel input service */
|
| 1604 |
|
| 1605 | t_stat ch9_req_rd (uint32 ch, t_uint64 val)
|
| 1606 | {
|
| 1607 | if (ch < NUM_CHAN) { /* valid chan? */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1608 | if (ch_idf[ch] & CH9DF_VLD) /* prev still valid? io chk */
|
| 1609 | ch9_set_ioc (ch);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1610 | ch_idf[ch] = CH9DF_VLD; /* set ar valid */
|
| 1611 | ch_req |= REQ_CH (ch); /* request chan */
|
| 1612 | ch_ar[ch] = val & DMASK; /* save data */
|
| 1613 | }
|
| 1614 | return SCPE_OK;
|
| 1615 | }
|
| 1616 |
|
| 1617 | /* Set attention */
|
| 1618 |
|
| 1619 | void ch9_set_atn (uint32 ch)
|
| 1620 | {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1621 | if (ch < NUM_CHAN)
|
| 1622 | ch9_eval_int (ch, CHINT_ATN1);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1623 | return;
|
| 1624 | }
|
| 1625 |
|
| 1626 | /* Set IO check - UEND will occur at end - not recognized in int mode */
|
| 1627 |
|
| 1628 | void ch9_set_ioc (uint32 ch)
|
| 1629 | {
|
| 1630 | if ((ch < NUM_CHAN) && !(ch_flags[ch] & CHF_INT)) {
|
| 1631 | ind_ioc = 1; /* IO check */
|
| 1632 | ch_flags[ch] |= CHF_IOC; /* ch IOC for end */
|
| 1633 | }
|
| 1634 | return;
|
| 1635 | }
|
| 1636 |
|
| 1637 | /* Set end */
|
| 1638 |
|
| 1639 | void ch9_set_end (uint32 ch, uint32 iflags)
|
| 1640 | {
|
| 1641 | if (ch < NUM_CHAN) { /* valid chan? */
|
| 1642 | ch_flags[ch] |= CHF_EOR;
|
| 1643 | ch9_eval_int (ch, iflags);
|
| 1644 | }
|
| 1645 | return;
|
| 1646 | }
|
| 1647 |
|
| 1648 | /* Test connected */
|
| 1649 |
|
| 1650 | t_bool ch9_qconn (uint32 ch)
|
| 1651 | {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1652 | if ((ch < NUM_CHAN) && (ch_sta[ch] == CHXS_DSX))
|
| 1653 | return TRUE;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1654 | return FALSE;
|
| 1655 | }
|
| 1656 |
|
| 1657 | /* Evaluate interrupts
|
| 1658 |
|
| 1659 | - Interrupt requests set flags in the channel flags word
|
| 1660 | - If an interrupt is not in progress, interrupt requests are evaluated
|
| 1661 | - If an interrupt request is found, the interruptable flags are
|
| 1662 | transferred to the channel condition register and cleared in
|
| 1663 | the channel flags
|
| 1664 |
|
| 1665 | This provides an effective stage of buffering for interrupt requests
|
| 1666 | that are not immediately serviced */
|
| 1667 |
|
| 1668 | void ch9_eval_int (uint32 ch, uint32 iflags)
|
| 1669 | {
|
| 1670 | uint32 ireq;
|
| 1671 |
|
| 1672 | ch_flags[ch] |= (iflags << CHF_V_COND); /* or into chan flags */
|
| 1673 | if ((ch_flags[ch] & CHF_INT) == 0) { /* int not in prog? */
|
| 1674 | ireq = ((ch_flags[ch] >> CHF_V_COND) & CHF_M_COND) &
|
| 1675 | ~(((ch_sms[ch] & CHSMS_IUEND)? CHINT_UEND: 0) |
|
| 1676 | ((ch_sms[ch] & CHSMS_IATN1)? CHINT_ATN1: 0) |
|
| 1677 | ((ch_sms[ch] & CHSMS_IATN2)? CHINT_ATN2: 0) |
|
| 1678 | ((ch_flags[ch] & (CHF_PRD|CHF_PWR|CHF_RDS|CHF_WRS))? CHINT_SEQC: 0));
|
| 1679 | if (ireq) { /* int pending? */
|
| 1680 | ch_cnd[ch] = ireq; /* set cond reg */
|
| 1681 | ch_flags[ch] &= ~(ireq << CHF_V_COND); /* clear chan flags */
|
| 1682 | ch_flags[ch] |= CHF_IRQ; /* set int req */
|
| 1683 | ch_req |= REQ_CH (ch); /* request channel */
|
| 1684 | }
|
| 1685 | }
|
| 1686 | return;
|
| 1687 | }
|
| 1688 |
|
| 1689 | /* Test for all channels idle */
|
| 1690 |
|
| 1691 | t_bool ch_qidle (void)
|
| 1692 | {
|
| 1693 | uint32 i;
|
| 1694 |
|
| 1695 | for (i = 0; i < NUM_CHAN; i++) {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1696 | if (ch_sta[i] != CHXS_IDLE)
|
| 1697 | return FALSE;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1698 | }
|
| 1699 | return TRUE;
|
| 1700 | }
|
| 1701 |
|
| 1702 | /* Evaluate/execute channel traps */
|
| 1703 |
|
| 1704 | uint32 chtr_eval (uint32 *decr)
|
| 1705 | {
|
| 1706 | uint32 i, cme;
|
| 1707 |
|
| 1708 | if (!chtr_inht && !chtr_inhi && chtr_enab) {
|
| 1709 | if (BIT_TST (chtr_enab, CHTR_V_CLK) && chtr_clk) { /* clock trap? */
|
| 1710 | if (decr) { /* exec? */
|
| 1711 | chtr_clk = 0; /* clr flag */
|
| 1712 | *decr = 0;
|
| 1713 | }
|
| 1714 | return CHTR_CLK_SAV;
|
| 1715 | }
|
| 1716 | for (i = 0; i < NUM_CHAN; i++) { /* loop thru chan */
|
| 1717 | cme = BIT_TST (chtr_enab, CHTR_V_CME + i); /* cmd/eof enab? */
|
| 1718 | if (cme && (ch_flags[i] & CHF_CMD)) { /* cmd enab and set? */
|
| 1719 | if (decr) { /* exec? */
|
| 1720 | ch_flags[i] &= ~CHF_CMD; /* clr flag */
|
| 1721 | *decr = CHTR_F_CMD;
|
| 1722 | }
|
| 1723 | return (CHTR_CHA_SAV + (i << 1));
|
| 1724 | }
|
| 1725 | if (cme && (ch_flags[i] & CHF_EOF)) { /* eof enab and set? */
|
| 1726 | if (decr) { /* exec? */
|
| 1727 | ch_flags[i] &= ~CHF_EOF; /* clr flag */
|
| 1728 | *decr = CHTR_F_EOF;
|
| 1729 | }
|
| 1730 | return (CHTR_CHA_SAV + (i << 1));
|
| 1731 | }
|
| 1732 | if (BIT_TST (chtr_enab, CHTR_V_TRC + i) && /* trc enab? */
|
| 1733 | (ch_flags[i] & CHF_TRC)) { /* trc flag? */
|
| 1734 | if (decr) { /* exec? */
|
| 1735 | ch_flags[i] &= ~CHF_TRC; /* clr flag */
|
| 1736 | *decr = CHTR_F_TRC;
|
| 1737 | }
|
| 1738 | return (CHTR_CHA_SAV + (i << 1));
|
| 1739 | } /* end if BIT_TST */
|
| 1740 | } /* end for */
|
| 1741 | } /* end if !chtr_inht */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1742 | if (decr)
|
| 1743 | *decr = 0;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1744 | return 0;
|
| 1745 | }
|
| 1746 |
|
| 1747 | /* Channel reset */
|
| 1748 |
|
| 1749 | t_stat ch_reset (DEVICE *dptr)
|
| 1750 | {
|
| 1751 | uint32 ch = dptr - &ch_dev[0]; /* get channel */
|
| 1752 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1753 | if (ch == CH_A) /* channel A fixed */
|
| 1754 | ch2dev[ch] = &mt_dev[0];
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1755 | ch_sta[ch] = 0;
|
| 1756 | ch_flags[ch] = 0;
|
| 1757 | ch_idf[ch] = 0;
|
| 1758 | ch_dso[ch] = 0;
|
| 1759 | ch_dsu[ch] = 0;
|
| 1760 | ch_ndso[ch] = 0;
|
| 1761 | ch_ndsu[ch] = 0;
|
| 1762 | ch_op[ch] = 0;
|
| 1763 | ch_clc[ch] = 0;
|
| 1764 | ch_wc[ch] = 0;
|
| 1765 | ch_ca[ch] = 0;
|
| 1766 | ch_ar[ch] = 0;
|
| 1767 | ch_sms[ch] = 0;
|
| 1768 | ch_cnd[ch] = 0;
|
| 1769 | ch_lcc[ch] = 0;
|
| 1770 | sim_cancel (&ch_unit[ch]);
|
| 1771 | return SCPE_OK;
|
| 1772 | }
|
| 1773 |
|
| 1774 | /* Show channel type */
|
| 1775 |
|
Mark Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 1776 | t_stat ch_show_type (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1777 | {
|
| 1778 | DEVICE *dptr;
|
| 1779 |
|
| 1780 | dptr = find_dev_from_unit (uptr);
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1781 | if (dptr == NULL)
|
| 1782 | return SCPE_IERR;
|
| 1783 | if (dptr->flags & DEV_7909)
|
| 1784 | fputs ("7909", st);
|
| 1785 | else if (dptr->flags & DEV_7289)
|
| 1786 | fputs ("7289", st);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1787 | else fputs ("7607", st);
|
| 1788 | return SCPE_OK;
|
| 1789 | }
|
| 1790 |
|
| 1791 | /* Enable channel, assign device */
|
| 1792 |
|
Mark Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 1793 | t_stat ch_set_enable (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1794 | {
|
| 1795 | DEVICE *dptr, *dptr1;
|
| 1796 | char gbuf[CBUFSIZE];
|
| 1797 | uint32 i, ch;
|
| 1798 |
|
| 1799 | dptr = find_dev_from_unit (uptr);
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1800 | if (dptr == NULL)
|
| 1801 | return SCPE_IERR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1802 | ch = dptr - &ch_dev[0];
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1803 | if ((ch == 0) || !(dptr->flags & DEV_DIS))
|
| 1804 | return SCPE_ARG;
|
| 1805 | if (cptr == NULL)
|
| 1806 | cptr = "TAPE";
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1807 | get_glyph (cptr, gbuf, 0);
|
| 1808 | for (i = 0; dev_table[i].name; i++) {
|
| 1809 | if (strcmp (dev_table[i].name, gbuf) == 0) {
|
| 1810 | dptr1 = ch_map_flags (ch, dev_table[i].flags);
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1811 | if (!dptr1 || !(dptr1->flags & DEV_DIS))
|
| 1812 | return SCPE_ARG;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1813 | dptr->flags &= ~(DEV_DIS|DEV_7909|DEV_7289|DEV_7750|DEV_7631);
|
| 1814 | dptr->flags |= dev_table[i].flags;
|
| 1815 | dptr1->flags &= ~DEV_DIS;
|
| 1816 | ch2dev[ch] = dptr1;
|
| 1817 | return reset_all (0);
|
| 1818 | }
|
| 1819 | }
|
| 1820 | return SCPE_ARG;
|
| 1821 | }
|
| 1822 |
|
| 1823 | /* Map device flags to device pointer */
|
| 1824 |
|
| 1825 | DEVICE *ch_map_flags (uint32 ch, int32 fl)
|
| 1826 | {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1827 | if (fl & DEV_7289)
|
| 1828 | return &drm_dev;
|
| 1829 | if (!(fl & DEV_7909))
|
| 1830 | return &mt_dev[ch];
|
| 1831 | if (fl & DEV_7631)
|
| 1832 | return &dsk_dev;
|
| 1833 | if (fl & DEV_7750)
|
| 1834 | return &com_dev;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1835 | return NULL;
|
| 1836 | }
|
| 1837 |
|
| 1838 | /* Set up channel map */
|
| 1839 |
|
| 1840 | void ch_set_map (void)
|
| 1841 | {
|
| 1842 | uint32 i;
|
| 1843 |
|
| 1844 | for (i = 0; i < NUM_CHAN; i++) {
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1845 | if (ch_dev[i].flags & DEV_DIS)
|
| 1846 | ch2dev[i] = NULL;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1847 | else ch2dev[i] = ch_map_flags (i, ch_dev[i].flags);
|
| 1848 | }
|
| 1849 | return;
|
| 1850 | }
|
| 1851 |
|
| 1852 | /* Disable channel, deassign device */
|
| 1853 |
|
Mark Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 1854 | t_stat ch_set_disable (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1855 | {
|
| 1856 | DEVICE *dptr, *dptr1;
|
| 1857 | UNIT *uptr1;
|
| 1858 | uint32 i, ch;
|
| 1859 |
|
| 1860 | dptr = find_dev_from_unit (uptr);
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1861 | if (dptr == NULL)
|
| 1862 | return SCPE_IERR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1863 | ch = dptr - &ch_dev[0];
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1864 | if ((ch == 0) || (dptr->flags & DEV_DIS) || (cptr != NULL))
|
| 1865 | return SCPE_ARG;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1866 | dptr1 = ch2dev[ch];
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1867 | if (dptr1 == NULL)
|
| 1868 | return SCPE_IERR;
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1869 | if (dptr1->units) {
|
| 1870 | for (i = 0; i < dptr1->numunits; i++) {
|
| 1871 | uptr1 = dptr1->units + i;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1872 | if (dptr1->detach)
|
| 1873 | dptr1->detach (uptr1);
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1874 | else detach_unit (uptr1);
|
| 1875 | }
|
| 1876 | }
|
| 1877 | dptr->flags &= ~(DEV_7909|DEV_7289);
|
| 1878 | dptr->flags |= DEV_DIS;
|
| 1879 | dptr1->flags |= DEV_DIS;
|
| 1880 | return reset_all (0);
|
| 1881 | }
|
| 1882 |
|
| 1883 | /* Show channel that device is on (tapes, 7289, 7909 only) */
|
| 1884 |
|
Mark Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 1885 | t_stat ch_show_chan (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
Bob Supnik | dc871fa | 2006-05-27 11:34:00 -0700 | [diff] [blame] | 1886 | {
|
| 1887 | DEVICE *dptr;
|
| 1888 | uint32 i;
|
| 1889 |
|
| 1890 | dptr = find_dev_from_unit (uptr);
|
| 1891 | if (dptr) {
|
| 1892 | for (i = 0; i < NUM_CHAN; i++) {
|
| 1893 | if (ch2dev[i] == dptr) {
|
| 1894 | fprintf (st, "channel %c", 'A' + i);
|
| 1895 | return SCPE_OK;
|
| 1896 | }
|
| 1897 | }
|
| 1898 | }
|
| 1899 | fprintf (st, "not assigned to channel");
|
| 1900 | return SCPE_OK;
|
| 1901 | }
|