1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * CDDL HEADER START
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The contents of this file are subject to the terms of the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Common Development and Distribution License (the "License").
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * You may not use this file except in compliance with the License.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * or http://www.opensolaris.org/os/licensing.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * See the License for the specific language governing permissions
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * and limitations under the License.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * When distributing Covered Code, include this CDDL HEADER in each
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * If applicable, add the following below this CDDL HEADER, with the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * fields enclosed by brackets "[]" replaced with your own identifying
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * information: Portions Copyright [yyyy] [name of copyright owner]
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * CDDL HEADER END
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Use is subject to license terms.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The "bscbus" driver provides access to the LOMlite2 virtual registers,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * so that its clients (children) need not be concerned with the details
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * of the access mechanism, which in this case is implemented via a
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * packet-based protocol over a Xbus (similar to ebus) parallel link to the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * H8 host interface registers.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * On the other hand, this driver doesn't generally know what the virtual
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * registers signify - only the clients need this information.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/note.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/types.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/conf.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/debug.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/errno.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/file.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#if defined(__sparc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/intr.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/membar.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/kmem.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/modctl.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/note.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/open.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/poll.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/spl.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/stat.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/strlog.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/atomic.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/ddi.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/sunddi.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/sunndi.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#include <sys/bscbus.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#if defined(NDI_ACC_HDL_V2)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Compiling for Solaris 10+ with access handle enhancements
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_TYPE ndi_acc_handle_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_ADDR(hdlp) (hdlp->ah_addr)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_FAULT(hdlp) (hdlp->ah_fault)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_MAPLEN(hdlp) (hdlp->ah_len)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_PRIVATE(hdlp) (hdlp->ah_bus_private)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#else
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Compatibility definitions for backport to Solaris 8/9
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_TYPE ddi_acc_impl_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_ADDR(hdlp) (hdlp->ahi_common.ah_addr)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_FAULT(hdlp) (hdlp->ahi_fault)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_MAPLEN(hdlp) (hdlp->ahi_common.ah_len)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define HANDLE_PRIVATE(hdlp) (hdlp->ahi_common.ah_bus_private)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define ddi_driver_major(dip) ddi_name_to_major(ddi_binding_name(dip))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* NDI_ACC_HDL_V2 */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Local definitions
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define MYNAME "bscbus"
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define NOMAJOR (~(major_t)0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define DUMMY_VALUE (~(int8_t)0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_INST_TO_MINOR(i) (i)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_MINOR_TO_INST(m) (m)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_MAX_CHANNELS (4)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_DUMMY_ADDRESS ((caddr_t)0x0CADD1ED)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define ADDR_TO_OFFSET(a, hdlp) ((caddr_t)(a) - HANDLE_ADDR(hdlp))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define ADDR_TO_VREG(a) ((caddr_t)(a) - BSCBUS_DUMMY_ADDRESS)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define VREG_TO_ADDR(v) (BSCBUS_DUMMY_ADDRESS + (v))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#ifdef DEBUG
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_LOGSTATUS
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* DEBUG */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#ifdef BSCBUS_LOGSTATUS
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSC command logging routines.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Record the data passing to and from the BSC
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdtypedef enum {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_BUSY = 1, /* bsc reports busy */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_CLEARING = 2, /* clearing bsc busy */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_CLEARED = 3, /* cleared bsc busy */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_SENDING = 4, /* sending next byte */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_SENT = 5, /* sending last byte */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_PENDING = 6, /* got sent byte ack */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_REPLY = 7, /* got reply byte */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_COMPLETE = 8, /* command complete */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_ERROR_SEQ = 9, /* error status */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_ERROR_STATUS = 10, /* error status */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_ERROR_OFLOW = 11, /* error status */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_ERROR_TOUT = 12, /* error status */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_PROCESS = 13, /* async intr */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_V1INTR = 14, /* v1 intr */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_V1INTRUNCL = 15, /* v1 intr unclaim */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSC_CMD_DOGPAT = 17 /* watchdog pat */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd} bsc_cmd_stamp_t;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdtypedef struct {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd hrtime_t bcl_now;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int bcl_seq;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bsc_cmd_stamp_t bcl_cat;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t bcl_chno;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t bcl_cmdstate;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t bcl_status;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t bcl_data;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd} bsc_cmd_log_t;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egduint32_t bscbus_cmd_log_size = 1024;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egduint32_t bscbus_cmd_log_flags = 0xffffffff;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* BSCBUS_LOGSTATUS */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The following definitions are taken from the Hardware Manual for
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * the Hitachi H8S/2148 in conjunction with the hardware specification
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * for the Stiletto blade.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Each instance of the host interface has 3 registers on the H8:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * IDRn - Input Data Register - write-only for Solaris.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * writes to this can be done via two
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * addresses - control and data.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The H8 can determine which address was
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * written by examining the C/D bit in
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * the status register.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * ODRn - Output Data Register - read-only for Solaris.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * A read has the side effect of acknowledging
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * interrupts.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * STRn - Status Register - read-only for Solaris.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * In terms of host access to this the Input and Output data registers are
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * mapped at the same address.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define H8_IDRD 0
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define H8_IDRC 1
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define H8_ODR 0
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define H8_STR 1
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define H8_STR_OBF 0x01 /* data available in ODR */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define H8_STR_IBF 0x02 /* data for H8 in IDR */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define H8_STR_IDRC 0x08 /* last write to IDR was to IDRC */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* 0=data, 1=command */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define H8_STR_BUSY 0x04 /* H8 busy processing command */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define H8_STR_TOKENPROTOCOL 0x80 /* token-passing protocol */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Packet format ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_MASK 0xc0 /* Byte-type bits */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_PARAM 0x00 /* Parameter byte: 0b0xxxxxxx */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_LAST 0x80 /* Last byte of packet */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_CMD 0x80 /* Command byte: 0b10###XWV */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_STATUS 0xc0 /* Status byte: 0b11###AEV */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_SEQ 0x38 /* Sequence number bits */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_SEQ_LSB 0x08 /* Sequence number LSB */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_CMD_XADDR 0x04 /* Extended (2-byte) addressing */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_CMD_WRITE 0x02 /* Write command */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_CMD_WMSB 0x01 /* Set MSB on Write */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_CMD_READ 0x01 /* Read command */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_CMD_NOP 0x00 /* NOP command */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_STATUS_ASYNC 0x04 /* Asynchronous event pending */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_STATUS_ERR 0x02 /* Error in command processing */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_STATUS_MSB 0x01 /* MSB of Value read */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_VREG_LO(x) ((x) & ((1 << 7) - 1))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_VREG_HI(x) ((x) >> 7)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_BUFSIZE 8
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_CHANNEL_TO_OFFSET(chno) ((chno) * 2) /* Register offset */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Time periods, in nanoseconds
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Note that LOMBUS_ONE_SEC and some other time
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * periods are defined in <sys/lombus.h>
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_CMD_POLL (LOMBUS_ONE_SEC)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_CMD_POLLNOINTS (LOMBUS_ONE_SEC/20)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_HWRESET_POLL (LOMBUS_ONE_SEC/20)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_HWRESET_TIMEOUT (LOMBUS_ONE_SEC*2)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_DOG_PAT_POLL_LIMIT (1000)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_DOG_PAT_POLL (1)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_PAT_RETRY_LIMIT 5
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Local datatypes
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdenum bscbus_cmdstate {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSCBUS_CMDSTATE_IDLE, /* No transaction in progress */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSCBUS_CMDSTATE_BUSY, /* Setting up command */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSCBUS_CMDSTATE_CLEARING, /* Clearing firmware busy status */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSCBUS_CMDSTATE_SENDING, /* Waiting to send data to f/w */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSCBUS_CMDSTATE_PENDING, /* Waiting for ack from f/w */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSCBUS_CMDSTATE_WAITING, /* Waiting for status from f/w */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSCBUS_CMDSTATE_READY, /* Status received/command done */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSCBUS_CMDSTATE_ERROR /* Command failed with error */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstruct bscbus_channel_state {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Changes to these are protected by the instance ch_mutex mutex */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_state *ssp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t *ch_regs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_acc_handle_t ch_handle; /* per channel access handle */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd unsigned int chno;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd unsigned int map_count; /* Number of mappings to channel */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd boolean_t map_dog; /* channel is mapped for watchdog */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Flag to indicate that we've incurred a hardware fault on
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * accesses to the H8; once this is set, we fake all further
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * accesses in order not to provoke additional bus errors.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd boolean_t xio_fault;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Data protected by the dog_mutex: the watchdog-patting
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * protocol data (since the dog can be patted from a high-level
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * cyclic), and the interrupt-enabled flag.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd kmutex_t dog_mutex[1];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd unsigned int pat_retry_count;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd unsigned int pat_fail_count;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Serial protocol state data, protected by lo_mutex
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * (which is initialised using <lo_iblk>)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd kmutex_t lo_mutex[1];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_iblock_cookie_t lo_iblk;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd kcondvar_t lo_cv[1];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int unclaimed_count;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd volatile enum bscbus_cmdstate cmdstate;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd clock_t deadline;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd clock_t poll_hz;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd boolean_t interrupt_failed;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t cmdbuf[BSCBUS_BUFSIZE];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t *cmdp; /* Points to last tx'd in cmdbuf */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t reply[BSCBUS_BUFSIZE];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t async;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t index;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t result;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t sequence;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint32_t error;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define BSCBUS_TX_PENDING(csp) ((csp)->cmdp > (csp)->cmdbuf)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * This driver's soft-state structure
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstruct bscbus_state {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Configuration data, set during attach
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd dev_info_t *dip;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd major_t majornum;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int instance;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_acc_handle_t h8_handle;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t *h8_regs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Parameters derived from .conf properties
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint32_t debug;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Flag to indicate that we are using per channel
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * mapping of the register sets and interrupts.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * reg set 0 is chan 0
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * reg set 1 is chan 1 ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Interrupts are specified in that order but later
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * channels may not have interrupts.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd boolean_t per_channel_regs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * channel state data, protected by ch_mutex
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * channel claim/release requests are protected by this mutex.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd kmutex_t ch_mutex[1];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_channel_state channel[BSCBUS_MAX_CHANNELS];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#ifdef BSCBUS_LOGSTATUS
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Command logging buffer for recording transactions with the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSC. This is useful for debugging failed transactions and other
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * such funnies.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bsc_cmd_log_t *cmd_log;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint32_t cmd_log_idx;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint32_t cmd_log_size;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint32_t cmd_log_flags;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* BSCBUS_LOGSTATUS */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The auxiliary structure attached to each child
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * (the child's parent-private-data points to this).
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstruct bscbus_child_info {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd lombus_regspec_t *rsp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int nregs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#ifdef BSCBUS_LOGSTATUS
1c42de6d020629af774dd9e9fc81be3f3ed9398egdvoid bscbus_cmd_log(struct bscbus_channel_state *, bsc_cmd_stamp_t,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t, uint8_t);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#else /* BSCBUS_LOGSTATUS */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define bscbus_cmd_log(state, stamp, status, data)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* BSCBUS_LOGSTATUS */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Local data
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void *bscbus_statep;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic major_t bscbus_major = NOMAJOR;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic ddi_device_acc_attr_t bscbus_dev_acc_attr[1] = {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd DDI_DEVICE_ATTR_V0,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd DDI_STRUCTURE_LE_ACC,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd DDI_STRICTORDER_ACC
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * General utility routines ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#ifdef DEBUG
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_trace(struct bscbus_channel_state *csp, char code, const char *caller,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd const char *fmt, ...)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd char buf[256];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd char *p;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd va_list va;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->ssp->debug & (1 << (code-'@'))) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd p = buf;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) snprintf(p, sizeof (buf) - (p - buf),
193974072f41a843678abf5f61979c748687e66bSherry Moore "%s/%s: ", MYNAME, caller);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd p += strlen(p);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd va_start(va, fmt);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) vsnprintf(p, sizeof (buf) - (p - buf), fmt, va);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd va_end(va);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd buf[sizeof (buf) - 1] = '\0';
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) strlog(csp->ssp->majornum, csp->ssp->instance,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd code, SL_TRACE, buf);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#else /* DEBUG */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#define bscbus_trace
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* DEBUG */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic struct bscbus_state *
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_getstate(dev_info_t *dip, int instance, const char *caller)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_state *ssp = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd dev_info_t *sdip = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd major_t dmaj = NOMAJOR;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (dip != NULL) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Use the instance number from the <dip>; also,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * check that it really corresponds to this driver
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd instance = ddi_get_instance(dip);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd dmaj = ddi_driver_major(dip);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (bscbus_major == NOMAJOR && dmaj != NOMAJOR)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_major = dmaj;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd else if (dmaj != bscbus_major) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cmn_err(CE_WARN,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "%s: major number mismatch (%d vs. %d) in %s(),"
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "probably due to child misconfiguration",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd MYNAME, bscbus_major, dmaj, caller);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd instance = -1;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (instance >= 0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp = ddi_get_soft_state(bscbus_statep, instance);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ssp != NULL) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd sdip = ssp->dip;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (dip == NULL && sdip == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd else if (dip != NULL && sdip != NULL && sdip != dip) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cmn_err(CE_WARN,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "%s: devinfo mismatch (%p vs. %p) in %s(), "
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "probably due to child misconfiguration",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd MYNAME, (void *)dip, (void *)sdip, caller);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (ssp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Lowest-level I/O register read/write
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_put_reg(struct bscbus_channel_state *csp, uint_t reg, uint8_t val)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->ch_handle != NULL && !csp->xio_fault) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_put8(csp->ch_handle,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_regs + reg, val);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint8_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_get_reg(struct bscbus_channel_state *csp, uint_t reg)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t val;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->ch_handle != NULL && !csp->xio_fault)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd val = ddi_get8(csp->ch_handle,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_regs + reg);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd else
1c42de6d020629af774dd9e9fc81be3f3ed9398egd val = DUMMY_VALUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (val);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_check_fault_status(struct bscbus_channel_state *csp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->xio_fault =
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_check_acc_handle(csp->ch_handle) != DDI_SUCCESS;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic boolean_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_faulty(struct bscbus_channel_state *csp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (!csp->xio_fault)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_check_fault_status(csp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (csp->xio_fault);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Write data into h8 registers
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_pat_dog(struct bscbus_channel_state *csp, uint8_t val)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t status;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint32_t doglimit = BSCBUS_DOG_PAT_POLL_LIMIT;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'W', "bscbus_pat_dog:", "");
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_DOGPAT, 0, val);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status = bscbus_get_reg(csp, H8_STR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd while (status & H8_STR_IBF) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->pat_retry_count > BSCBUS_PAT_RETRY_LIMIT) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Previous attempts to contact BSC have failed.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Do not bother waiting for it to eat previous
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * data.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Pat anyway just in case the BSC is really alive
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * and the IBF bit is lying.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_put_reg(csp, H8_IDRC, val);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'W', "bscbus_pat_dog:",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "retry count exceeded");
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (--doglimit == 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* The BSC is not responding - give up */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->pat_fail_count++;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->pat_retry_count++;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Pat anyway just in case the BSC is really alive */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_put_reg(csp, H8_IDRC, val);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'W', "bscbus_pat_dog:",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "poll limit exceeded");
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd drv_usecwait(BSCBUS_DOG_PAT_POLL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status = bscbus_get_reg(csp, H8_STR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_put_reg(csp, H8_IDRC, val);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->pat_retry_count = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * State diagrams for how bscbus_process works.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSCBUS_CMDSTATE_IDLE No transaction in progress
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSCBUS_CMDSTATE_BUSY Setting up command
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSCBUS_CMDSTATE_CLEARING Clearing firmware busy status
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSCBUS_CMDSTATE_SENDING Waiting to send data to f/w
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSCBUS_CMDSTATE_PENDING Waiting for ack from f/w
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSCBUS_CMDSTATE_WAITING Waiting for status from f/w
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSCBUS_CMDSTATE_READY Status received/command done
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * BSCBUS_CMDSTATE_ERROR Command failed with error
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * +----------+
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | IDLE/BUSY|
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | (0/1) | abnormal
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * +----------+ state
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | \ detected
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | \------>------+ +----<---+
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * bsc | | | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * is | V V |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * ready| +----------+ |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | | | ^
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | | CLEARING | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | | (2) | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | +----------+ |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | cleared / | \ | more to clear
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | / | \-->--+
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | +-------<-------/ V
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * V V |timeout
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * +----------+ timeout |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | |------>---------+--------+
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | SENDING | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | (3) |------<-------+ |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * +----------+ | V
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * sent| \ send ^ack |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * last| \ next |received |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | \ +----------+ |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | \ | | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | \------>| PENDING |-->-+
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | | (4) | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | +----------+ |timeout
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | +---<----+ |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | | | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * V V | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * +----------+ | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | | | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | WAITING | ^ |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | (5) | | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * +----------+ | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | | |more | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | V |required| |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * done| | +--->----+ |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | +--->--------------+ +---<---+
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | error/timeout | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * V V V
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * +----------+ +----------+
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | | | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | READY | | ERROR |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | (7) | | (6) |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * +----------+ +----------+
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * V V
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * | |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * +------>---+---<------+
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * |
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Back to
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Idle
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_process_sending(struct bscbus_channel_state *csp, uint8_t status)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * When we get here we actually expect H8_STR_IBF to
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * be clear but we check just in case of problems.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ASSERT(BSCBUS_TX_PENDING(csp));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (!(status & H8_STR_IBF)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_put_reg(csp, H8_IDRD, *--csp->cmdp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'P', "bscbus_process_sending",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "state %d; val $%x",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate, *csp->cmdp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (!BSCBUS_TX_PENDING(csp)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_SENT,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status, *csp->cmdp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* No more pending - move to waiting state */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'P', "bscbus_process_sending",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "moving to waiting");
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_WAITING;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Extend deadline because time has moved on */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->deadline = ddi_get_lbolt() +
193974072f41a843678abf5f61979c748687e66bSherry Moore drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Wait for ack of this byte */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_SENDING,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status, *csp->cmdp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_PENDING;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'P', "bscbus_process_sending",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "moving to pending");
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_process_clearing(struct bscbus_channel_state *csp,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t status, uint8_t data)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * We only enter this state if H8_STR_BUSY was set when
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * we started the transaction. We just ignore all received
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * data until we see OBF set AND BUSY cleared.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * It is not good enough to see BUSY clear on its own
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((status & H8_STR_OBF) && !(status & H8_STR_BUSY)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_CLEARED, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Throw away any data received up until now */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'P', "bscbus_process_clearing",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "busy cleared");
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Send the next byte immediately.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * At this stage we should clear the OBF flag because that
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * data has been used. IBF is still valid so do not clear that.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status &= ~(H8_STR_OBF);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_process_sending(csp, status);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (status & H8_STR_OBF) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_CLEARING, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_process_pending(struct bscbus_channel_state *csp, uint8_t status)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* We are waiting for an acknowledgement of a byte */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (status & H8_STR_OBF) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_PENDING,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status, *csp->cmdp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'P', "bscbus_process_pending",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "moving to sending");
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Send the next byte immediately.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * At this stage we should clear the OBF flag because that
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * data has been used. IBF is still valid so do not clear that.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status &= ~(H8_STR_OBF);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_process_sending(csp, status);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic boolean_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_process_waiting(struct bscbus_channel_state *csp,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t status, uint8_t data)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t rcvd = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd boolean_t ready = B_FALSE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t tmp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (status & H8_STR_OBF) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->reply[rcvd = csp->index] = data;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (++rcvd < BSCBUS_BUFSIZE)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->index = rcvd;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'D', "bscbus_process_waiting",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "rcvd %d: $%02x $%02x $%02x $%02x $%02x $%02x $%02x $%02x",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd rcvd,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->reply[0], csp->reply[1],
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->reply[2], csp->reply[3],
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->reply[4], csp->reply[5],
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->reply[6], csp->reply[7]);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (rcvd == 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * No bytes received this time through (though there
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * might be a partial packet sitting in the buffer).
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* EMPTY */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else if (rcvd >= BSCBUS_BUFSIZE) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Buffer overflow; discard the data & treat as an error
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * (even if the last byte read did claim to terminate a
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * packet, it can't be a valid one 'cos it's too long!)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_ERROR_OFLOW, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->index = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->error = LOMBUS_ERR_OFLOW;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ready = B_TRUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else if ((data & BSCBUS_LAST) == 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Packet not yet complete; leave the partial packet in
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * the buffer for later ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_REPLY, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else if ((data & BSCBUS_MASK) != BSCBUS_STATUS) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Invalid "status" byte - maybe an echo of the command? */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_ERROR_STATUS, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->error = LOMBUS_ERR_BADSTATUS;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ready = B_TRUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else if ((data & BSCBUS_SEQ) != csp->sequence) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Wrong sequence number! Flag this as an error */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_ERROR_SEQ, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->error = LOMBUS_ERR_SEQUENCE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ready = B_TRUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Finally, we know that's it's a valid reply to our
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * last command. Update the ASYNC status, derive the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * reply parameter (if any), and check the ERROR bit
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * to find out what the parameter means.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Note that not all the values read/assigned here
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * are meaningful, but it doesn't matter; the waiting
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * thread will know which one(s) it should check.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_COMPLETE, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->async = (data & BSCBUS_STATUS_ASYNC) ? 1 : 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd tmp = ((data & BSCBUS_STATUS_MSB) ? 0x80 : 0) | csp->reply[0];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (data & BSCBUS_STATUS_ERR) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->error = tmp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_READY;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->result = tmp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ready = B_TRUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (ready);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Packet receive handler
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * This routine should be called from the low-level softint,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * or bscbus_cmd() (for polled operation), with the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * low-level mutex already held.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_process(struct bscbus_channel_state *csp,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t status, uint8_t data)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd boolean_t ready = B_FALSE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ASSERT(mutex_owned(csp->lo_mutex));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((status & H8_STR_OBF) || (status & H8_STR_IBF)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'D', "bscbus_process",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "state %d; error $%x",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate, csp->error);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (csp->cmdstate) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case BSCBUS_CMDSTATE_CLEARING:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_process_clearing(csp, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case BSCBUS_CMDSTATE_SENDING:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_process_sending(csp, status);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case BSCBUS_CMDSTATE_PENDING:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_process_pending(csp, status);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case BSCBUS_CMDSTATE_WAITING:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ready = bscbus_process_waiting(csp, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Nothing to do */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Check for timeouts - but only if the command has not yet
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * completed (ready is true when command completes in this
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * call to bscbus_process OR cmdstate is READY or ERROR if
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * this is a spurious call to bscbus_process i.e. a spurious
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * interrupt)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (!ready &&
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ((ddi_get_lbolt() - csp->deadline) > 0) &&
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate != BSCBUS_CMDSTATE_READY &&
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate != BSCBUS_CMDSTATE_ERROR) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'P', "bscbus_process",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "timeout previous state %d; error $%x",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate, csp->error);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_ERROR_TOUT, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->cmdstate == BSCBUS_CMDSTATE_CLEARING) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Move onto sending because busy might be stuck */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Extend timeout relative to original start time */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->deadline += drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else if (csp->cmdstate != BSCBUS_CMDSTATE_IDLE) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->error = LOMBUS_ERR_TIMEOUT;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ready = B_TRUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((status & H8_STR_OBF) || (status & H8_STR_IBF) || ready) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'D', "bscbus_process",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "last $%02x; state %d; error $%x; ready %d",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd data, csp->cmdstate, csp->error, ready);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ready)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cv_broadcast(csp->lo_cv);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_hwintr(caddr_t arg)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_channel_state *csp = (void *)arg;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t status;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t data = 0xb0 /* Dummy value */;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_enter(csp->lo_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Read the registers to ensure that the interrupt is cleared.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Status must be read first because reading data changes the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * status.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * We always read the data because that clears the interrupt down.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * This is horrible hardware semantics but we have to do it!
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status = bscbus_get_reg(csp, H8_STR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd data = bscbus_get_reg(csp, H8_ODR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (!(status & H8_STR_OBF)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_V1INTRUNCL, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->unclaimed_count++;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_V1INTR, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (status & H8_STR_TOKENPROTOCOL) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_process(csp, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->interrupt_failed) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'I', "bscbus_hwintr:",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "interrupt fault cleared channel %d", csp->chno);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->interrupt_failed = B_FALSE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->poll_hz = drv_usectohz(BSCBUS_CMD_POLL / 1000);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_exit(csp->lo_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_INTR_CLAIMED);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdvoid
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_poll(struct bscbus_channel_state *csp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * This routine is only called if we timeout in userland
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * waiting for an interrupt. This generally means that we have
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * lost interrupt capabilities or that something has gone
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * wrong. In this case we are allowed to access the hardware
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * and read the data register if necessary.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * If interrupts return then recovery actions should mend us!
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t status;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t data = 0xfa; /* Dummy value */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ASSERT(mutex_owned(csp->lo_mutex));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Should look for data to receive */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status = bscbus_get_reg(csp, H8_STR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (status & H8_STR_OBF) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* There is data available */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd data = bscbus_get_reg(csp, H8_ODR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_PROCESS, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_process(csp, status, data);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Serial protocol
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * This routine builds a command and sets it in progress.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint8_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_cmd(HANDLE_TYPE *hdlp, ptrdiff_t vreg, uint_t val, uint_t cmd)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_channel_state *csp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd clock_t start;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t status;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * First of all, wait for the interface to be available.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * NOTE: we blow through all the mutex/cv/state checking and
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * preempt any command in progress if the system is panicking!
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp = HANDLE_PRIVATE(hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_enter(csp->lo_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd while (csp->cmdstate != BSCBUS_CMDSTATE_IDLE && !ddi_in_panic())
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cv_wait(csp->lo_cv, csp->lo_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_BUSY;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->sequence = (csp->sequence + BSCBUS_SEQ_LSB) & BSCBUS_SEQ;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * We have exclusive ownership, so assemble the command (backwards):
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * [byte 0] Command: modified by XADDR and/or WMSB bits
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * [Optional] Parameter: Value to write (low 7 bits)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * [Optional] Parameter: Register number (high 7 bits)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * [Optional] Parameter: Register number (low 7 bits)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdp = &csp->cmdbuf[0];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *csp->cmdp++ = BSCBUS_CMD | csp->sequence | cmd;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (cmd) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case BSCBUS_CMD_WRITE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *csp->cmdp++ = val & 0x7f;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (val >= 0x80)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdbuf[0] |= BSCBUS_CMD_WMSB;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*FALLTHRU*/
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case BSCBUS_CMD_READ:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (BSCBUS_VREG_HI(vreg) != 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *csp->cmdp++ = BSCBUS_VREG_HI(vreg);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdbuf[0] |= BSCBUS_CMD_XADDR;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *csp->cmdp++ = BSCBUS_VREG_LO(vreg);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*FALLTHRU*/
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case BSCBUS_CMD_NOP:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Check and update the H8 h/w fault status before accessing
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * the chip registers. If there's a (new or previous) fault,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * we'll run through the protocol but won't really touch the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * hardware and all commands will timeout. If a previously
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * discovered fault has now gone away (!), then we can (try to)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * proceed with the new command (probably a probe).
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_check_fault_status(csp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Prepare for the command (to be processed by the interrupt
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * handler and/or polling loop below), and wait for a response
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * or timeout.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd start = ddi_get_lbolt();
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->deadline = start + drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->error = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->index = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->result = DUMMY_VALUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status = bscbus_get_reg(csp, H8_STR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (status & H8_STR_BUSY) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0xfd);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Must ensure that the busy state has cleared before
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * sending the command
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_CLEARING;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'P', "bscbus_cmd",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "h8 reporting status (%x) busy - clearing", status);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* It is clear to send the command immediately */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'P', "bscbus_cmd",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "sending first byte of command, status %x", status);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_poll(csp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->poll_hz = drv_usectohz(
193974072f41a843678abf5f61979c748687e66bSherry Moore (csp->interrupt_failed ?
193974072f41a843678abf5f61979c748687e66bSherry Moore BSCBUS_CMD_POLLNOINTS : BSCBUS_CMD_POLL) / 1000);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd while ((csp->cmdstate != BSCBUS_CMDSTATE_READY) &&
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (csp->cmdstate != BSCBUS_CMDSTATE_ERROR)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ASSERT(csp->cmdstate != BSCBUS_CMDSTATE_IDLE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if ((cv_reltimedwait(csp->lo_cv, csp->lo_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni csp->poll_hz, TR_CLOCK_TICK) == -1) &&
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate != BSCBUS_CMDSTATE_READY &&
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate != BSCBUS_CMDSTATE_ERROR) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (!csp->interrupt_failed) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'I', "bscbus_cmd:",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "interrupt_failed channel %d", csp->chno);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->interrupt_failed = B_TRUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->poll_hz = drv_usectohz(
193974072f41a843678abf5f61979c748687e66bSherry Moore BSCBUS_CMD_POLLNOINTS / 1000);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_poll(csp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The return value may not be meaningful but retrieve it anyway
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd val = csp->result;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (bscbus_faulty(csp)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd val = DUMMY_VALUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_SIOHW;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else if (csp->cmdstate != BSCBUS_CMDSTATE_READY) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Some problem here ... transfer the error code from
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * the per-instance state to the per-handle fault flag.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The error code shouldn't be zero!
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->error != 0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = csp->error;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd else
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_BADERRCODE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * All done now!
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->index = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cv_broadcast(csp->lo_cv);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_exit(csp->lo_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (val);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Space 0 - LOM virtual register access
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Only 8-bit accesses are supported.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint8_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_vreg_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ptrdiff_t offset;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Check the offset that the caller has added to the base address
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * against the length of the mapping originally requested.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd offset = ADDR_TO_OFFSET(addr, hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return a dummy value
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DUMMY_VALUE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Derive the virtual register number and run the command
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (bscbus_cmd(hdlp, ADDR_TO_VREG(addr), 0, BSCBUS_CMD_READ));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_vreg_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ptrdiff_t offset;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Check the offset that the caller has added to the base address
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * against the length of the mapping originally requested.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd offset = ADDR_TO_OFFSET(addr, hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Derive the virtual register number and run the command
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) bscbus_cmd(hdlp, ADDR_TO_VREG(addr), val, BSCBUS_CMD_WRITE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_vreg_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd size_t inc;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (; repcount--; dev_addr += inc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *host_addr++ = bscbus_vreg_get8(hdlp, dev_addr);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_vreg_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd size_t inc;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (; repcount--; dev_addr += inc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_vreg_put8(hdlp, dev_addr, *host_addr++);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Space 1 - LOM watchdog pat register access
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Only 8-bit accesses are supported.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Reads have no effect and return 0.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Multi-byte reads (using ddi_rep_get8(9F)) are a fairly inefficient
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * way of zeroing the destination area ;-) and still won't pat the dog.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Multi-byte writes (using ddi_rep_put8(9F)) will almost certainly
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * only count as a single pat, no matter how many bytes the caller
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * says to write, as the inter-pat time is VERY long compared with
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * the time it will take to read the memory source area.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint8_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_pat_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ptrdiff_t offset;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Check the offset that the caller has added to the base address
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * against the length of the mapping originally requested.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd offset = ADDR_TO_OFFSET(addr, hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return a dummy value
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DUMMY_VALUE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_pat_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_channel_state *csp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ptrdiff_t offset;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Check the offset that the caller has added to the base address
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * against the length of the mapping originally requested.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd offset = ADDR_TO_OFFSET(addr, hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp = HANDLE_PRIVATE(hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_enter(csp->dog_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_pat_dog(csp, val);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_exit(csp->dog_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_pat_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd size_t inc;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (; repcount--; dev_addr += inc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *host_addr++ = bscbus_pat_get8(hdlp, dev_addr);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_pat_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd size_t inc;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (; repcount--; dev_addr += inc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_pat_put8(hdlp, dev_addr, *host_addr++);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Space 2 - LOM async event flag register access
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Only 16-bit accesses are supported.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint16_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_event_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_channel_state *csp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ptrdiff_t offset;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Check the offset that the caller has added to the base address
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * against the length of the mapping orignally requested.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd offset = ADDR_TO_OFFSET(addr, hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return a dummy value
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DUMMY_VALUE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Return the value of the asynchronous-event-pending flag
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * as passed back by the LOM at the end of the last command.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp = HANDLE_PRIVATE(hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (csp->async);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_event_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ptrdiff_t offset;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(val))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Check the offset that the caller has added to the base address
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * against the length of the mapping originally requested.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd offset = ADDR_TO_OFFSET(addr, hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The user can't overwrite the asynchronous-event-pending flag!
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_RO;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_event_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint16_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd size_t inc;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (; repcount--; dev_addr += inc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *host_addr++ = bscbus_event_get16(hdlp, dev_addr);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_event_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint16_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd size_t inc;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (; repcount--; dev_addr += inc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_event_put16(hdlp, dev_addr, *host_addr++);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * All spaces - access handle fault information
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Only 32-bit accesses are supported.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint32_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_meta_get32(HANDLE_TYPE *hdlp, uint32_t *addr)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_channel_state *csp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ptrdiff_t offset;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Derive the offset that the caller has added to the base
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * address originally returned, and use it to determine
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * which meta-register is to be accessed ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd offset = ADDR_TO_OFFSET(addr, hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (offset) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_FAULT_REG:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * This meta-register provides a code for the most
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * recent virtual register access fault, if any.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (HANDLE_FAULT(hdlp));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_PROBE_REG:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Reading this meta-register clears any existing fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * (at the virtual, not the hardware access layer), then
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * runs a NOP command and returns the fault code from that.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (HANDLE_FAULT(hdlp));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_ASYNC_REG:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Obsolescent - but still supported for backwards
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * compatibility. This is an alias for the newer
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * LOMBUS_EVENT_REG, but doesn't require a separate
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * "reg" entry and ddi_regs_map_setup() call.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * It returns the value of the asynchronous-event-pending
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * flag as passed back by the BSC at the end of the last
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * completed command.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp = HANDLE_PRIVATE(hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (csp->async);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return a dummy value
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DUMMY_VALUE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_meta_put32(HANDLE_TYPE *hdlp, uint32_t *addr, uint32_t val)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ptrdiff_t offset;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Derive the offset that the caller has added to the base
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * address originally returned, and use it to determine
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * which meta-register is to be accessed ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd offset = ADDR_TO_OFFSET(addr, hdlp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (offset) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_FAULT_REG:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * This meta-register contains a code for the most
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * recent virtual register access fault, if any.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * It can be cleared simply by writing 0 to it.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = val;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_PROBE_REG:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Writing this meta-register clears any existing fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * (at the virtual, not the hardware acess layer), then
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * runs a NOP command. The caller can check the fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * code later if required.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_meta_rep_get32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint32_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd size_t inc;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (; repcount--; dev_addr += inc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *host_addr++ = bscbus_meta_get32(hdlp, dev_addr);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_meta_rep_put32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint32_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd size_t inc;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (; repcount--; dev_addr += inc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_put32(hdlp, dev_addr, *host_addr++);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Finally, some dummy functions for all unsupported access
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * space/size/mode combinations ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint8_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(addr))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return a dummy value
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DUMMY_VALUE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(addr, val))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint16_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(addr))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return a dummy value
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DUMMY_VALUE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(addr, val))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint16_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint16_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic uint64_t
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_get64(HANDLE_TYPE *hdlp, uint64_t *addr)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(addr))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault and return a dummy value
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DUMMY_VALUE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_put64(HANDLE_TYPE *hdlp, uint64_t *addr, uint64_t val)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(addr, val))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_rep_get64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint64_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_no_rep_put64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint64_t *dev_addr, size_t repcount, uint_t flags)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Invalid access - flag a fault
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_acc_fault_check(HANDLE_TYPE *hdlp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (HANDLE_FAULT(hdlp) != 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Hardware setup - ensure that there are no pending transactions and
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * hence no pending interrupts. We do this be ensuring that the BSC is
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * not reporting a busy condition and that it does not have any data
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * pending in its output buffer.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * This is important because if we have pending interrupts at attach
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * time Solaris will hang due to bugs in ddi_get_iblock_cookie.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_hw_reset(struct bscbus_channel_state *csp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int64_t timeout;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t status;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->map_count == 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* No-one using this instance - no need to reset hardware */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'R', "bscbus_hw_reset",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "resetting channel %d", csp->chno);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status = bscbus_get_reg(csp, H8_STR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (status & H8_STR_BUSY) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Give the h8 time to complete a reply.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * In practice we should never worry about this
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * because whenever we get here it will have been
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * long enough for the h8 to complete a reply
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'R', "bscbus_hw_reset",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "h8 reporting status (%x) busy - waiting", status);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ddi_in_panic()) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd drv_usecwait(BSCBUS_HWRESET_POLL/1000);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Reply should be completed by now. Try to clear busy status */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status = bscbus_get_reg(csp, H8_STR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (status & (H8_STR_BUSY | H8_STR_OBF)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'R', "bscbus_hw_reset",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "clearing busy status for channel %d", csp->chno);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (timeout = BSCBUS_HWRESET_TIMEOUT;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (timeout > 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd timeout -= BSCBUS_HWRESET_POLL) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (status & H8_STR_OBF) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) bscbus_get_reg(csp, H8_ODR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (!(status & H8_STR_BUSY)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* We are done */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ddi_in_panic()) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd drv_usecwait(BSCBUS_HWRESET_POLL/1000);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd status = bscbus_get_reg(csp, H8_STR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (timeout <= 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cmn_err(CE_WARN, "bscbus_hw_reset: timed out "
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "clearing busy status");
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * We read ODR just in case there is a pending interrupt with
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * no data. This is potentially dangerous because we could get
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * out of sync due to race conditions BUT at this point the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * channel should be idle so it is safe.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) bscbus_get_reg(csp, H8_ODR);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Higher-level setup & teardown
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_offline(struct bscbus_state *ssp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ssp->h8_handle != NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_regs_map_free(&ssp->h8_handle);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->h8_handle = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->h8_regs = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_online(struct bscbus_state *ssp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_acc_handle_t h;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd caddr_t p;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int nregs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int err;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->h8_handle = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->h8_regs = (void *)NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->per_channel_regs = B_FALSE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ddi_dev_nregs(ssp->dip, &nregs) != DDI_SUCCESS)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nregs = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (nregs) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case 1:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * regset 0 represents the H8 interface registers
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = ddi_regs_map_setup(ssp->dip, 0, &p, 0, 0,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_dev_acc_attr, &h);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (err != DDI_SUCCESS)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (EIO);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->h8_handle = h;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->h8_regs = (void *)p;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case 0:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * If no registers are defined, succeed vacuously;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * commands will be accepted, but we fake the accesses.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Remember that we are using the new register scheme.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * reg set 0 is chan 0
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * reg set 1 is chan 1 ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Interrupts are specified in that order but later
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * channels may not have interrupts.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * We map the regs later on a per channel basis.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->per_channel_regs = B_TRUE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_claim_channel(struct bscbus_channel_state *csp, boolean_t map_dog)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int err;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_enter(csp->ssp->ch_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->map_count++;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'C', "bscbus_claim_channel",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "claim channel for channel %d, count %d",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->chno, csp->map_count);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->map_count == 1) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* No-one is using this channel - initialise it */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'C', "bscbus_claim_channel",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "initialise channel %d, count %d",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->chno, csp->map_count);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_init(csp->dog_mutex, NULL, MUTEX_DRIVER,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void *)(uintptr_t)__ipltospl(SPL7 - 1));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->map_dog = map_dog;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->interrupt_failed = B_FALSE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->pat_retry_count = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->pat_fail_count = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Map appropriate register set for this channel */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->ssp->per_channel_regs == B_TRUE) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_acc_handle_t h;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd caddr_t p;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = ddi_regs_map_setup(csp->ssp->dip, csp->chno,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd &p, 0, 0, bscbus_dev_acc_attr, &h);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (err != DDI_SUCCESS) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd goto failed1;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_handle = h;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_regs = (void *)p;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'C', "bscbus_claim_channel",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "mapped chno=%d ch_handle=%d ch_regs=%p",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->chno, h, p);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * if using the old reg property scheme use the
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * common mapping.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_handle = csp->ssp->h8_handle;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_regs =
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ssp->h8_regs +
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BSCBUS_CHANNEL_TO_OFFSET(csp->chno);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* Ensure no interrupts pending prior to getting iblk cookie */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_hw_reset(csp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->map_dog == 1) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * we don't want lo_mutex to be initialised
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * with an iblock cookie if we are the wdog,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * because we don't use interrupts.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_init(csp->lo_mutex, NULL,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd MUTEX_DRIVER, NULL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cv_init(csp->lo_cv, NULL,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd CV_DRIVER, NULL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->unclaimed_count = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int ninterrupts;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * check that there is an interrupt for this
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * this channel. If we fail to setup interrupts we
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * must unmap the registers and fail.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = ddi_dev_nintrs(csp->ssp->dip, &ninterrupts);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (err != DDI_SUCCESS) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ninterrupts = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ninterrupts <= csp->chno) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cmn_err(CE_WARN,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "no interrupt available for "
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "bscbus channel %d", csp->chno);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd goto failed2;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ddi_intr_hilevel(csp->ssp->dip, csp->chno) != 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cmn_err(CE_WARN,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "bscbus interrupts are high "
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "level - channel not usable.");
1c42de6d020629af774dd9e9fc81be3f3ed9398egd goto failed2;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = ddi_get_iblock_cookie(csp->ssp->dip,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->chno, &csp->lo_iblk);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (err != DDI_SUCCESS) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd goto failed2;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_init(csp->lo_mutex, NULL,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd MUTEX_DRIVER, csp->lo_iblk);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cv_init(csp->lo_cv, NULL,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd CV_DRIVER, NULL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->unclaimed_count = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = ddi_add_intr(csp->ssp->dip, csp->chno,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd &csp->lo_iblk, NULL,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_hwintr, (caddr_t)csp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (err != DDI_SUCCESS) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cv_destroy(csp->lo_cv);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_destroy(csp->lo_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd goto failed2;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The channel is now live and may
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * receive interrupts
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd } else if (csp->map_dog != map_dog) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'C', "bscbus_claim_channel",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "request conflicts with previous mapping. old %x, new %x.",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->map_dog, map_dog);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd goto failed1;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_exit(csp->ssp->ch_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (1);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdfailed2:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* unmap regs for failed channel */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->ssp->per_channel_regs == B_TRUE) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_regs_map_free(&csp->ch_handle);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_handle = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_regs = (void *)NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egdfailed1:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->map_count--;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_exit(csp->ssp->ch_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic void
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_release_channel(struct bscbus_channel_state *csp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_enter(csp->ssp->ch_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->map_count == 1) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* No-one is now using this channel - shutdown channel */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'C', "bscbus_release_channel",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "shutdown channel %d, count %d",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->chno, csp->map_count);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->map_dog == 0) {
193974072f41a843678abf5f61979c748687e66bSherry Moore ASSERT(!ddi_intr_hilevel(csp->ssp->dip, csp->chno));
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_remove_intr(csp->ssp->dip, csp->chno, csp->lo_iblk);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cv_destroy(csp->lo_cv);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_destroy(csp->lo_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_destroy(csp->dog_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_hw_reset(csp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /* unmap registers if using the new register scheme */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (csp->ssp->per_channel_regs == B_TRUE) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_regs_map_free(&csp->ch_handle);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_handle = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ch_regs = (void *)NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->map_count--;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_trace(csp, 'C', "bscbus_release_channel",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "release channel %d, count %d",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->chno, csp->map_count);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_exit(csp->ssp->ch_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Nexus routines
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#if defined(NDI_ACC_HDL_V2)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic const ndi_acc_fns_t bscbus_vreg_acc_fns = {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd NDI_ACC_FNS_CURRENT,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd NDI_ACC_FNS_V1,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_vreg_get8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_vreg_put8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_vreg_rep_get8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_vreg_rep_put8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_get16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_put16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_get16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_put16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_get32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_put32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_rep_get32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_rep_put32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_get64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_put64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_get64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_put64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_acc_fault_check
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic const ndi_acc_fns_t bscbus_pat_acc_fns = {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd NDI_ACC_FNS_CURRENT,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd NDI_ACC_FNS_V1,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_pat_get8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_pat_put8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_pat_rep_get8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_pat_rep_put8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_get16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_put16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_get16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_put16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_get32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_put32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_rep_get32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_rep_put32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_get64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_put64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_get64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_put64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_acc_fault_check
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic const ndi_acc_fns_t bscbus_event_acc_fns = {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd NDI_ACC_FNS_CURRENT,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd NDI_ACC_FNS_V1,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_get8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_put8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_get8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_put8,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_event_get16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_event_put16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_event_rep_get16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_event_rep_put16,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_get32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_put32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_rep_get32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_meta_rep_put32,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_get64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_put64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_get64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_no_rep_put64,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_acc_fault_check
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int space, caddr_t vaddr, off_t len,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ndi_acc_handle_t *hdlp, caddr_t *addrp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (op) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_UNIMPLEMENTED);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_MO_MAP_LOCKED:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (bscbus_claim_channel(csp,
193974072f41a843678abf5f61979c748687e66bSherry Moore (space == LOMBUS_PAT_SPACE)) == 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_GENERIC);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (space) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_REGSPEC_RANGE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_VREG_SPACE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ndi_set_acc_fns(hdlp, &bscbus_vreg_acc_fns);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_PAT_SPACE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ndi_set_acc_fns(hdlp, &bscbus_pat_acc_fns);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_EVENT_SPACE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ndi_set_acc_fns(hdlp, &bscbus_event_acc_fns);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd hdlp->ah_addr = *addrp = vaddr;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd hdlp->ah_len = len;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd hdlp->ah_bus_private = csp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_MO_UNMAP:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *addrp = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd hdlp->ah_bus_private = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_release_channel(csp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#else
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int space, caddr_t vaddr, off_t len,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_acc_hdl_t *hdlp, caddr_t *addrp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_acc_impl_t *aip = hdlp->ah_platform_private;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (op) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_UNIMPLEMENTED);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_MO_MAP_LOCKED:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (bscbus_claim_channel(csp,
193974072f41a843678abf5f61979c748687e66bSherry Moore (space == LOMBUS_PAT_SPACE)) == 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_GENERIC);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (space) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_REGSPEC_RANGE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_VREG_SPACE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get8 = bscbus_vreg_get8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put8 = bscbus_vreg_put8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get8 = bscbus_vreg_rep_get8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put8 = bscbus_vreg_rep_put8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get16 = bscbus_no_get16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put16 = bscbus_no_put16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get16 = bscbus_no_rep_get16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put16 = bscbus_no_rep_put16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get32 = bscbus_meta_get32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put32 = bscbus_meta_put32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get32 = bscbus_meta_rep_get32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put32 = bscbus_meta_rep_put32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get64 = bscbus_no_get64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put64 = bscbus_no_put64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get64 = bscbus_no_rep_get64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put64 = bscbus_no_rep_put64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_fault_check = bscbus_acc_fault_check;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_PAT_SPACE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get8 = bscbus_pat_get8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put8 = bscbus_pat_put8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get8 = bscbus_pat_rep_get8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put8 = bscbus_pat_rep_put8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get16 = bscbus_no_get16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put16 = bscbus_no_put16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get16 = bscbus_no_rep_get16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put16 = bscbus_no_rep_put16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get32 = bscbus_meta_get32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put32 = bscbus_meta_put32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get32 = bscbus_meta_rep_get32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put32 = bscbus_meta_rep_put32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get64 = bscbus_no_get64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put64 = bscbus_no_put64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get64 = bscbus_no_rep_get64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put64 = bscbus_no_rep_put64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_fault_check = bscbus_acc_fault_check;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_EVENT_SPACE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get8 = bscbus_no_get8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put8 = bscbus_no_put8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get8 = bscbus_no_rep_get8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put8 = bscbus_no_rep_put8;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get16 = bscbus_event_get16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put16 = bscbus_event_put16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get16 = bscbus_event_rep_get16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put16 = bscbus_event_rep_put16;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get32 = bscbus_meta_get32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put32 = bscbus_meta_put32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get32 = bscbus_meta_rep_get32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put32 = bscbus_meta_rep_put32;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_get64 = bscbus_no_get64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_put64 = bscbus_no_put64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_get64 = bscbus_no_rep_get64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_rep_put64 = bscbus_no_rep_put64;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd aip->ahi_fault_check = bscbus_acc_fault_check;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd hdlp->ah_addr = *addrp = vaddr;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd hdlp->ah_len = len;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd hdlp->ah_bus_private = csp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_MO_UNMAP:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *addrp = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd hdlp->ah_bus_private = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_release_channel(csp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* NDI_ACC_HDL_V2 */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd off_t off, off_t len, caddr_t *addrp)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_child_info *lcip;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_state *ssp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd lombus_regspec_t *rsp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((ssp = bscbus_getstate(dip, -1, "bscbus_map")) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE); /* this "can't happen" */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Validate mapping request ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (mp->map_flags != DDI_MF_KERNEL_MAPPING)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_UNSUPPORTED);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (mp->map_handlep == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_UNSUPPORTED);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (mp->map_type != DDI_MT_RNUMBER)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_UNIMPLEMENTED);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((lcip = ddi_get_parent_data(rdip)) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_INVAL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((rsp = lcip->rsp) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_INVAL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (mp->map_obj.rnumber >= lcip->nregs)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_RNUMBER_RANGE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd rsp += mp->map_obj.rnumber;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (off < 0 || off >= rsp->lombus_size)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_INVAL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (len == 0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd len = rsp->lombus_size-off;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (len < 0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_INVAL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (off+len < 0 || off+len > rsp->lombus_size)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_ME_INVAL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (bscbus_map_handle(
193974072f41a843678abf5f61979c748687e66bSherry Moore &ssp->channel[LOMBUS_SPACE_TO_CHANNEL(rsp->lombus_space)],
193974072f41a843678abf5f61979c748687e66bSherry Moore mp->map_op, LOMBUS_SPACE_TO_REGSET(rsp->lombus_space),
193974072f41a843678abf5f61979c748687e66bSherry Moore VREG_TO_ADDR(rsp->lombus_base+off), len, mp->map_handlep, addrp));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd void *arg, void *result)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_child_info *lcip;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd lombus_regspec_t *rsp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd dev_info_t *cdip;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd char addr[32];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint_t nregs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint_t rnum;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int *regs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int limit;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int err;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int i;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (bscbus_getstate(dip, -1, "bscbus_ctlops") == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE); /* this "can't happen" */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (op) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_CTLOPS_INITCHILD:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * First, look up and validate the "reg" property.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * It must be a non-empty integer array containing a set
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * of triples. Once we've verified that, we can treat it
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * as an array of type lombus_regspec_t[], which defines
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * the meaning of the elements of each triple:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * + the first element of each triple must be a valid space
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * + the second and third elements (base, size) of each
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * triple must define a valid subrange of that space
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * If it passes all the tests, we save it away for future
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * reference in the child's parent-private-data field.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cdip = arg;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_PROP_DONTPASS, "reg", &regs, &nregs);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (err != DDI_PROP_SUCCESS)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = (nregs <= 0 || (nregs % LOMBUS_REGSPEC_SIZE) != 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nregs /= LOMBUS_REGSPEC_SIZE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd rsp = (lombus_regspec_t *)regs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (i = 0; i < nregs && !err; ++i) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (LOMBUS_SPACE_TO_REGSET(rsp[i].lombus_space)) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd limit = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = 1;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cmn_err(CE_WARN,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd "child(%p): unknown reg space %d",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void *)cdip, rsp[i].lombus_space);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_VREG_SPACE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd limit = LOMBUS_MAX_REG+1;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_PAT_SPACE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd limit = LOMBUS_PAT_REG+1;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case LOMBUS_EVENT_SPACE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd limit = LOMBUS_EVENT_REG+1;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err |= (rsp[i].lombus_base < 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err |= (rsp[i].lombus_base >= limit);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (rsp[i].lombus_size == 0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd rsp[i].lombus_size = limit-rsp[i].lombus_base;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err |= (rsp[i].lombus_size < 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err |= (rsp[i].lombus_base+rsp[i].lombus_size < 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (err) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_prop_free(regs);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd lcip = kmem_zalloc(sizeof (*lcip), KM_SLEEP);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd lcip->nregs = nregs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd lcip->rsp = rsp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_set_parent_data(cdip, lcip);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) snprintf(addr, sizeof (addr),
193974072f41a843678abf5f61979c748687e66bSherry Moore "%x,%x", rsp[0].lombus_space, rsp[0].lombus_base);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_set_name_addr(cdip, addr);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_CTLOPS_UNINITCHILD:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cdip = arg;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_set_name_addr(cdip, NULL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd lcip = ddi_get_parent_data(cdip);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_set_parent_data(cdip, NULL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_prop_free(lcip->rsp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd kmem_free(lcip, sizeof (*lcip));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_CTLOPS_REPORTDEV:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (rdip == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd cmn_err(CE_CONT, "?BSC device: %s@%s, %s#%d\n",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_node_name(rdip), ddi_get_name_addr(rdip),
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_driver_name(dip), ddi_get_instance(dip));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_CTLOPS_REGSIZE:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((lcip = ddi_get_parent_data(rdip)) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((rnum = *(uint_t *)arg) >= lcip->nregs)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *(off_t *)result = lcip->rsp[rnum].lombus_size;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_CTLOPS_NREGS:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((lcip = ddi_get_parent_data(rdip)) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd *(int *)result = lcip->nregs;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (ddi_ctlops(dip, rdip, op, arg, result));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * This nexus does not support passing interrupts to leaf drivers, so
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * all the intrspec-related operations just fail as cleanly as possible.
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*ARGSUSED*/
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_intr_handle_impl_t *hdlp, void *result)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#if defined(__sparc)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (i_ddi_intr_ops(dip, rdip, op, hdlp, result));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#else
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(dip, rdip, op, hdlp, result))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Clean up on detach or failure of attach
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_unattach(struct bscbus_state *ssp, int instance)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int chno;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ssp != NULL) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ASSERT(ssp->channel[chno].map_count == 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_offline(ssp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_set_driver_private(ssp->dip, NULL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_destroy(ssp->ch_mutex);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#ifdef BSCBUS_LOGSTATUS
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ssp->cmd_log_size != 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd kmem_free(ssp->cmd_log,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->cmd_log_size * sizeof (bsc_cmd_log_t));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* BSCBUS_LOGSTATUS */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_soft_state_free(bscbus_statep, instance);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Autoconfiguration routines
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_state *ssp = NULL;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int chno;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int instance;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int err;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (cmd) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_ATTACH:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Allocate the soft-state structure
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd instance = ddi_get_instance(dip);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ddi_soft_state_zalloc(bscbus_statep, instance) != DDI_SUCCESS)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((ssp = bscbus_getstate(dip, instance, "bscbus_attach")) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (bscbus_unattach(ssp, instance));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_set_driver_private(dip, ssp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Initialise devinfo-related fields
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->dip = dip;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->majornum = ddi_driver_major(dip);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->instance = instance;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Set various options from .conf properties
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
193974072f41a843678abf5f61979c748687e66bSherry Moore DDI_PROP_DONTPASS, "debug", 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd mutex_init(ssp->ch_mutex, NULL, MUTEX_DRIVER, NULL);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#ifdef BSCBUS_LOGSTATUS
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->cmd_log_size = bscbus_cmd_log_size;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ssp->cmd_log_size != 0) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ssp->cmd_log_idx = 0;
193974072f41a843678abf5f61979c748687e66bSherry Moore ssp->cmd_log = kmem_zalloc(ssp->cmd_log_size *
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (bsc_cmd_log_t), KM_SLEEP);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* BSCBUS_LOGSTATUS */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Online the hardware ...
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = bscbus_online(ssp);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (err != 0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (bscbus_unattach(ssp, instance));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_channel_state *csp = &ssp->channel[chno];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Initialise state
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * The hardware/interrupts are setup at map time to
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * avoid claiming hardware that OBP is using
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->ssp = ssp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->chno = chno;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->map_count = 0;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd csp->map_dog = B_FALSE;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd /*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * All done, report success
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_report_dev(dip);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_state *ssp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int instance;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd switch (cmd) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd default:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd case DDI_DETACH:
1c42de6d020629af774dd9e9fc81be3f3ed9398egd break;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd instance = ddi_get_instance(dip);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((ssp = bscbus_getstate(dip, instance, "bscbus_detach")) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE); /* this "can't happen" */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd (void) bscbus_unattach(ssp, instance);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic int
1c42de6d020629af774dd9e9fc81be3f3ed9398egdbscbus_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_state *ssp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int chno;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd _NOTE(ARGUNUSED(cmd))
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((ssp = bscbus_getstate(dip, -1, "bscbus_reset")) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_FAILURE);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_hw_reset(&ssp->channel[chno]);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (DDI_SUCCESS);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * System interface structures
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic struct cb_ops bscbus_cb_ops =
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* b/c open */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* b/c close */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* b strategy */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* b print */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* b dump */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* c read */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* c write */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* c ioctl */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* c devmap */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* c mmap */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nodev, /* c segmap */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nochpoll, /* c poll */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_prop_op, /* b/c prop_op */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd NULL, /* c streamtab */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd D_MP | D_NEW /* b/c flags */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic struct bus_ops bscbus_bus_ops =
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd BUSO_REV, /* revision */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_map, /* bus_map */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* get_intrspec */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* add_intrspec */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* remove_intrspec */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd i_ddi_map_fault, /* map_fault */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_no_dma_map, /* dma_map */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_no_dma_allochdl, /* allocate DMA handle */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_no_dma_freehdl, /* free DMA handle */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_no_dma_bindhdl, /* bind DMA handle */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_no_dma_unbindhdl, /* unbind DMA handle */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_no_dma_flush, /* flush DMA */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_no_dma_win, /* move DMA window */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_no_dma_mctl, /* generic DMA control */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_ctlops, /* generic control */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_bus_prop_op, /* prop_op */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ndi_busop_get_eventcookie, /* get_eventcookie */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ndi_busop_add_eventcall, /* add_eventcall */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ndi_busop_remove_eventcall, /* remove_eventcall */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ndi_post_event, /* post_event */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* interrupt control */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* bus_config */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* bus_unconfig */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* bus_fm_init */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* bus_fm_fini */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* bus_fm_access_enter */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* bus_fm_access_exit */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* bus_power */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_intr_op /* bus_intr_op */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic struct dev_ops bscbus_dev_ops =
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd DEVO_REV,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd 0, /* refcount */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_no_info, /* getinfo */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nulldev, /* identify */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd nulldev, /* probe */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_attach, /* attach */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_detach, /* detach */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_reset, /* reset */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd &bscbus_cb_ops, /* driver operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore &bscbus_bus_ops, /* bus operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_needed, /* quiesce */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic struct modldrv modldrv =
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd &mod_driverops,
193974072f41a843678abf5f61979c748687e66bSherry Moore "bscbus driver",
1c42de6d020629af774dd9e9fc81be3f3ed9398egd &bscbus_dev_ops
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdstatic struct modlinkage modlinkage =
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd MODREV_1,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd &modldrv,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd NULL
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd};
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd/*
1c42de6d020629af774dd9e9fc81be3f3ed9398egd * Dynamic loader interface code
1c42de6d020629af774dd9e9fc81be3f3ed9398egd */
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdint
1c42de6d020629af774dd9e9fc81be3f3ed9398egd_init(void)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int err;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd err = ddi_soft_state_init(&bscbus_statep,
193974072f41a843678abf5f61979c748687e66bSherry Moore sizeof (struct bscbus_state), 0);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (err == DDI_SUCCESS)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((err = mod_install(&modlinkage)) != DDI_SUCCESS) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_soft_state_fini(&bscbus_statep);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (err);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdint
1c42de6d020629af774dd9e9fc81be3f3ed9398egd_info(struct modinfo *mip)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (mod_info(&modlinkage, mip));
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egdint
1c42de6d020629af774dd9e9fc81be3f3ed9398egd_fini(void)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int err;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((err = mod_remove(&modlinkage)) == DDI_SUCCESS) {
1c42de6d020629af774dd9e9fc81be3f3ed9398egd ddi_soft_state_fini(&bscbus_statep);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bscbus_major = NOMAJOR;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd }
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return (err);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#ifdef BSCBUS_LOGSTATUS
1c42de6d020629af774dd9e9fc81be3f3ed9398egdvoid bscbus_cmd_log(struct bscbus_channel_state *csp, bsc_cmd_stamp_t cat,
1c42de6d020629af774dd9e9fc81be3f3ed9398egd uint8_t status, uint8_t data)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd{
1c42de6d020629af774dd9e9fc81be3f3ed9398egd int idx;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd bsc_cmd_log_t *logp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd struct bscbus_state *ssp;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((csp) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((ssp = (csp)->ssp) == NULL)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if (ssp->cmd_log_size == 0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd if ((bscbus_cmd_log_flags & (1 << cat)) == 0)
1c42de6d020629af774dd9e9fc81be3f3ed9398egd return;
1a5e258f5471356ca102c7176637cdce45bac147Josef 'Jeff' Sipek idx = atomic_inc_32_nv(&ssp->cmd_log_idx);
1c42de6d020629af774dd9e9fc81be3f3ed9398egd logp = &ssp->cmd_log[idx % ssp->cmd_log_size];
1c42de6d020629af774dd9e9fc81be3f3ed9398egd logp->bcl_seq = idx;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd logp->bcl_cat = cat;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd logp->bcl_now = gethrtime();
1c42de6d020629af774dd9e9fc81be3f3ed9398egd logp->bcl_chno = csp->chno;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd logp->bcl_cmdstate = csp->cmdstate;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd logp->bcl_status = status;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd logp->bcl_data = data;
1c42de6d020629af774dd9e9fc81be3f3ed9398egd}
1c42de6d020629af774dd9e9fc81be3f3ed9398egd#endif /* BSCBUS_LOGSTATUS */