/* hp3000_cpu_ims.h: HP 3000 CPU-to-IOP/MPX/SEL/CPP interface declarations

   Copyright (c) 2016-2023, J. David Bryan

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
   AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

   Except as contained in this notice, the name of the author shall not be used
   in advertising or otherwise to promote the sale, use or other dealings in
   this Software without prior written authorization from the author.

   28-Mar-23    JDB     Added cpp_io_op routine declaration
   01-Mar-23    JDB     Added globals for imb_initialization, cpp_request,
                        cpp_service, and fprint_cpi
   22-Nov-22    JDB     Added cpp_cold_load routine declaration
   08-Apr-21    JDB     Expanded bank register widths from 4 to 6 bits
   10-Oct-16    JDB     Moved cpu_read_memory, cpu_write_memory to hp3000_cpu.h
   01-Sep-16    JDB     Added the cpu_cold_cmd and cpu_power_cmd routines
   15-Aug-16    JDB     Removed obsolete comment mentioning iop_read/write_memory
   15-Jul-16    JDB     Corrected the IOCW_COUNT macro to return the correct value
   11-Jun-16    JDB     Bit mask constants are now unsigned
   05-Sep-15    JDB     First release version
   11-Dec-12    JDB     Created


   This file contains declarations used by the CPU to interface with the HP 3000
   I/O Processor, Multiplexer Channel, Selector Channel, and Channel Program
   Processor.
*/



/* Global data structures */


/* I/O commands.

   The enumeration values correspond to the IOP bus IOCMD0-2 signal
   representations.
*/

typedef enum {
    ioSIN  = 0,                                 /* set interrupt */
    ioCIO  = 1,                                 /* control I/O */
    ioSIO  = 2,                                 /* start I/O */
    ioWIO  = 3,                                 /* write I/O */
    ioRIN  = 4,                                 /* reset interrupt */
    ioTIO  = 5,                                 /* test I/O */
    ioSMSK = 6,                                 /* set interrupt mask */
    ioRIO  = 7                                  /* read I/O */
    } IO_COMMAND;


/* SIO program orders.

   32-bit I/O program words are formed from a 16-bit I/O control word (IOCW) and
   a 16-bit I/O address word (IOAW).  The Interrupt, Control, Sense, Write, and
   Read orders use this format:

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | C |   order   |           control word 1/word count           |  IOCW
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     |                 control word 2/status/address                 |  IOAW
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

   For the Write and Read orders only, bit 0 of the IOCW is the "data chain"
   flag.  If it is set, then this transfer is a continuation of the previous
   Write or Read transfer.

   The Jump, End, Return Residue, and Set Bank orders require an additional bit
   (IOCW bit 4) to define their orders fully:

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | - |     order     | -   -   -   -   -   -   -   -   -   -   - |  IOCW
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     |                     address/status/count                      |  IOAW
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | -   -   -   -   -   -   -   -   -   - | *   * : *   * : bank  |  IOAW
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

   The bank number occupies two bits in a Series II or four bits in a Series
   III, although MPE-V/R can accommodate bank numbers up to six bits in length.

   In simulation, IOCW bits 0-4 are used to index into a 32-element lookup table
   to produce the final I/O order (because some of the orders define IOCW bit 4
   as "don't care", there are only thirteen distinct orders).


   Implementation notes:

    1. The IOCW_COUNT(w) macro sign-extends the 12-bit two's-complement word
       count to a 16-bit value for the Return Residue order.

    2. The sioWRITE, sioWRITEC, sioREAD, and sioREADC enumeration constants must
       be contiguous and the final four values, so that a ">= sioWRITE" test
       identifies all four cases.
*/

#define IOCW_DC             0100000u            /* data chain */
#define IOCW_SIO_MASK       0070000u            /* general SIO order mask */
#define IOCW_ORDER_MASK     0174000u            /* fully decoded I/O order mask */
#define IOCW_CNTL_MASK      0007777u            /* control word mask */
#define IOCW_WCNT_MASK      0007777u            /* word count mask */

#define IOAW_BANK_MASK      0000077u            /* 6-bit bank number mask */

#define IOCW_ORDER_SHIFT    11                  /* I/O order alignment shift */
#define IOCW_CNTL_SHIFT     0                   /* control word alignment shift */
#define IOCW_WCNT_SHIFT     0                   /* word count alignment shift */

