root/src/dps8/dps8_iom.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


   1 /*
   2  * vim: filetype=c:tabstop=4:ai:expandtab
   3  * SPDX-License-Identifier: ICU
   4  * scspell-id: 8e66ce24-f62e-11ec-8690-80ee73e9b8e7
   5  *
   6  * ---------------------------------------------------------------------------
   7  *
   8  * Copyright (c) 2007-2013 Michael Mondy
   9  * Copyright (c) 2012-2016 Harry Reed
  10  * Copyright (c) 2013-2022 Charles Anthony
  11  * Copyright (c) 2026 Eric Swenson
  12  * Copyright (c) 2026 Jeffrey H. Johnson
  13  * Copyright (c) 2021-2025 The DPS8M Development Team
  14  *
  15  * This software is made available under the terms of the ICU License.
  16  * See the LICENSE.md file at the top-level directory of this distribution.
  17  *
  18  * ---------------------------------------------------------------------------
  19  */
  20 
  21 // IDCW Instruction                   18-20  111
  22 // TDCW Transfer                      18-20 !111,  22-23 10
  23 // IOTD IO Transfer and disconnect    18-20 !111,  22-23 00
  24 // IOTP IO Transfer and proceed       18-20 !111,  22-23 01
  25 // IONTP IO Non-Transfer and proceed  18-20 !111,  22-23 11
  26 
  27 #if defined(IO_THREADZ)
  28 extern __thread uint this_iom_idx;
  29 extern __thread uint this_chan_num;
  30 //extern __thread bool thisIOMHaveLock;
  31 #endif
  32 
  33 //typedef enum
  34   //{
  35     //cm_LPW_init_state,       // No TDCWs encountered; state is:
  36                              ////    PCW64 (pcw64_pge): on   PAGE CHAN
  37                              ////    PCW64 (pcw64_pge): off  EXT MODE CHAN
  38     //cm_real_LPW_real_DCW,
  39     //cm_ext_LPW_real_DCW,
  40     //cm_paged_LPW_seg_DCW
  41   //} chanMode_t;
  42 
  43 typedef enum chanStat
  44   {
  45     chanStatNormal          = 0,
  46     chanStatUnexpectedPCW   = 1,
  47     chanStatInvalidInstrPCW = 2,
  48     chanStatIncorrectDCW    = 3,
  49     chanStatIncomplete      = 4,
  50     chanStatUnassigned      = 5,
  51     chanStatParityErrPeriph = 6,
  52     chanStatParityErrBus    = 7
  53   } chanStat;
  54 
  55 // Due to lack of documentation, chan_cmd is largely ignored
  56 //
  57 // iom_chan_control_words.incl.pl1
  58 //
  59 //   SINGLE_RECORD       init ("00"b3),
  60 //   NONDATA             init ("02"b3),
  61 //   MULTIRECORD         init ("06"b3),
  62 //   SINGLE_CHARACTER    init ("10"b3)
  63 //
  64 // bound_tolts_/mtdsim_.pl1
  65 //
  66 //    idcw.chan_cmd = "40"b3;           /* otherwise set special cont. cmd */
  67 //
  68 // bound_io_tools/exercise_disk.pl1
  69 //
  70 //   idcw.chan_cmd = INHIB_AUTO_RETRY; /* inhibit mpc auto retries */
  71 //   dcl     INHIB_AUTO_RETRY       bit (6) int static init ("010001"b);  // 021
  72 //
  73 // poll_mpc.pl1:
  74 //  /* Build dcw list to get statistics from EURC MPC */
  75 //  idcw.chan_cmd = "41"b3;            /* Indicate special controller command */
  76 //  /* Build dcw list to get configuration and statistics from DAU MSP */
  77 //  idcw.chan_cmd = "30"b3;                           /* Want list in dev# order */
  78 //
  79 // tape_ioi_io.pl1:
  80 //   idcw.chan_cmd = "03"b3;          /* data security erase */
  81 //   dcw.chan_cmd = "30"b3;           /* use normal values, auto-retry */
  82 
  83 // iom_word_macros.incl.alm
  84 //
  85 // Channel control
  86 #define CHAN_CTRL_TERMINATE 0
  87 #define CHAN_CTRL_PROCEED   2
  88 #define CHAN_CTRL_MARKER    3
  89 
  90 // Channel command
  91 #define CHAN_CMD_RECORD      0
  92 #define CHAN_CMD_NONDATA     2
  93 #define CHAN_CMD_MULTIRECORD 6
  94 #define CHAN_CMD_CHARACTER   8
  95 
  96 #define IS_IDCW(p)     ((p)->DCW_18_20_CP == 07)
  97 #define IS_NOT_IDCW(p) ((p)->DCW_18_20_CP != 07)
  98 #define IS_TDCW(p)     ((p)->DCW_18_20_CP !=  7 && (p)->DDCW_22_23_TYPE == 2)
  99 #define IS_IOTD(p)     ((p)->DCW_18_20_CP !=  7 && (p)->DDCW_22_23_TYPE == 0)
 100 #define IS_IONTP(p)    ((p)->DCW_18_20_CP !=  7 && (p)->DDCW_22_23_TYPE == 3)
 101 
 102 // exercise_disk.pl1
 103 #define CHAN_CMD_INHIB_AUTO_RETRY    021
 104 // load_mpc.pl1
 105 #define CHAN_CMD_SPECIAL_CTLR        040
 106 // poll_mpc.pl1
 107 #define CHAN_CMD_DEV_ORDER           030
 108 #define CHAN_CMD_SPECIAL_CTLR2       041
 109 // tape_ioi_io.pl1
 110 #define CHAN_CMD_DATA_SECURITY_ERASE  03
 111 #define CHAN_CMD_NORM_AUTO_TRY       030
 112 
 113 typedef volatile struct
 114   {
 115 // scratch pad
 116 
 117     // packed LPW
 118     word36 LPW;
 119     // unpacked LPW
 120     word18 LPW_DCW_PTR;
 121     word1 LPW_18_RES;
 122     word1 LPW_19_REL;
 123     word1 LPW_20_AE;
 124     word1 LPW_21_NC;
 125     word1 LPW_22_TAL;
 126     word1 LPW_23_REL;
 127     word12 LPW_TALLY;
 128 
 129     // packed LPWX
 130     word36 LPWX;
 131     // unpacked LPWX
 132     word18 LPWX_BOUND; // MOD 2 (pg B16) 0-2^19; ie val = LPX_BOUND * 2
 133     word18 LPWX_SIZE;  // MOD 1 (pg B16) 0-2^18
 134 
 135 // PCW_63_PTP indicates paging mode; indicates that a page table
 136 // is available.
 137 // XXX pg B11: cleared by a terminate interrupt service with the
 138 // character size bit of the transaction command = 1. (bit 32)
 139 // what is the 'transaction command.?
 140 
 141     // packed PCW
 142     word36 PCW0, PCW1;
 143     // unpacked PCW
 144     word6 PCW_CHAN;
 145     word6 PCW_AE;
 146     // Pg B2: "Absolute location (MOD 64) of the channels Page Table"
 147     word18 PCW_PAGE_TABLE_PTR;
 148     word1 PCW_63_PTP;
 149     word1 PCW_64_PGE;
 150     word1 PCW_65_AUX; // XXX
 151     word1 PCW_21_MSK; // Sometimes called 'M' // see 3.2.2, pg 25
 152 
 153     // packed DCW
 154     word36 DCW;
 155     // unpacked DCW
 156     // TDCW only
 157     word18 TDCW_DATA_ADDRESS;
 158     word1  TDCW_34_RES;
 159     word1  TDCW_35_REL;
 160     // TDCW, PCW 64 = 0
 161     word1  TDCW_33_EC;
 162     // TDCW, PCW 64 = 1
 163     word1  TDCW_31_SEG;
 164     word1  TDCW_32_PDTA;
 165     word1  TDCW_33_PDCW;
 166     // IDCW only
 167     word6  IDCW_DEV_CMD;
 168     word6  IDCW_DEV_CODE;
 169     word6  IDCW_AE;
 170     word1  IDCW_EC;
 171     word2  IDCW_CHAN_CTRL; // 0 terminate, 2 process, 3 marker
 172     word6  IDCW_CHAN_CMD;
 173     // POLTS sets this to one if there are IOTxes.
 174     word6  IDCW_COUNT;
 175     // DDCW only
 176     /*word18*/ uint DDCW_ADDR; // Allow overflow detection
 177     word12 DDCW_TALLY;
 178     word2  DDCW_22_23_TYPE; // '2' indicates TDCW
 179     // xDCW
 180     word3  DCW_18_20_CP; // '7' indicates IDCW
 181     // XXX pg 30; the indirect data service needs to use this.
 182 
 183     word6 ADDR_EXT; // 3.2.2, 3.2.3.1
 184     word1 SEG;  // pg B21
 185 
 186     enum { /* PGE */ cm1, cm2, cm3a, cm3b, cm4, cm5,
 187            /* EXT */ cm1e, cm2e } chanMode;
 188 
 189 // XXX CP XXXX
 190 // "Specifies the positions of the first character with the first word
 191 // of the block. The byte size, defined by the channel, determines
 192 // what CP values are valid/
 193 //  6 bit: 0-5; 9 bit: 0-4; 18 bit: 0-1; 36 bit: 0-6
 194 //
 195 // For word channels, CP is sent to the channel during list service,
 196 // and is zeros when placed in the mailbox for subsequent data
 197 // services to the channel.
 198 //
 199 //  [CAC: I think that this can be elided. To implement correctly,
 200 //  iom_list_service and/or doPayloadChannel would have to know the
 201 //  word or sub-word functionality of the channel. But it would
 202 //  be simpler to let the device handler just access the CP data,
 203 //  and make it's own decisions about "zeros". After all, it is
 204 //  not clear what a non-zero CP means for a word channel.]
 205 //
 206 // For sub-word channels which depend on IOM Central for packing and
 207 // unpacking words, [IOM Central uses and updates the CP to access
 208 // sub-words].
 209 //
 210 //  [CAC: Again, I think that this can be elided. It is simpler to
 211 //  to have the device handler pack and unpack.]
 212 //
 213 
 214 // LPW addressing mode
 215 
 216     //enum { LPW_REAL, LPW_EXT, LPW_PAGED, LPW_SEG } lpwAddrMode;
 217 
 218     // pg B2: "Scratchpad area for two Page Table Words ... one
 219     // for the DCW List (PTW-LPW) and one for the data (PTW-DCW).
 220 
 221     // PTW format: (pg B8)
 222     //   4-17: Address of page table, mod 64
 223     //   31: WRC: Write control bit (1: page may be written)
 224     //   32: HSE: Housekeeping
 225     //   33: PGP: Page present
 226     // To read or write PGP must be 1
 227     // To write, WRC must be 1, HSE 0; system fault 15 on fail
 228 // pg b8: PTWs are used iff (indirect store and LPw 23 (segmented)), or
 229 // direct store.
 230 //
 231 //  ADDR  0-13 <- PTW 4-17
 232 //       14-23 <- LPW 8-17; DCW 8-17; direct channel address 14-23
 233 
 234     word36 PTW_DCW;  // pg B8.
 235     word36 PTW_LPW;  // pg B6.
 236 
 237 // pg b11 defines two PTW flags to indicate the validity of the
 238 // PTW_DCW and PTW_LPW; it is simpler to simply always fetch
 239 // the PTWs on demand.
 240 
 241 //  flag
 242     //chanMode_t chanMode;
 243 
 244     // true if the DCW is from a PCW
 245     bool isPCW;
 246 
 247     // Information accumulated for status service.
 248     word12 stati;
 249     uint dev_code;
 250     // Initialized to IDCW_COUNT; decremented when a IDCW that expects an IOTx is processed by the channel.
 251     // XXX POLTS console code drives this; if it turns out to be common across channels, the decrement should
 252     // be moved into the IOM.
 253     word6 recordResidue;
 254     word12 tallyResidue;
 255     word3 charPos;
 256     bool isRead;
 257     // isOdd can be ignored; see https://ringzero.wikidot.com/wiki:cac-2015-10-22
 258     // bool isOdd;
 259     bool initiate;
 260 
 261     chanStat chanStatus;
 262 
 263     bool lsFirst;
 264 
 265     bool wasTDCW;
 266 
 267     bool masked;
 268 
 269     bool in_use;
 270 
 271     bool start;
 272 
 273   } iom_chan_data_t;
 274 
 275 extern iom_chan_data_t iom_chan_data [N_IOM_UNITS_MAX] [MAX_CHANNELS];
 276 
 277 extern DEVICE iom_dev;
 278 
 279 // Indirect data service data type
 280 typedef enum
 281   {
 282     idsTypeW36  // Incoming data is array of word36
 283   } idsType;
 284 
 285 typedef enum
 286   {
 287     direct_load,
 288     direct_store,
 289     direct_read_clear,
 290   } iom_direct_data_service_op;
 291 
 292 
 293 
 294 
 295 
 296 
 297 
 298 
 299 
 300 
 301 
 302 
 303 
 304 
 305 
 306 
 307 
 308 
 309 
 310 
 311 
 312 
 313 
 314 
 315 
 316 
 317 
 318 
 319 
 320 
 321 
 322 
 323 
 324 
 325 
 326 
 327 
 328 #define IOM_MBX_LPW     0
 329 #define IOM_MBX_LPWX    1
 330 #define IOM_MBX_SCW     2
 331 #define IOM_MBX_DCW     3
 332 
 333 /* From AN70-1 May84
 334  *  ... The IOM determines an interrupt
 335  * number. (The interrupt number is a five bit value, from 0 to 31.
 336  * The high order bits are the interrupt level.
 337  *
 338  * 0 - system fault
 339  * 1 - terminate
 340  * 2 - marker
 341  * 3 - special
 342  *
 343  * The low order three bits determines the IOM and IOM channel
 344  * group.
 345  *
 346  * 0 - IOM 0 channels 32-63
 347  * 1 - IOM 1 channels 32-63
 348  * 2 - IOM 2 channels 32-63
 349  * 3 - IOM 3 channels 32-63
 350  * 4 - IOM 0 channels 0-31
 351  * 5 - IOM 1 channels 0-31
 352  * 6 - IOM 2 channels 0-31
 353  * 7 - IOM 3 channels 0-31
 354  *
 355  *   3  3     3   3   3
 356  *   1  2     3   4   5
 357  *  ---------------------
 358  *  | pic | group | iom |
 359  *  -----------------------------
 360  *       2       1     2
 361  */
 362 
 363 enum iomImwPics
 364   {
 365     imwSystemFaultPic = 0,
 366     imwTerminatePic   = 1,
 367     imwMarkerPic      = 2,
 368     imwSpecialPic     = 3
 369   };
 370 
 371 int send_general_interrupt (uint iom_unit_idx, uint chan, enum iomImwPics pic);
 372 
 373 int send_special_interrupt (uint iom_unit_idx, uint chanNum, uint devCode,
 374                             word8 status0, word8 status1);
 375 //
 376 // iom_cmd_t returns:
 377 //
 378 //  0: ok
 379 //  1; ignored cmd, drop connect.
 380 //  2: did command, don't do DCW list
 381 //  3; command pending, don't sent terminate interrupt
 382 // -1: error
 383 
 384 //#define IOM_CMD_OK       0
 385 //#define IOM_CMD_IGNORED  1
 386 //#define IOM_CMD_NO_DCW   2
 387 //#define IOM_CMD_PENDING  3
 388 //#define IOM_CMD_ERROR   -1
 389 
 390 typedef enum
 391   {
 392      IOM_CMD_ERROR   = -1,
 393      IOM_CMD_PROCEED =  0,
 394      IOM_CMD_RESIDUE,
 395      IOM_CMD_DISCONNECT,
 396      IOM_CMD_PENDING
 397   } iom_cmd_rc_t;
 398 
 399 typedef iom_cmd_rc_t iom_cmd_t (uint iom_unit_idx, uint chan);
 400 int iom_list_service (uint iom_unit_idx, uint chan,
 401                       bool * ptro, bool * sendp, bool * uffp);
 402 int send_terminate_interrupt (uint iom_unit_idx, uint chanNum);
 403 void iom_interrupt (uint scuUnitNum, uint iom_unit_idx);
 404 void iom_direct_data_service (uint iom_unit_idx, uint chan, word24 daddr, word36 * data,
 405                               iom_direct_data_service_op op);
 406 void iom_indirect_data_service (uint iom_unit_idx, uint chan, word36 * data,
 407                                 uint * cnt, bool write);
 408 void iom_init (void);
 409 int send_marker_interrupt (uint iom_unit_idx, int chan);
 410 void iom_advance_lpw (uint iom_unit_idx, uint chan);
 411 int iom_continue_channel (uint iom_unit_idx, uint chan);
 412 #if defined(PANEL68)
 413 void do_boot (void);
 414 #endif
 415 #if defined(IO_THREADZ)
 416 void * iom_thread_main (void * arg);
 417 void * chan_thread_main (void * arg);
 418 #endif
 419 void iom_core_read (uint iom_unit_idx, word24 addr, word36 *data, UNUSED const char * ctx);
 420 void iom_core_read2 (uint iom_unit_idx, word24 addr, word36 *even, word36 *odd, UNUSED const char * ctx);
 421 void iom_core_write (uint iom_unit_idx, word24 addr, word36 data, UNUSED const char * ctx);
 422 void iom_core_write2 (uint iom_unit_idx, word24 addr, word36 even, word36 odd, UNUSED const char * ctx);
 423 void iom_core_read_lock (uint iom_unit_idx, word24 addr, word36 *data, UNUSED const char * ctx);
 424 void iom_core_write_unlock (uint iom_unit_idx, word24 addr, word36 data, UNUSED const char * ctx);
 425 t_stat iom_unit_reset_idx (uint iom_unit_idx);
 426 
 427 #if defined(IO_ASYNC_PAYLOAD_CHAN) || defined(IO_ASYNC_PAYLOAD_CHAN_THREAD)
 428 void iomProcess (void);
 429 #endif
 430 
 431 char iomChar (uint iomUnitIdx);
 432 #if defined(TESTING)
 433 void dumpDCW (word36 DCW, word1 LPW_23_REL);
 434 #endif

/* [previous][next][first][last][top][bottom][index][help] */