bscbus.c revision d3d50737e566cade9a08d73d2af95105ac7cd960
9622934a862fa39a8e90c816c4136e293d75629djacobs * CDDL HEADER START
9622934a862fa39a8e90c816c4136e293d75629djacobs * The contents of this file are subject to the terms of the
9622934a862fa39a8e90c816c4136e293d75629djacobs * Common Development and Distribution License (the "License").
9622934a862fa39a8e90c816c4136e293d75629djacobs * You may not use this file except in compliance with the License.
9622934a862fa39a8e90c816c4136e293d75629djacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9622934a862fa39a8e90c816c4136e293d75629djacobs * See the License for the specific language governing permissions
9622934a862fa39a8e90c816c4136e293d75629djacobs * and limitations under the License.
9622934a862fa39a8e90c816c4136e293d75629djacobs * When distributing Covered Code, include this CDDL HEADER in each
9622934a862fa39a8e90c816c4136e293d75629djacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9622934a862fa39a8e90c816c4136e293d75629djacobs * If applicable, add the following below this CDDL HEADER, with the
9622934a862fa39a8e90c816c4136e293d75629djacobs * fields enclosed by brackets "[]" replaced with your own identifying
9622934a862fa39a8e90c816c4136e293d75629djacobs * information: Portions Copyright [yyyy] [name of copyright owner]
9622934a862fa39a8e90c816c4136e293d75629djacobs * CDDL HEADER END
9622934a862fa39a8e90c816c4136e293d75629djacobs * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
9622934a862fa39a8e90c816c4136e293d75629djacobs * Use is subject to license terms.
9622934a862fa39a8e90c816c4136e293d75629djacobs * The "bscbus" driver provides access to the LOMlite2 virtual registers,
9622934a862fa39a8e90c816c4136e293d75629djacobs * so that its clients (children) need not be concerned with the details
9622934a862fa39a8e90c816c4136e293d75629djacobs * of the access mechanism, which in this case is implemented via a
9622934a862fa39a8e90c816c4136e293d75629djacobs * packet-based protocol over a Xbus (similar to ebus) parallel link to the
9622934a862fa39a8e90c816c4136e293d75629djacobs * H8 host interface registers.
9622934a862fa39a8e90c816c4136e293d75629djacobs * On the other hand, this driver doesn't generally know what the virtual
9622934a862fa39a8e90c816c4136e293d75629djacobs * registers signify - only the clients need this information.
9622934a862fa39a8e90c816c4136e293d75629djacobs * Compiling for Solaris 10+ with access handle enhancements
9622934a862fa39a8e90c816c4136e293d75629djacobs * Compatibility definitions for backport to Solaris 8/9
9622934a862fa39a8e90c816c4136e293d75629djacobs#define HANDLE_PRIVATE(hdlp) (hdlp->ahi_common.ah_bus_private)
9622934a862fa39a8e90c816c4136e293d75629djacobs#define ddi_driver_major(dip) ddi_name_to_major(ddi_binding_name(dip))
9622934a862fa39a8e90c816c4136e293d75629djacobs#endif /* NDI_ACC_HDL_V2 */
9622934a862fa39a8e90c816c4136e293d75629djacobs * Local definitions
9622934a862fa39a8e90c816c4136e293d75629djacobs#define ADDR_TO_OFFSET(a, hdlp) ((caddr_t)(a) - HANDLE_ADDR(hdlp))
9622934a862fa39a8e90c816c4136e293d75629djacobs#define ADDR_TO_VREG(a) ((caddr_t)(a) - BSCBUS_DUMMY_ADDRESS)
9622934a862fa39a8e90c816c4136e293d75629djacobs#endif /* DEBUG */
9622934a862fa39a8e90c816c4136e293d75629djacobs * BSC command logging routines.
9622934a862fa39a8e90c816c4136e293d75629djacobs * Record the data passing to and from the BSC
9622934a862fa39a8e90c816c4136e293d75629djacobstypedef enum {
9622934a862fa39a8e90c816c4136e293d75629djacobstypedef struct {
9622934a862fa39a8e90c816c4136e293d75629djacobs#endif /* BSCBUS_LOGSTATUS */
9622934a862fa39a8e90c816c4136e293d75629djacobs * The following definitions are taken from the Hardware Manual for
9622934a862fa39a8e90c816c4136e293d75629djacobs * the Hitachi H8S/2148 in conjunction with the hardware specification
9622934a862fa39a8e90c816c4136e293d75629djacobs * for the Stiletto blade.
9622934a862fa39a8e90c816c4136e293d75629djacobs * Each instance of the host interface has 3 registers on the H8:
9622934a862fa39a8e90c816c4136e293d75629djacobs * IDRn - Input Data Register - write-only for Solaris.
9622934a862fa39a8e90c816c4136e293d75629djacobs * writes to this can be done via two
9622934a862fa39a8e90c816c4136e293d75629djacobs * addresses - control and data.
9622934a862fa39a8e90c816c4136e293d75629djacobs * The H8 can determine which address was
9622934a862fa39a8e90c816c4136e293d75629djacobs * written by examining the C/D bit in
9622934a862fa39a8e90c816c4136e293d75629djacobs * the status register.
9622934a862fa39a8e90c816c4136e293d75629djacobs * ODRn - Output Data Register - read-only for Solaris.
9622934a862fa39a8e90c816c4136e293d75629djacobs * A read has the side effect of acknowledging
9622934a862fa39a8e90c816c4136e293d75629djacobs * interrupts.
9622934a862fa39a8e90c816c4136e293d75629djacobs * STRn - Status Register - read-only for Solaris.
9622934a862fa39a8e90c816c4136e293d75629djacobs * In terms of host access to this the Input and Output data registers are
9622934a862fa39a8e90c816c4136e293d75629djacobs * mapped at the same address.
9622934a862fa39a8e90c816c4136e293d75629djacobs#define H8_STR_IDRC 0x08 /* last write to IDR was to IDRC */
9622934a862fa39a8e90c816c4136e293d75629djacobs /* 0=data, 1=command */
9622934a862fa39a8e90c816c4136e293d75629djacobs#define H8_STR_BUSY 0x04 /* H8 busy processing command */
9622934a862fa39a8e90c816c4136e293d75629djacobs#define H8_STR_TOKENPROTOCOL 0x80 /* token-passing protocol */
9622934a862fa39a8e90c816c4136e293d75629djacobs * Packet format ...
9622934a862fa39a8e90c816c4136e293d75629djacobs#define BSCBUS_PARAM 0x00 /* Parameter byte: 0b0xxxxxxx */
9622934a862fa39a8e90c816c4136e293d75629djacobs#define BSCBUS_CMD 0x80 /* Command byte: 0b10###XWV */
9622934a862fa39a8e90c816c4136e293d75629djacobs#define BSCBUS_STATUS 0xc0 /* Status byte: 0b11###AEV */
9622934a862fa39a8e90c816c4136e293d75629djacobs#define BSCBUS_CMD_XADDR 0x04 /* Extended (2-byte) addressing */
9622934a862fa39a8e90c816c4136e293d75629djacobs#define BSCBUS_STATUS_ASYNC 0x04 /* Asynchronous event pending */
9622934a862fa39a8e90c816c4136e293d75629djacobs#define BSCBUS_STATUS_ERR 0x02 /* Error in command processing */
9622934a862fa39a8e90c816c4136e293d75629djacobs#define BSCBUS_STATUS_MSB 0x01 /* MSB of Value read */
9622934a862fa39a8e90c816c4136e293d75629djacobs#define BSCBUS_CHANNEL_TO_OFFSET(chno) ((chno) * 2) /* Register offset */
9622934a862fa39a8e90c816c4136e293d75629djacobs * Time periods, in nanoseconds
9622934a862fa39a8e90c816c4136e293d75629djacobs * Note that LOMBUS_ONE_SEC and some other time
9622934a862fa39a8e90c816c4136e293d75629djacobs * periods are defined in <sys/lombus.h>
9622934a862fa39a8e90c816c4136e293d75629djacobs * Local datatypes
9622934a862fa39a8e90c816c4136e293d75629djacobs BSCBUS_CMDSTATE_IDLE, /* No transaction in progress */
9622934a862fa39a8e90c816c4136e293d75629djacobs BSCBUS_CMDSTATE_CLEARING, /* Clearing firmware busy status */
9622934a862fa39a8e90c816c4136e293d75629djacobs BSCBUS_CMDSTATE_SENDING, /* Waiting to send data to f/w */
9622934a862fa39a8e90c816c4136e293d75629djacobs BSCBUS_CMDSTATE_PENDING, /* Waiting for ack from f/w */
9622934a862fa39a8e90c816c4136e293d75629djacobs BSCBUS_CMDSTATE_WAITING, /* Waiting for status from f/w */
9622934a862fa39a8e90c816c4136e293d75629djacobs BSCBUS_CMDSTATE_READY, /* Status received/command done */
9622934a862fa39a8e90c816c4136e293d75629djacobs BSCBUS_CMDSTATE_ERROR /* Command failed with error */
9622934a862fa39a8e90c816c4136e293d75629djacobs /* Changes to these are protected by the instance ch_mutex mutex */
9622934a862fa39a8e90c816c4136e293d75629djacobs ddi_acc_handle_t ch_handle; /* per channel access handle */
9622934a862fa39a8e90c816c4136e293d75629djacobs unsigned int chno;
9622934a862fa39a8e90c816c4136e293d75629djacobs unsigned int map_count; /* Number of mappings to channel */
9622934a862fa39a8e90c816c4136e293d75629djacobs boolean_t map_dog; /* channel is mapped for watchdog */
9622934a862fa39a8e90c816c4136e293d75629djacobs * Flag to indicate that we've incurred a hardware fault on
9622934a862fa39a8e90c816c4136e293d75629djacobs * accesses to the H8; once this is set, we fake all further
9622934a862fa39a8e90c816c4136e293d75629djacobs * accesses in order not to provoke additional bus errors.
9622934a862fa39a8e90c816c4136e293d75629djacobs * Data protected by the dog_mutex: the watchdog-patting
9622934a862fa39a8e90c816c4136e293d75629djacobs * protocol data (since the dog can be patted from a high-level
9622934a862fa39a8e90c816c4136e293d75629djacobs * cyclic), and the interrupt-enabled flag.
9622934a862fa39a8e90c816c4136e293d75629djacobs unsigned int pat_fail_count;
9622934a862fa39a8e90c816c4136e293d75629djacobs * Serial protocol state data, protected by lo_mutex
9622934a862fa39a8e90c816c4136e293d75629djacobs * (which is initialised using <lo_iblk>)
struct bscbus_state {
int instance;
#ifdef BSCBUS_LOGSTATUS
struct bscbus_child_info {
int nregs;
#ifdef BSCBUS_LOGSTATUS
static void *bscbus_statep;
#ifdef DEBUG
const char *fmt, ...)
p = buf;
p += strlen(p);
#define bscbus_trace
static struct bscbus_state *
if (instance >= 0)
return (ssp);
static uint8_t
return (val);
static boolean_t
if (--doglimit == 0) {
static boolean_t
rcvd,
if (rcvd == 0) {
return (ready);
case BSCBUS_CMDSTATE_CLEARING:
case BSCBUS_CMDSTATE_SENDING:
case BSCBUS_CMDSTATE_PENDING:
case BSCBUS_CMDSTATE_WAITING:
if (!ready &&
if (ready)
static uint_t
return (DDI_INTR_CLAIMED);
static uint8_t
switch (cmd) {
case BSCBUS_CMD_WRITE:
case BSCBUS_CMD_READ:
case BSCBUS_CMD_NOP:
return (val);
static uint8_t
return (DUMMY_VALUE);
static uint8_t
return (DUMMY_VALUE);
static uint16_t
return (DUMMY_VALUE);
static uint32_t
switch (offset) {
case LOMBUS_FAULT_REG:
case LOMBUS_PROBE_REG:
case LOMBUS_ASYNC_REG:
return (DUMMY_VALUE);
switch (offset) {
case LOMBUS_FAULT_REG:
case LOMBUS_PROBE_REG:
static uint8_t
return (DUMMY_VALUE);
static uint16_t
return (DUMMY_VALUE);
static uint64_t
return (DUMMY_VALUE);
if (ddi_in_panic()) {
(timeout > 0);
if (ddi_in_panic()) {
if (timeout <= 0) {
caddr_t p;
int nregs;
int err;
nregs = 0;
switch (nregs) {
bscbus_dev_acc_attr, &h);
return (EIO);
int err;
caddr_t p;
&p, 0, 0, bscbus_dev_acc_attr, &h);
goto failed1;
int ninterrupts;
ninterrupts = 0;
goto failed2;
goto failed2;
goto failed2;
goto failed2;
goto failed1;
#if defined(NDI_ACC_HDL_V2)
switch (op) {
return (DDI_ME_UNIMPLEMENTED);
case DDI_MO_MAP_LOCKED:
return (DDI_ME_GENERIC);
switch (space) {
return (DDI_ME_REGSPEC_RANGE);
case LOMBUS_VREG_SPACE:
case LOMBUS_PAT_SPACE:
case LOMBUS_EVENT_SPACE:
return (DDI_SUCCESS);
case DDI_MO_UNMAP:
return (DDI_SUCCESS);
switch (op) {
return (DDI_ME_UNIMPLEMENTED);
case DDI_MO_MAP_LOCKED:
return (DDI_ME_GENERIC);
switch (space) {
return (DDI_ME_REGSPEC_RANGE);
case LOMBUS_VREG_SPACE:
case LOMBUS_PAT_SPACE:
case LOMBUS_EVENT_SPACE:
return (DDI_SUCCESS);
case DDI_MO_UNMAP:
return (DDI_SUCCESS);
return (DDI_ME_UNSUPPORTED);
return (DDI_ME_UNSUPPORTED);
return (DDI_ME_UNIMPLEMENTED);
return (DDI_ME_INVAL);
return (DDI_ME_INVAL);
return (DDI_ME_RNUMBER_RANGE);
return (DDI_ME_INVAL);
if (len == 0)
if (len < 0)
return (DDI_ME_INVAL);
return (DDI_ME_INVAL);
return (bscbus_map_handle(
int *regs;
int limit;
int err;
switch (op) {
case DDI_CTLOPS_INITCHILD:
return (DDI_FAILURE);
limit = 0;
case LOMBUS_VREG_SPACE:
case LOMBUS_PAT_SPACE:
case LOMBUS_EVENT_SPACE:
if (err) {
return (DDI_FAILURE);
return (DDI_SUCCESS);
case DDI_CTLOPS_UNINITCHILD:
return (DDI_SUCCESS);
case DDI_CTLOPS_REPORTDEV:
return (DDI_FAILURE);
return (DDI_SUCCESS);
case DDI_CTLOPS_REGSIZE:
return (DDI_FAILURE);
return (DDI_FAILURE);
return (DDI_SUCCESS);
case DDI_CTLOPS_NREGS:
return (DDI_FAILURE);
return (DDI_SUCCESS);
#if defined(__sparc)
return (DDI_FAILURE);
int chno;
#ifdef BSCBUS_LOGSTATUS
return (DDI_FAILURE);
int chno;
int instance;
int err;
switch (cmd) {
return (DDI_FAILURE);
case DDI_ATTACH:
return (DDI_FAILURE);
#ifdef BSCBUS_LOGSTATUS
if (err != 0)
* The hardware/interrupts are setup at map time to
return (DDI_SUCCESS);
int instance;
switch (cmd) {
return (DDI_FAILURE);
case DDI_DETACH:
return (DDI_SUCCESS);
int chno;
return (DDI_FAILURE);
return (DDI_SUCCESS);
&modldrv,
_init(void)
int err;
sizeof (struct bscbus_state), 0);
return (err);
_fini(void)
int err;
return (err);
#ifdef BSCBUS_LOGSTATUS
int idx;