#define IOAW_BANK_SHIFT     0                   /* bank number alignment shift */

#define IOCW_ORDER(w)       to_sio_order [((w) & IOCW_ORDER_MASK) >> IOCW_ORDER_SHIFT]

#define IOCW_CNTL(w)        (((w) & IOCW_CNTL_MASK) >> IOCW_CNTL_SHIFT)
#define IOCW_WCNT(w)        (((w) & IOCW_WCNT_MASK) >> IOCW_WCNT_SHIFT)
#define IOCW_COUNT(w)       ((w) | ~IOCW_WCNT_MASK & D16_MASK)

#define IOAW_BANK(w)        ((w) >> IOAW_BANK_SHIFT & mem_bank_mask)


typedef enum {
    sioJUMP,                                    /* Jump unconditionally */
    sioJUMPC,                                   /* Jump conditionally */
    sioRTRES,                                   /* Return residue */
    sioSBANK,                                   /* Set bank */
    sioINTRP,                                   /* Interrupt */
    sioEND,                                     /* End */
    sioENDIN,                                   /* End with interrupt */
    sioCNTL,                                    /* Control */
    sioSENSE,                                   /* Sense */
    sioWRITE,                                   /* Write */
    sioWRITEC,                                  /* Write chained */
    sioREAD,                                    /* Read */
    sioREADC                                    /* Read chained */
    } SIO_ORDER;


/* Global CPU routine declarations.

   cpu_cold_cmd     : process the LOAD and DUMP commands
   cpu_power_cmd    : process the POWER commands
*/

extern t_stat cpu_cold_cmd  (int32 arg, char *buf);
extern t_stat cpu_power_cmd (int32 arg, char *buf);


/* Global SIO order structures.

   to_sio_order   : translates IOCW bits 1-4 to an SIO_ORDER
   sio_order_name : the name of the orders indexed by SIO_ORDER
*/

extern const SIO_ORDER   to_sio_order   [];
extern const char *const sio_order_name [];


/* Global I/O processor state and functions.

   iop_interrupt_request_set : the set of devices requesting interrupts

   iop_initialize   : initialize the I/O processor
   iop_poll         : poll the interfaces for an active interrupt request
   iop_direct_io    : dispatch an I/O command to an interface
*/

extern uint32 iop_interrupt_request_set;

extern uint32  iop_initialize   (void);
extern uint32  iop_poll         (void);
extern HP_WORD iop_direct_io    (HP_WORD device_number, IO_COMMAND io_cmd, HP_WORD write_value);


/* Global multiplexer channel state and functions.

   mpx_request_set : the set of pending channel service requests

   mpx_initialize : initialize the multiplexer channel
   mpx_service    : poll the interfaces for an active service request
*/

extern uint32 mpx_request_set;

extern void mpx_initialize (void);
extern void mpx_service    (uint32 ticks_elapsed);


/* Global selector channel state and functions

   sel_request : TRUE if a pending channel service request

   sel_initialize : initialize the selector channel
   sel_service    : service the interface with an active service request
*/

extern t_bool sel_request;

extern void sel_initialize (void);
extern void sel_service    (uint32 ticks_elapsed);


/* Global Channel Program Processor state and functions.

   cpp_request : delay until a pending channel processor request is serviced

   cpp_io        : execute an HP-IB I/O operation
   cpp_service   : run the channel program processor to service a request
   cpp_cold_load : cold load a program from a GIC device
   fprint_cpi    : format and print a channel program instruction
*/

typedef struct {                                /* channel processor I/O result */
    HP_WORD  data;                              /*   16-bit return data */
    HP_WORD  condition;                         /*   16-bit condition code */
    } IO_RESULT;

extern uint32 cpp_request;

extern IO_RESULT cpp_io_op     (uint32 opcode, HP_WORD opnd_1, HP_WORD opnd_2);
extern void      cpp_service   (uint32 ticks_elapsed);
extern t_bool    cpp_cold_load (uint32 cold_load_device);
extern t_stat    fprint_cpi    (FILE *ofile, t_value *val, uint32 radix, t_addr addr, UNIT *uptr);


/* Global Intermodule Bus functions.

   imb_initialize : initialize the Intermodule Bus
*/

extern t_bool imb_initialize (void);
