/* hp3000_gic.h: HP 3000 31262A General I/O Channel simulator 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
   12-Sep-22    JDB     Created

   References:
     - HP 3000 Series 40/44 Computer Systems Reference/Training Manual
         (30090-90001, July 1981) [pp. 7-21 to 7-39]
     - HP 13255 HP-IB Interface Module
         (13255-91128, April 1979) [pp. 20 to 41]


   This file contains declarations used by the General I/O Channel (GIC) and the
   Channel Program Processor (CPP).  It provides the symbols that allow direct
   manipulation of the channel registers via the IMB I/O Read and I/O Write
   commands.  Registers 0-7 are contained within the Processor-to-HP-IB (PHI)
   chip that provides the bus interface for the GIC.  Registers 8-F are
   implemented in discrete logic on the GIC.
*/



/* PHI and GIC registers */

typedef enum {                                  /* PHI register identifiers */
    Reg_0 = 0,                                  /*   FIFO */
    Reg_1,                                      /*   Status */
    Reg_2,                                      /*   Interrupt Conditions */
    Reg_3,                                      /*   Interrupt Mask */
    Reg_4,                                      /*   Parallel Poll Mask */
    Reg_5,                                      /*   Parallel Poll Sense */
    Reg_6,                                      /*   Control */
    Reg_7,                                      /*   HP-IB Address */

                                                /* GIC register identifiers */
    Reg_8,                                      /*   DMA Extended Address */
    Reg_9,                                      /*   DMA Address */
    Reg_A,                                      /*   DMA Byte Count */
    Reg_B,                                      /*   DMA Status/Control */
    Reg_C,                                      /*   Interrupt Register */
    Reg_D,                                      /*   Interrupt Information */
    Reg_E,                                      /*   Channel Configuration/DMA Abort */
    Reg_F                                       /*   Channel Service Information */
    } REGISTER;


/* Register 0 - FIFO

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0 | -   -   -   -   -   - |    parallel poll responses    | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   1 | -   -   -   -   -   - | 0   0 | T |     secondary     | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0 | -   -   -   -   -   - |           data byte           | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 1   0 | -   -   -   -   -   - |        final data byte        | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 1   1 | -   -   -   -   -   - |       tagged data byte        | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | E | 0 | -   -   -   -   -   - |           data byte           | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   1 | -   -   -   -   -   - | P |   bus interface command   | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | L | 0 | -   -   -   -   -   - |         receive count         | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 1   1 | -   -   -   -   -   - | 0   0   0   0   0   0   0   0 | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 1   1 | -   -   -   -   -   - | 0 |       receive count       | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 1   1 | -   -   -   -   -   - | 1 |        send count         | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R0_MODE_MASK        HP_BITS ( 0, 1)     /* byte mode */
#define R0_TALK             HP_BIT  (10)        /* (T) Talk secondary */

#define R0_MODE(w)          HP_BITS_TO ( 0,  1, w)      /* extract the data mode */
#define R0_PPR(w)           HP_BITS_TO ( 8, 15, w)      /* extract the parallel poll responses */
#define R0_SECONDARY(w)     HP_BITS_TO (11, 15, w)      /* extract the secondary command */
#define R0_DATA(w)          HP_BITS_TO ( 8, 15, w)      /* extract the data byte */

#define R0_TO_MODE(w)       TO_HP_BITS (0, 1, w)        /* set the data mode */

#define R0_MODE_DATA        0u                  /* data byte */
#define R0_MODE_SECONDARY   1u                  /* secondary command byte */
#define R0_MODE_FINAL       2u                  /* final data byte */
#define R0_MODE_TAGGED      3u                  /* tagged data byte */

#define R0_EOI              HP_BIT (0)          /* (E) Tag byte with EOI */
#define R0_NO_LF            HP_BIT (0)          /* (L) Inhibit LF detection */
#define R0_PARITY           HP_BIT (8)          /* (P) Odd parity */

#define R0_COMMAND(w)       HP_BITS_TO ( 9, 15, w)      /* extract the bus command */
#define R0_COUNT(w)         HP_BITS_TO ( 8, 15, w)      /* extract the receive count */

