/* hp3000_imb.h: HP 3000 Intermodule Bus interface declarations

   Copyright (c) 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.

   09-Jun-23    JDB     First release
   18-May-22    JDB     Created


   This file contains declarations used by I/O channels to interface with the
   Intermodule Bus.  It is required by any module that interacts with the IMB.
*/



/* Channel identifiers (as reported in register 14) */

#define GIC_ID              0                   /* General I/O Channel ID = 0000 */
#define ADCC_ID             1                   /* Asynchronous Data Communication Channel ID = 0001 */


/* IMB command accessors */


/* IMB command code accessors.

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     |    Command    |   Register    | - |    Channel    | -   -   - |
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+


   Implementation notes:

    1. Accessors follow the usual convention, except for IMB_COMMAND and
       TO_IMB_COMMAND.  The former takes a command word and an opcode and
       converts to an IMB_IO_COMMAND enumerator.  The latter takes an
       IMB_IO_COMMAND enumerator and converts to a command field.
*/

#define IMB_GLOBAL          HP_BIT  (0)         /* global commands have bit 0 set */
#define IMB_GLOBAL_MASK     HP_BITS (0, 7)      /* global commands do not specify channels */

#define IMB_COMMAND(c,o)    (HP_BITS_TO (0, 2, c) << 1 | (o) == IMB_IO_Write)
#define IMB_REGISTER(w)     HP_BITS_TO (4,  7, w)
#define IMB_CHANNEL(w)      HP_BITS_TO (9, 12, w)

#define TO_IMB_COMMAND(e)   TO_HP_BITS (0,  2, (e) >> 1)
#define TO_IMB_REGISTER(w)  TO_HP_BITS (4,  7, w)
#define TO_IMB_CHANNEL(w)   TO_HP_BITS (9, 12, w)


/* OBII accessors.

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0   0 | N |    Channel    |  Device   |
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

   Where:

     N = Channel and device numbers are not valid
*/

#define OBII_INVALID        HP_BIT (8)          /* (N) channel and device numbers are invalid */

#define OBII_CHANNEL(w)     HP_BITS_TO ( 9, 12, w)      /* channel number */
#define OBII_DEVICE(w)      HP_BITS_TO (13, 15, w)      /* device number */
#define OBII_CHANDEV(w)     HP_BITS_TO ( 9, 15, w)      /* channel and device number */


/* OBSI accessors.

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0 | T | A | S | D | H | N |    Channel    |  Device   |
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

   Where:

     T = Timeout
     A = DMA Abort
     S = SRQ Request
     D = Device Request
     H = Channel Request (including DMA completion)
     N = Channel and Device numbers are not valid
*/

#define OBSI_TIMEOUT        HP_BIT (3)          /* (T) Timeout */
#define OBSI_ABORT          HP_BIT (4)          /* (A) DMA abort */
#define OBSI_SRVRQ          HP_BIT (5)          /* (S) SRQ request */
#define OBSI_DEVRQ          HP_BIT (6)          /* (D) Device request */
#define OBSI_CHNRQ          HP_BIT (7)          /* (H) Channel request */
#define OBSI_INVALID        HP_BIT (8)          /* (N) Channel and device numbers are invalid */

#define OBSI_CHANNEL(w)     HP_BITS_TO ( 9, 12, w)      /* channel number */
#define OBSI_DEVICE(w)      HP_BITS_TO (13, 15, w)      /* device number */


/* SIOP/HIOP accessors.

        0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
      | -   -   -   -   -   -   -   -   -   -   -   - | S |  Device   |
      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

   Where:

     S = New status (0 = set CSRQ/1 = clear CSRQ)
*/

#define SIOP_CLEAR_STATUS   HP_BIT (12)         /* (S) Clear status request */
#define SIOP_SET_STATUS     0u                  /* (S) Set status request */

#define SIOP_DEVICE(w)      HP_BITS_TO (13, 15, w)

#define HIOP_CLEAR_STATUS   HP_BIT (12)         /* (S) Clear status request */
#define HIOP_SET_STATUS     0u                  /* (S) Set status request */

#define HIOP_DEVICE(w)      HP_BITS_TO (13, 15, w)


/* Global IMB state and functions.

   imb_channel_request_set   : the set of channels requesting service
   imb_interrupt_request_set : the set of channels requesting interrupts

   imb_cycle       : execute a general IMB memory or I/O cycle
   imb_io_cycle    : execute an IMB I/O cycle
   imb_io_write    : execute an IMB I/O read cycle
   imb_io_read     : execute an IMB I/O write cycle
   imb_assert_CSRQ : assert the CSRQ1 signal asynchronously
   imb_assert_IRQ  : assert the IRQ signal asynchronously
*/

extern uint32 imb_channel_request_set;
extern uint32 imb_interrupt_request_set;


extern IMB_OUTBOUND imb_cycle       (IMB_OPCODE     opcode,  IMB_ADDRESS address,  IMB_DATA data);
extern IMB_DATA     imb_io_cycle    (IMB_IO_COMMAND command, uint32      channel,  IMB_DATA data);
extern void         imb_io_write    (uint32         channel, uint32      Register, IMB_DATA data);
extern IMB_DATA     imb_io_read     (uint32         channel, uint32      Register);
extern void         imb_assert_CSRQ (uint32         channel);
extern void         imb_assert_IRQ  (uint32         channel);
