root/usr/src/uts/sun4u/sys/rmc_comm.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_RMC_COMM_H
#define _SYS_RMC_COMM_H

#pragma ident   "%Z%%M% %I%     %E% SMI"

#ifdef  __cplusplus
extern "C" {
#endif

/*
 * Hardware: serial chip register numbers
 */
#define SIO_RXD                 0       /* read         */
#define SIO_TXD                 0       /* write        */
#define SIO_IER                 1
#define SIO_EIR                 2       /* read         */
#define SIO_FCR                 2       /* write        */
#define SIO_LCR                 3
#define SIO_BSR                 3       /* wierd        */
#define SIO_MCR                 4
#define SIO_LSR                 5
#define SIO_MSR                 6
#define SIO_SCR                 7

#define SIO_LBGDL               0       /* bank 1       */
#define SIO_LBGDH               1       /* bank 1       */

/*
 * Hardware: serial chip register bits
 */
#define SIO_IER_RXHDL_IE        0x01
#define SIO_IER_STD             0x00

#define SIO_FCR_FIFO_EN         0x01
#define SIO_FCR_RXSR            0x02
#define SIO_FCR_TXSR            0x04
#define SIO_FCR_RXFTH0          0x40
#define SIO_FCR_STD             (SIO_FCR_RXFTH0|SIO_FCR_FIFO_EN)

#define SIO_LCR_WLS0            0x01
#define SIO_LCR_WLS1            0x02
#define SIO_LCR_PEN             0x08
#define SIO_LCR_EPS             0x10
#define SIO_LCR_BKSE            0x80
#define SIO_LCR_8BIT            (SIO_LCR_WLS0|SIO_LCR_WLS1)
#define SIO_LCR_STD             (SIO_LCR_8BIT)
#define SIO_BSR_BANK0           (SIO_LCR_STD)
#define SIO_BSR_BANK1           (SIO_LCR_BKSE|SIO_LCR_STD)

#define SIO_MCR_ISEN            0x08
#define SIO_MCR_STD             (SIO_MCR_ISEN)

/* Line Status Register */
#define SIO_LSR_RXDA            0x01    /* data ready */
#define SIO_LSR_OVRRUN          0x02    /* overrun error */
#define SIO_LSR_PARERR          0x04    /* parity error */
#define SIO_LSR_FRMERR          0x08    /* framing error */
#define SIO_LSR_BRKDET          0x10    /* a break has arrived */
#define SIO_LSR_XHRE            0x20    /* tx hold reg is now empty */
#define SIO_LSR_XSRE            0x40    /* tx shift reg is now empty */
#define SIO_LSR_RFBE            0x80    /* rx FIFO Buffer error */

/*
 * Min/max/default baud rates, and a macro to convert from a baud
 * rate to the number (divisor) to put in the baud rate registers
 */
#define SIO_BAUD_MIN            50
#define SIO_BAUD_MAX            115200
#define SIO_BAUD_DEFAULT        115200
#define SIO_BAUD_TO_DIVISOR(b)  (115200 / (b))
#define SIO_BAUD_DIVISOR_MIN    1
#define SIO_BAUD_DIVISOR_MAX    64

/*
 * serial rx buffer size: set to maximum message size + 'bits'
 * (protocol overhead)
 */

#define SIO_MAX_RXBUF_SIZE      (DP_MAX_MSGLEN + 128)

/*
 * protocol status struct
 */

typedef struct rmc_comm_serdev_state {

        ddi_acc_handle_t sio_handle;
        uint8_t *sio_regs;
        ddi_softintr_t softid;
        ddi_periodic_t cycid; /* periodical callback */

        /*
         * Hardware mutex (initialised using <hw_iblk>),
         * used to prevent retriggering the softint while
         * it's still fetching data out of the chip FIFO.
         */
        kmutex_t hw_mutex[1];
        ddi_iblock_cookie_t hw_iblk;
        boolean_t hw_int_enabled;

        /*
         * Flag to indicate that we've incurred a hardware fault on
         * accesses to the SIO; once this is set, we fake all further
         * accesses in order not to provoke additional bus errors.
         */
        boolean_t sio_fault;

        /*
         * serial device receive buffer
         */
        char serdev_rx_buf[SIO_MAX_RXBUF_SIZE];
        uint16_t serdev_rx_count;

} rmc_comm_serdev_state_t;

/*
 * This driver's soft-state structure
 */
struct rmc_comm_state {
        /*
         * Configuration data, set during attach
         */
        dev_info_t *dip;
        major_t majornum;
        int instance;
        int n_registrations;
        boolean_t is_attached;

        /*
         * Parameters derived from .conf properties
         */
        int baud;
        uint32_t debug;
        int baud_divisor_factor;

        /*
         * serial device status...
         */
        rmc_comm_serdev_state_t sd_state;

        /*
         * protocol status struct
         */
        rmc_comm_dp_state_t dp_state;

        /*
         * driver interface status struct
         */
        rmc_comm_drvintf_state_t drvi_state;
};


/*
 * Time periods, in nanoseconds
 */
#define RMC_COMM_ONE_SEC        1000000000LL

/*
 * debugging
 */

#define DSER    0x01    /* serial device */
#define DPRO    0x02    /* protocol */
#define DAPI    0x04    /* API */
#define DPKT    0x08    /* packet handling routine */
#define DGEN    0x10    /* generic */
#define DDSC    0x20    /* datascope */
#define DMEM    0x40    /* memory alloc/release */

#ifdef  DEBUG
#define DPRINTF(rcs, d, ARGLIST)        { if (rcs->debug & d) cmn_err ARGLIST; }
#define DATASCOPE(rcs, c, b, l) { int i, j; char s[80]; \
                                s[0] = (c); \
                                s[1] = '\0'; \
                                for (i = 1; i < (l)+1; i++) { \
                                        j = strlen(s); \
                                        (void) sprintf(s+j, "%02x ", \
                                                (uchar_t)b[i-1]); \
                                        if (i%24 == 0) { \
                                                DPRINTF(rcs, DDSC, \
                                                        (CE_CONT, "%s\n", s)); \
                                                s[0] = (c); \
                                                s[1] = '\0'; \
                                        } \
                                } \
                                if (i%24 != 0) \
                                        DPRINTF(rcs, DDSC, \
                                                        (CE_CONT, "%s\n", s)); \
                                }