#define R0_MODE_LF_COUNTED  R0_TO_MODE (0)      /* receive ends on count or LF or EOI */
#define R0_MODE_COMMAND     R0_TO_MODE (1)      /* bus interface command */
#define R0_MODE_COUNTED     R0_TO_MODE (2)      /* receive ends on count or EOI */
#define R0_MODE_UNCOUNTED   R0_TO_MODE (3)      /* receive ends on EOI */
#define R0_MODE_RECEIVE     R0_TO_MODE (3)      /* deprecated counted receive enable */


/* Register 1 - Status

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0   0 | -   - | R | C | S | T | L | F | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | -   -   -   -   -   -   -   -   -   -   -   -   -   -   - | F | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R1_REMOTE           HP_BIT (10)         /* (R) PHI is in remote mode */
#define R1_CNTLR            HP_BIT (11)         /* (C) PHI is the controller */
#define R1_SYSCNTLR         HP_BIT (12)         /* (S) PHI is the system controller */
#define R1_TALKER           HP_BIT (13)         /* (T) PHI is addressed to talk */
#define R1_LISTENER         HP_BIT (14)         /* (L) PHI is addressed to listen */
#define R1_FREEZE           HP_BIT (15)         /* (F) Outbound data freeze */

#define R1_CNTLRS(w)        HP_BITS_TO (11, 12, w)



/* Register 2 - Interrupt Conditions

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | I | P | 0   0   0   0   0   0 | C | H | R | S | F | D | E | L | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | - | P | -   -   -   -   -   - | C | H | -   -   -   -   - | L | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R2_PENDING          HP_BIT  (0)         /* (I) Interrupt is pending */
#define R2_PARITY           HP_BIT  (1)         /* (P) Parity error */
#define R2_STATUS           HP_BIT  (8)         /* (C) Status has changed */
#define R2_HSABORT          HP_BIT  (9)         /* (H) Handshake abort for FIFO overflow/underflow */
#define R2_POLL             HP_BIT (10)         /* (R) Parallel poll response present */
#define R2_SRQ              HP_BIT (11)         /* (S) Service Request (SRQ) asserted */
#define R2_AVAIL            HP_BIT (12)         /* (F) Outbound FIFO has space available */
#define R2_DATA             HP_BIT (13)         /* (D) Data available in inbound FIFO */
#define R2_EMPTY            HP_BIT (14)         /* (E) Outbound FIFO is empty */
#define R2_DCL              HP_BIT (15)         /* (L) Device Clear (DCL) received */

#define R2_EVENTS           (R2_PARITY | R2_STATUS | R2_HSABORT | R2_DCL)   /* the set of latched events */


/* Register 3 - Interrupt Mask

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | I | P | 0   0   0   0   0   0 | C | H | R | S | F | D | E | L | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | I | P | -   -   -   -   -   - | C | H | R | S | F | D | E | L | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R3_ENABLE           HP_BIT  (0)         /* (I) Enable all interrupts */
#define R3_PARITY           HP_BIT  (1)         /* (P) Enable parity errors */
#define R3_STATUS           HP_BIT  (8)         /* (C) Enable status changes */
#define R3_OVERFLOW         HP_BIT  (9)         /* (H) Enable FIFO overflows/underflows */
#define R3_POLL             HP_BIT (10)         /* (R) Enable parallel poll responses */
#define R3_SRQ              HP_BIT (11)         /* (S) Enable Service Requests (SRQ) */
#define R3_AVAIL            HP_BIT (12)         /* (F) Enable outbound FIFO space available */
#define R3_DATA             HP_BIT (13)         /* (D) Enable data available */
#define R3_EMPTY            HP_BIT (14)         /* (E) Enable outbound FIFO empty */
#define R3_DCL              HP_BIT (15)         /* (L) Enable Device Clears (DCL) */

#define R3_UNMASK           (R3_PARITY | R3_STATUS | R3_OVERFLOW \
                           | R3_POLL   | R3_SRQ    | R3_AVAIL    \
                           | R3_DATA   | R3_EMPTY  | R3_DCL)    /* unmask all interrupts */


/* Register 4 - Parallel Poll Mask

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0   0 |  parallel poll response mask  | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | -   -   -   -   -   -   -   - |  parallel poll response mask  | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R4_RESPONSE_MASK    HP_BITS (8, 15)     /* poll response mask */


/* Register 5 - Parallel Poll Sense

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0   0 | parallel poll response sense  | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | -   -   -   -   -   -   -   - | parallel poll response sense  | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R5_SENSE_MASK       HP_BITS (8, 15)     /* poll sense mask */


/* Register 6 - Control

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0   0 | B | F | R | I | P | S | D | C | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0 | -   -   -   -   -   - | B | F | R | I | P | S | D | C | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R6_8BIT             HP_BIT  (8)         /* (B) 8-bit processor */
#define R6_FREEZE           HP_BIT  (9)         /* (F) Parity freeze */
#define R6_REN              HP_BIT (10)         /* (R) Remote Enable (REN) bus line */
#define R6_IFC              HP_BIT (11)         /* (I) Interface Clear (IFC) bus line */
#define R6_POLL             HP_BIT (12)         /* (P) Set Parallel Poll response */
#define R6_SRQ              HP_BIT (13)         /* (S) Service Request (SRQ) bus line */
#define R6_OUTBOUND         HP_BIT (14)         /* (D) DMA direction is outbound) */
#define R6_CLEAR            HP_BIT (15)         /* (C) Clear outbound FIFO */
#define R6_INBOUND          0u                  /* (D) DMA direction is inbound */


/* Register 7 - HP-IB Address

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0   0 | O | T | L |    bus address    | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0 | -   -   -   -   -   - | O | T | L |    bus address    | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R7_ONLINE           HP_BIT  (8)         /* (O) PHI is online */
#define R7_TALK_ALWAYS      HP_BIT  (9)         /* (T) PHI is talk always */
#define R7_LISTEN_ALWAYS    HP_BIT (10)         /* (L) PHI is listen always */
#define R7_OFFLINE          0u                  /* (O) PHI is offline */

#define R7_ADDRESS(w)       HP_BITS_TO (11, 15, w)

#define R7_TO_ADDRESS(c)    TO_HP_BITS (11, 15, c)


/* Register 8 - DMA Extended Address

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | E | 0   0 |     DMA state     |      upper address bits       | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0   0 |      upper address bits       | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R8_DMA_ENABLED      HP_BIT (0)          /* (E) DMA is enabled */
#define R8_BANK_MASK        HP_BITS (8, 15)     /* bank mask */

#define R8_DMA_STATE(w)     HP_BITS_TO (3,  7, w)
#define R8_BANK(w)          HP_BITS_TO (8, 15, w)

#define R8_TO_DMA_STATE(s)  TO_HP_BITS (3,  7, s)
#define R8_TO_BANK(b)       TO_HP_BITS (8, 15, b)


/* Register 9 - DMA Address

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     |                      lower address bits                       | read/write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define R9_OFFSET(w)        HP_BITS_TO (0, 15, w)


/* Register A - DMA Byte Count

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     |                          byte count                           | read/write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define RA_COUNT(w)         HP_BITS_TO (0, 15, w)


/* Register B - DMA Status/Control

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | I | P | V | T | 0 | stat  | B | C | R | E | D | S |  Device   | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0 | A | C | R | E | D | G |  Device   | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define RB_IRQ              HP_BIT   (0)        /* (I) PHI interrupt */
#define RB_PARITY           HP_BIT   (1)        /* (P) parity error */
#define RB_OVERFLOW         HP_BIT   (2)        /* (V) address overflow */
#define RB_TIMEOUT          HP_BIT   (3)        /* (T) timeout */
#define RB_DMA_STATUS       HP_BITS  (5, 6)     /* DMA end status */
#define RB_DMA_BUSY         HP_BIT   (7)        /* (B) DMA busy */
#define RB_NO_POLL          HP_BIT   (8)        /* (C) disable CSRQ for Parallel Polls */
#define RB_RIGHT_BYTE       HP_BIT   (9)        /* (R) right-hand byte */
#define RB_NO_EOI           HP_BIT  (10)        /* (E) EOI disabled */
#define RB_DIRECTION        HP_BIT  (11)        /* (D) DMA direction (0/1 = inbound/outbound) */
#define RB_TEST             HP_BIT  (12)        /* (S) diagnostic switch position (0/1 = OPERATE/TEST) */
#define RB_DEV_MASK         HP_BITS (13, 15)    /* device mask */