#else
#define DPRINTF(rcs, d, ARGLIST)
#define DATASCOPE(rcs, c, b, l)
#endif  /* DEBUG */


/*
 * function prototypes
 */

int rmc_comm_serdev_init(struct rmc_comm_state *, dev_info_t *);
void rmc_comm_serdev_fini(struct rmc_comm_state *, dev_info_t *);
void rmc_comm_serdev_receive(struct rmc_comm_state *);
void rmc_comm_serdev_send(struct rmc_comm_state *, char *, int);
void rmc_comm_serdev_drain(struct rmc_comm_state *);
struct rmc_comm_state *rmc_comm_getstate(dev_info_t *, int, const char *);
int rmc_comm_register(void);
void rmc_comm_unregister(void);

void rmc_comm_dp_init(struct rmc_comm_state *);
void rmc_comm_dp_fini(struct rmc_comm_state *);
void rmc_comm_dp_drecv(struct rmc_comm_state *, uint8_t *, int);
void rmc_comm_dp_mrecv(struct rmc_comm_state *, uint8_t *);
int rmc_comm_dp_msend(struct rmc_comm_state *, dp_message_t *);
void rmc_comm_bp_msend(struct rmc_comm_state *, bp_msg_t *);
void rmc_comm_bp_srecsend(struct rmc_comm_state *, char *, int);
int rmc_comm_dp_ctlsend(struct rmc_comm_state *, uint8_t);
void rmc_comm_dp_mcleanup(struct rmc_comm_state *);

int rmc_comm_drvintf_init(struct rmc_comm_state *);
void rmc_comm_drvintf_fini(struct rmc_comm_state *);

#ifdef  __cplusplus
}
#endif

#endif  /* _SYS_RMC_COMM_H */