#define RB_COMMON_BITS      (RB_NO_POLL | RB_RIGHT_BYTE | RB_NO_EOI | RB_DIRECTION | RB_DEV_MASK)

#define RB_STATUS(w)        HP_BITS_TO ( 5,  6, w)      /* extract the DMA status */
#define RB_DEVICE(w)        HP_BITS_TO (13, 15, w)      /* extract the device accessor */
#define RB_ABORT(w)         HP_BITS_TO ( 0, 12, w)      /* extract the reported status for a DMA abort */

#define RB_TO_STATUS(w)     TO_HP_BITS ( 5,  6, w)      /* position the DMA status field */

#define RB_STATUS_TAGGED    0u                  /* ~DMASTATA * ~DMASTATB = tagged byte */
#define RB_STATUS_FINAL     1u                  /* ~DMASTATA *  DMASTATB = final byte */
#define RB_STATUS_RCOUNT    2u                  /*  DMASTATA * ~DMASTATB = DMA count (inbound xfer) */
#define RB_STATUS_ERROR     3u                  /*  DMASTATA *  DMASTATB = DMA error */
#define RB_STATUS_WCOUNT    0u                  /* ~DMASTATA * ~DMASTATB = DMA count (outbound xfer) */

#define RB_NO_INCREMENT     HP_BIT  (7)         /* (A) disable address increment / assert SRQ (only when S5 = TEST) */
#define RB_OUTBOUND         HP_BIT (11)         /* (D) DMA direction is outbound */
#define RB_NO_TEST          HP_BIT (12)         /* (G) Diagnostic disabled (only when S5 = TEST) */
#define RB_INBOUND          0u                  /* (D) DMA direction is inbound */

#define RB_TO_DMA_FLAGS(w)  TO_HP_BITS ( 8, 11, w)      /* position the DMA instruction flag bits */


/* Register C - Interrupt Register

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0   0 |   device interrupt requests   | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | -   -   -   -   -   -   -   -   -   -   -   - | S |  device   | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define RC_SET_IRQ          HP_BIT (12)         /* (S) set interrupt request */
#define RC_CLEAR_IRQ        0u                  /* clear interrupt request */

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


/* Register D - Interrupt Information

       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   | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define RD_INVALID          HP_BIT  (8)         /* (N) Channel and device numbers are not valid */
#define RD_CHANNEL_MASK     HP_BITS (9, 12)

#define RD_CHANNEL(w)       HP_BITS_TO ( 9, 12, w)
#define RD_DEVICE(w)        HP_BITS_TO (13, 15, w)

#define RD_TO_CHANNEL(v)    TO_HP_BITS ( 9, 12, v)
#define RD_TO_DEVICE(v)     TO_HP_BITS (13, 15, v)


/* Register E - Channel Configuration/DMA Abort

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0 | H | C | 0   0   0   0   0   0   0   0   0 |  Channel ID   | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0 | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define RE_HYBRID           HP_BIT (1)          /* (H) Hybrid (switch S2 position 0/1 = A/B) */
#define RE_CPP              HP_BIT (2)          /* (C) CPU/CPP (switch S1 position 0/1 = CPU/CPP) */

#define RE_CHANNEL_ID(w)    HP_BITS_TO (12, 15, w)


/* Register F - Channel Service Information

       0 | 1   2   3 | 4   5   6 | 7   8   9 |10  11  12 |13  14  15
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0 | T | A | S | V | H | N |    Channel    |  Device   | read
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | 0   0   0   0   0   0   0 | A | C | R | E | D | G |  Device   | write
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
*/

#define RF_TIMEOUT          HP_BIT  ( 3)        /* (T) timeout */
#define RF_DMA_ABORT        HP_BIT  ( 4)        /* (A) DMA abort */
#define RF_SRQ              HP_BIT  ( 5)        /* (S) SRQ request (always 0 for GIC Revision D) */
#define RF_DEVRQ            HP_BIT  ( 6)        /* (V) device request */
#define RF_CHNRQ            HP_BIT  ( 7)        /* (H) channel request (including DMA completion) */
#define RF_INVALID          HP_BIT  ( 8)        /* (N) channel and device numbers are not valid */
#define RF_CHANNEL_MASK     HP_BITS ( 9, 12)    /* channel mask */
#define RF_CHANDEV_MASK     HP_BITS ( 9, 15)    /* channel and device mask */
#define RF_DEV_MASK         HP_BITS (13, 15)    /* device mask */

#define RF_NO_INCREMENT     HP_BIT  (7)         /* (A) disable address increment / assert SRQ (only when S5 = TEST) */
#define RF_NO_POLL          HP_BIT  (8)         /* (C) disable CSRQ for Parallel Polls */
#define RF_RIGHT_BYTE       HP_BIT  (9)         /* (R) right-hand byte */
#define RF_NO_EOI           HP_BIT (10)         /* (E) EOI disabled */
#define RF_OUTBOUND         HP_BIT (11)         /* (D) DMA direction is outbound */
#define RF_NO_TEST          HP_BIT (12)         /* (G) Diagnostic disabled (only when S5 = TEST) */
#define RF_INBOUND          0u                  /* (D) DMA direction is inbound */

#define RF_CHANNEL(w)       HP_BITS_TO ( 9, 12, w)
#define RF_DEVICE(w)        HP_BITS_TO (13, 15, w)

#define RF_TO_CHANNEL(v)    TO_HP_BITS ( 9, 12, v)
#define RF_TO_DEVICE(c)     TO_HP_BITS (13, 15, c)



/* HP-IB control and data lines.

   The HP-IB contains eight data lines, three handshake lines, and five
   bus management lines.  The state of the bus is represented by a 16-bit value,
   organized as follows:

                                   DIO 8   7   6   5   4   3   2   1
      15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | S | I | R | D | N | V | E | A | P | Group |      Address      | command
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
     | S | I | R | D | N | V | E | A |           Data Byte           | data
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+

   Where:

     S = SRQ (Service Request)
     I = IFC (Interface Clear)
     R = REN (Remote Enable)
     D = NDAC (Not Data Accepted)
     N = NRFD (Not Ready For Data)
     V = DAV (Data Valid)
     E = EOI (End or Identify)
     A = ATN (Attention)
     P = Odd parity

   Group:

     00 = Primary command group
     01 = Listen address group
     10 = Talk address group
     11 = Secondary command group


   Implementation notes:

    1. We supply type definitions for the bus control lines, data lines, and
       combined lines, but they are all interchangeably represented.

    2. The bit assignments of the SRQ, IFC, REN, EOI, and ATN signals are for
       the convenience of the HP 1000 HP-IB Disc Interface card, which uses this
       order in its status register and so provides a simple mapping.  When the
       signals are traced, the upper eight bits are rotated left by three
       places, producing this order when printed LSB first:

         REN | IFC | SRQ | ATN | EOI | DAV | NRFD | NDAC
*/

typedef enum {                                  /* HP-IB control lines */
    Bus_ATN  = 0000400,                         /*   Attention */
    Bus_EOI  = 0001000,                         /*   End or Identify */
    Bus_DAV  = 0002000,                         /*   Data Valid */
    Bus_NRFD = 0004000,                         /*   Not Ready for Data */
    Bus_NDAC = 0010000,                         /*   Not Data Accepted */
    Bus_REN  = 0020000,                         /*   Remote Enable */
    Bus_IFC  = 0040000,                         /*   Interface Clear */
    Bus_SRQ  = 0100000                          /*   Service Request */
    } BUS_SIGNALS;

typedef BUS_SIGNALS         BUS_CABLE;          /* the sixteen control and data lines */
typedef uint32              BUS_DATA;           /* the eight data lines */

#define BUS_CONTROL_MASK    BITS (15, 8)        /* control lines are in the upper byte */

#define BUS_NONE            0                   /* no signals asserted */
#define BUS_PPOLL           (Bus_ATN | Bus_EOI) /* signals for a parallel poll */

#define BUS_CONTROL(b)      BITS_TO (15, 8, b)  /* extract the control signals */
#define BUS_ADDRESS(b)      BITS_TO ( 4, 0, b)  /* extract the bus address */
#define BUS_GROUP(b)        BITS_TO ( 6, 5, b)  /* extract the bus group */
#define BUS_COMMAND(b)      BITS_TO ( 6, 0, b)  /* extract the bus command */
#define BUS_DATA(b)         BITS_TO ( 7, 0, b)  /* extract the bus data */

#define BUS_PCG             0u                  /* primary command group */
#define BUS_LAG             1u                  /* listen address group */
#define BUS_TAG             2u                  /* talk address group */
#define BUS_SCG             3u                  /* secondary command group */

#define BUS_PRIMARY         TO_BITS (6, 5, BUS_PCG)     /* primary command */
#define BUS_LISTEN          TO_BITS (6, 5, BUS_LAG)     /* listen address */
#define BUS_TALK            TO_BITS (6, 5, BUS_TAG)     /* talk address */
#define BUS_SECONDARY       TO_BITS (6, 5, BUS_SCG)     /* secondary command */

#define BUS_UNADDRESS       31                              /* unlisten and untalk addresses */
#define BUS_UNLISTEN        (BUS_LISTEN | BUS_UNADDRESS)    /* unlisten command */
#define BUS_UNTALK          (BUS_TALK   | BUS_UNADDRESS)    /* untalk command */

#define BUS_GTL             (BUS_PRIMARY | 0001)        /* Go To Local */
#define BUS_SDC             (BUS_PRIMARY | 0004)        /* Selected Device Clear */
#define BUS_PPC             (BUS_PRIMARY | 0005)        /* Parallel Poll Configure */
#define BUS_TCT             (BUS_PRIMARY | 0011)        /* Take Control */
#define BUS_DCL             (BUS_PRIMARY | 0024)        /* (Universal) Device Clear */
#define BUS_PPU             (BUS_PRIMARY | 0025)        /* Parallel Poll Unconfigure */
#define BUS_SPE             (BUS_PRIMARY | 0030)        /* Serial Poll Enable */
#define BUS_SPD             (BUS_PRIMARY | 0031)        /* Serial Poll Disable */

#define BUS_SBA             BIT (6)                     /* Serial poll affirmative status byte */
#define BUS_SBN             0u                          /* Serial poll negative status byte */

#define BUS_PPE             (BUS_SECONDARY | 0000)      /* Parallel Poll Enable (mask) */
#define BUS_PPD             (BUS_SECONDARY | 0020)      /* Parallel Poll Disable (mask) */

#define BUS_PPE_SENSE       BIT (3)             /* Parallel Poll Enable sense bit (mask) */
#define BUS_PPE_RESPONSE(b) BITS_TO (2, 0, (b)) /* Parallel Poll Enable response code */


/* Bus protocol handlers */

typedef enum {                                  /* protocol index number */
    DC_Index,                                   /*   CS/80 protocol */
/*  MA_Index,                                    *   Amigo Tape protocol */
/*  DA_Index,                                    *   Amigo Disc protocol */
/*  LP_Index,                                    *   Line Printer protocol */
    PHI_Index,                                  /*   PHI protocol */
    Protocol_Count                              /*   count of protocols */
    } PROTOCOL_INDEX;

typedef struct {                                /* bus report */
    DEVICE  *dptr;                              /*   a pointer to the reporting device */
    uint32  instance;                           /*   the instance ID of the protocol handler */
    uint32  present;                            /*   a bitmap of drives present */
    } BUS_REPORT;

typedef BUS_REPORT REPORTER (uint32 channel);                       /* reporter function type */
typedef uint32     ACCEPTOR (uint32 instance, BUS_CABLE signals);   /* acceptor function type */

typedef struct {                                /* bus protocol */
    REPORTER  *report;                          /*   a pointer to the protocol reporting routine */
    ACCEPTOR  *accept;                          /*   a pointer to the bus acceptor routine */
    } BUS_PROTOCOL;

typedef struct {                                /* bus protocol dispatcher */
    ACCEPTOR  *accept;                          /*   a pointer to the bus acceptor routine */
    DEVICE    *dptr;                            /*   a pointer to the protocol device */
    uint32    instance;                         /*   the instance number of the protocol handler instance */
    uint32    listeners;                        /*   a bitmap of the current listeners for this protocol */
    } BUS_DISPATCH;

typedef struct {                                /* bus registration */
    PROTOCOL_INDEX  index;                      /*   the protocol table index */
    BUS_PROTOCOL    protocol;                   /*   the protocol function pointers */
    } BUS_REGISTER;


/* Global bus routines */

extern void      hpib_register (BUS_REGISTER registration);
extern BUS_CABLE hpib_source   (uint32 channel, uint32 address, BUS_CABLE signals);
