3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * CDDL HEADER START
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The contents of this file are subject to the terms of the
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota * Common Development and Distribution License (the "License").
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota * You may not use this file except in compliance with the License.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * or http://www.opensolaris.org/os/licensing.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * See the License for the specific language governing permissions
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and limitations under the License.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * When distributing Covered Code, include this CDDL HEADER in each
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If applicable, add the following below this CDDL HEADER, with the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * fields enclosed by brackets "[]" replaced with your own identifying
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * information: Portions Copyright [yyyy] [name of copyright owner]
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * CDDL HEADER END
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Use is subject to license terms.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The "lombus" driver provides access to the LOMlite2 virtual registers,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * so that its clients (children) need not be concerned with the details
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * of the access mechanism, which in this case is implemented via a
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * packet-based protocol over a serial link connected to one of the serial
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * ports of the SuperIO (SIO) chip.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * On the other hand, this driver doesn't generally know what the virtual
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * registers signify - only the clients need this information.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Header files
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/types.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/conf.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/debug.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/errno.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/file.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/intr.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/kmem.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/membar.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/modctl.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/note.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/open.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/poll.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/spl.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/stat.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/strlog.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/ddi.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/sunddi.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/sunndi.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#include <sys/lombus.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#if defined(NDI_ACC_HDL_V2)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Compiling for Solaris 9+ with access handle enhancements
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_TYPE ndi_acc_handle_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_ADDR(hdlp) (hdlp->ah_addr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_FAULT(hdlp) (hdlp->ah_fault)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_MAPLEN(hdlp) (hdlp->ah_len)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_PRIVATE(hdlp) (hdlp->ah_bus_private)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#else
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Compatibility definitions for backport to Solaris 8
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_TYPE ddi_acc_impl_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_ADDR(hdlp) (hdlp->ahi_common.ah_addr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_FAULT(hdlp) (hdlp->ahi_fault)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_MAPLEN(hdlp) (hdlp->ahi_common.ah_len)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_PRIVATE(hdlp) (hdlp->ahi_common.ah_bus_private)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define ddi_driver_major(dip) ddi_name_to_major(ddi_binding_name(dip))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#endif /* NDI_ACC_HDL_V2 */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Local definitions
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define MYNAME "lombus"
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define NOMAJOR (~(major_t)0)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define DUMMY_VALUE (~(int8_t)0)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_INST_TO_MINOR(i) (i)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_MINOR_TO_INST(m) (m)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_DUMMY_ADDRESS ((caddr_t)0x0CADD1ED)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define ADDR_TO_OFFSET(a, hdlp) ((caddr_t)(a) - HANDLE_ADDR(hdlp))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define ADDR_TO_VREG(a) ((caddr_t)(a) - LOMBUS_DUMMY_ADDRESS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define VREG_TO_ADDR(v) (LOMBUS_DUMMY_ADDRESS + (v))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The following definitions are taken from the datasheet
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * for the National Semiconductor PC87317 (SuperIO) chip.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This chip implements UART functionality as logical device 6.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * It provides all sorts of wierd modes and extensions, but we
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * have chosen to use only the 16550-compatible features
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * ("non-extended mode").
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Hardware: serial chip register numbers
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_RXD 0 /* read */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_TXD 0 /* write */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_IER 1
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_EIR 2 /* read */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_FCR 2 /* write */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR 3
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_BSR 3 /* wierd */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MCR 4
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LSR 5
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MSR 6
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_SCR 7
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LBGDL 0 /* bank 1 */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LBGDH 1 /* bank 1 */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Hardware: serial chip register bits
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_IER_RXHDL_IE 0x01
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_IER_STD 0x00
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_EIR_IPF 0x01
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_EIR_IPR0 0x02
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_EIR_IPR1 0x04
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_EIR_RXFT 0x08
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_EIR_FEN0 0x40
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_EIR_FEN1 0x80
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_FCR_FIFO_EN 0x01
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_FCR_RXSR 0x02
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_FCR_TXSR 0x04
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_FCR_RXFTH0 0x40
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_FCR_RXFTH1 0x80
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_FCR_STD (SIO_FCR_RXFTH0|SIO_FCR_FIFO_EN)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_WLS0 0x01
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_WLS1 0x02
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_STB 0x04
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_PEN 0x08
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_EPS 0x10
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_STKP 0x20
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_SBRK 0x40
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_BKSE 0x80
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_8BIT (SIO_LCR_WLS0|SIO_LCR_WLS1)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_EPAR (SIO_LCR_PEN|SIO_LCR_EPS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LCR_STD (SIO_LCR_8BIT|SIO_LCR_EPAR)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_BSR_BANK0 (SIO_LCR_STD)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_BSR_BANK1 (SIO_LCR_BKSE|SIO_LCR_STD)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MCR_DTR 0x01
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MCR_RTS 0x02
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MCR_ISEN 0x08
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MCR_STD (SIO_MCR_ISEN)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LSR_RXDA 0x01
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LSR_OE 0x02
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LSR_PE 0x04
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LSR_FE 0x08
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LSR_BRKE 0x10
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LSR_TXRDY 0x20
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LSR_TXEMP 0x40
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_LSR_ER_INF 0x80
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MSR_DCTS 0x01
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MSR_DDSR 0x02
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MSR_TERI 0x04
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MSR_DDCD 0x08
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MSR_CTS 0x10
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MSR_DSR 0x20
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MSR_RI 0x40
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_MSR_DCD 0x80
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Min/max/default baud rates, and a macro to convert from a baud
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * rate to the number (divisor) to put in the baud rate registers
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_BAUD_MIN 50
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_BAUD_MAX 115200
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_BAUD_DEFAULT 38400
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define SIO_BAUD_TO_DIVISOR(b) (115200 / (b))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Packet format ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_MASK 0xc0 /* Byte-type bits */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_PARAM 0x00 /* Parameter byte: 0b0xxxxxxx */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_LAST 0x80 /* Last byte of packet */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CMD 0x80 /* Command byte: 0b10###XWV */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_STATUS 0xc0 /* Status byte: 0b11###AEV */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_SEQ 0x38 /* Sequence number bits */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_SEQ_LSB 0x08 /* Sequence number LSB */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CMD_XADDR 0x04 /* Extended (2-byte) addressing */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CMD_WRITE 0x02 /* Write command */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CMD_WMSB 0x01 /* Set MSB on Write */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CMD_READ 0x01 /* Read command */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CMD_NOP 0x00 /* NOP command */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_STATUS_ASYNC 0x04 /* Asynchronous event pending */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_STATUS_ERR 0x02 /* Error in command processing */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_STATUS_MSB 0x01 /* MSB of Value read */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_VREG_LO(x) ((x) & ((1 << 7) - 1))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_VREG_HI(x) ((x) >> 7)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_BUFSIZE 8
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Time periods, in nanoseconds
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Note that LOMBUS_ONE_SEC and some other time
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * periods are defined in <sys/lombus.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CMD_POLL (LOMBUS_ONE_SEC/20)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CTS_POLL (LOMBUS_ONE_SEC/20)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CTS_TIMEOUT (LOMBUS_ONE_SEC*2)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Local datatypes
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelenum lombus_cmdstate {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel LOMBUS_CMDSTATE_IDLE,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel LOMBUS_CMDSTATE_BUSY,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel LOMBUS_CMDSTATE_WAITING,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel LOMBUS_CMDSTATE_READY,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel LOMBUS_CMDSTATE_ERROR
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This driver's soft-state structure
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstruct lombus_state {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Configuration data, set during attach
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel dev_info_t *dip;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel major_t majornum;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int instance;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_acc_handle_t sio_handle;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t *sio_regs;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_softintr_t softid;
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ddi_periodic_t cycid; /* periodical callback */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Parameters derived from .conf properties
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel boolean_t allow_echo;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int baud;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint32_t debug;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel boolean_t fake_cts;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Hardware mutex (initialised using <hw_iblk>),
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * used to prevent retriggering the softint while
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * it's still fetching data out of the chip FIFO.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel kmutex_t hw_mutex[1];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_iblock_cookie_t hw_iblk;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Data protected by the hardware mutex: the watchdog-patting
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * protocol data (since the dog can be patted from a high-level
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * cyclic), and the interrupt-enabled flag.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hrtime_t hw_last_pat;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel boolean_t hw_int_enabled;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Flag to indicate that we've incurred a hardware fault on
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * accesses to the SIO; once this is set, we fake all further
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * accesses in order not to provoke additional bus errors.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel boolean_t sio_fault;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Serial protocol state data, protected by lo_mutex
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (which is initialised using <lo_iblk>)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel kmutex_t lo_mutex[1];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_iblock_cookie_t lo_iblk;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel kcondvar_t lo_cv[1];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel volatile enum lombus_cmdstate cmdstate;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel clock_t deadline;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t cmdbuf[LOMBUS_BUFSIZE];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t reply[LOMBUS_BUFSIZE];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t async;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t index;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t result;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t sequence;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint32_t error;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The auxiliary structure attached to each child
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (the child's parent-private-data points to this).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstruct lombus_child_info {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_regspec_t *rsp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int nregs;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Local data
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void *lombus_statep;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic major_t lombus_major = NOMAJOR;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic ddi_device_acc_attr_t lombus_dev_acc_attr[1] =
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DDI_DEVICE_ATTR_V0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DDI_STRUCTURE_LE_ACC,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DDI_STRICTORDER_ACC
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * General utility routines ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_trace(struct lombus_state *ssp, char code, const char *caller,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel const char *fmt, ...)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel char buf[256];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel char *p;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel va_list va;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->debug & (1 << (code-'@'))) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel p = buf;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) snprintf(p, sizeof (buf) - (p - buf),
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "%s/%s: ", MYNAME, caller);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel p += strlen(p);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel va_start(va, fmt);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) vsnprintf(p, sizeof (buf) - (p - buf), fmt, va);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel va_end(va);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel buf[sizeof (buf) - 1] = '\0';
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strlog(ssp->majornum, ssp->instance, code, SL_TRACE,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki buf);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic struct lombus_state *
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_getstate(dev_info_t *dip, int instance, const char *caller)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel dev_info_t *sdip = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel major_t dmaj = NOMAJOR;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (dip != NULL) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Use the instance number from the <dip>; also,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * check that it really corresponds to this driver
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel instance = ddi_get_instance(dip);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel dmaj = ddi_driver_major(dip);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (lombus_major == NOMAJOR && dmaj != NOMAJOR)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_major = dmaj;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel else if (dmaj != lombus_major) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "%s: major number mismatch (%d vs. %d) in %s(),"
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "probably due to child misconfiguration",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel MYNAME, lombus_major, dmaj, caller);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel instance = -1;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (instance >= 0)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp = ddi_get_soft_state(lombus_statep, instance);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp != NULL) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sdip = ssp->dip;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (dip == NULL && sdip == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel else if (dip != NULL && sdip != NULL && sdip != dip) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_WARN,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "%s: devinfo mismatch (%p vs. %p) in %s(), "
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "probably due to child misconfiguration",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel MYNAME, (void *)dip, (void *)sdip, caller);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Lowest-level serial I/O chip register read/write
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevelsio_put_reg(struct lombus_state *ssp, uint_t reg, uint8_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'P', "sio_put_reg", "REG[%d] <- $%02x", reg, val);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->sio_handle != NULL && !ssp->sio_fault) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The chip is mapped as "I/O" (e.g. with the side-effect
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * bit on SPARC), therefore accesses are required to be
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * in-order, with no value cacheing. However, there can
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * still be write-behind buffering, so it is not guaranteed
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * that a write actually reaches the chip in a given time.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * To force the access right through to the chip, we follow
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * the write with another write (to the SCRATCH register)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and a read (of the value just written to the SCRATCH
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * register). The SCRATCH register is specifically provided
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * for temporary data and has no effect on the SIO's own
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * operation, making it ideal as a synchronising mechanism.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If we didn't do this, it would be possible that the new
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * value wouldn't reach the chip (and have the *intended*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * side-effects, such as disabling interrupts), for such a
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * long time that the processor could execute a *lot* of
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * instructions - including exiting the interrupt service
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * routine and re-enabling interrupts. This effect was
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * observed to lead to spurious (unclaimed) interrupts in
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * some circumstances.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This will no longer be needed once "synchronous" access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * handles are available (see PSARC/2000/269 and 2000/531).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_put8(ssp->sio_handle, ssp->sio_regs + reg, val);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_put8(ssp->sio_handle, ssp->sio_regs + SIO_SCR, val);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel membar_sync();
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) ddi_get8(ssp->sio_handle, ssp->sio_regs + SIO_SCR);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint8_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevelsio_get_reg(struct lombus_state *ssp, uint_t reg)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t val;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->sio_handle && !ssp->sio_fault)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val = ddi_get8(ssp->sio_handle, ssp->sio_regs + reg);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel else
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val = DUMMY_VALUE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'G', "sio_get_reg", "$%02x <- REG[%d]", val, reg);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (val);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevelsio_check_fault_status(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->sio_fault = ddi_check_acc_handle(ssp->sio_handle) != DDI_SUCCESS;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic boolean_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevelsio_faulty(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (!ssp->sio_fault)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_check_fault_status(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (ssp->sio_fault);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check for data ready.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic boolean_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevelsio_data_ready(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t status;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Data is available if the RXDA bit in the LSR is nonzero
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (if reading it didn't incur a fault).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = sio_get_reg(ssp, SIO_LSR);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return ((status & SIO_LSR_RXDA) != 0 && !sio_faulty(ssp));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check for LOM ready
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic boolean_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevelsio_lom_ready(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t status;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel boolean_t rslt;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The LOM is ready if the CTS bit in the MSR is 1, meaning
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * that the /CTS signal is being asserted (driven LOW) -
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * unless we incurred a fault in trying to read the MSR!
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * For debugging, we force the result to TRUE if the FAKE flag is set
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = sio_get_reg(ssp, SIO_MSR);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel rslt = (status & SIO_MSR_CTS) != 0 && !sio_faulty(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'R', "sio_lom_ready", "S $%02x R %d F %d",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota status, rslt, ssp->fake_cts);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (rslt || ssp->fake_cts);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#if 0
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check for interrupt pending
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic boolean_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevelsio_irq_pending(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t status;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel boolean_t rslt;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * An interrupt is pending if the IPF bit in the EIR is 0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * assuming we didn't incur a fault in trying to ready it.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Note: we expect that every time we read this register
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (which is only done from the interrupt service routine),
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we will see $11001100 (RX FIFO timeout interrupt pending).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel status = sio_get_reg(ssp, SIO_EIR);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel rslt = (status & SIO_EIR_IPF) == 0 && !sio_faulty(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'I', "sio_irq_pending", "S $%02x R %d",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota status, rslt);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * To investigate whether we're getting any abnormal interrupts
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * this code checks that the status value is as expected, and that
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * chip-level interrupts are supposed to be enabled at this time.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This will cause a PANIC (on a driver compiled with DEBUG) if
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * all is not as expected ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ASSERT(status == 0xCC);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ASSERT(ssp->hw_int_enabled);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (rslt);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#endif /* 0 */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Enable/disable interrupts
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_set_irq(struct lombus_state *ssp, boolean_t newstate)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t val;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val = newstate ? SIO_IER_RXHDL_IE : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_IER, SIO_IER_STD | val);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->hw_int_enabled = newstate;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Assert/deassert RTS
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_toggle_rts(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t val;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val = sio_get_reg(ssp, SIO_MCR);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val &= SIO_MCR_RTS;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val ^= SIO_MCR_RTS;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val |= SIO_MCR_STD;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_MCR, val);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * High-level interrupt handler:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Checks whether initialisation is complete (to avoid a race
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * with mutex_init()), and whether chip interrupts are enabled.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If not, the interrupt's not for us, so just return UNCLAIMED.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Otherwise, disable the interrupt, trigger a softint, and return
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * CLAIMED. The softint handler will then do all the real work.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * NOTE: the chip interrupt capability is only re-enabled once the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * receive code has run, but that can be called from a poll loop
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * or cyclic callback as well as from the softint. So it's *not*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * guaranteed that there really is a chip interrupt pending here,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * 'cos the work may already have been done and the reason for the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * interrupt gone away before we get here.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * OTOH, if we come through here twice without the receive code
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * having run in between, that's definitely wrong. In such an
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * event, we would notice that chip interrupts haven't yet been
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * re-enabled and return UNCLAIMED, allowing the system's jabber
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * protect code (if any) to do its job.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_hi_intr(caddr_t arg)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp = (void *)arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint_t claim;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel claim = DDI_INTR_UNCLAIMED;
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota if (ssp->cycid != NULL) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_enter(ssp->hw_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->hw_int_enabled) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_set_irq(ssp, B_FALSE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_trigger_softintr(ssp->softid);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel claim = DDI_INTR_CLAIMED;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_exit(ssp->hw_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (claim);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Packet receive handler
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This routine should be called from the low-level softint, or the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * cyclic callback, or lombus_cmd() (for polled operation), with the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * low-level mutex already held.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_receive(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel boolean_t ready = B_FALSE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t data = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t rcvd = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t tmp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'S', "lombus_receive",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "state %d; error $%x",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->cmdstate, ssp->error);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check for access faults before starting the receive
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * loop (we don't want to cause bus errors or suchlike
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * unpleasantness in the event that the SIO has died).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (!sio_faulty(ssp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Read bytes from the FIFO until they're all gone,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * or we find the 'END OF PACKET' set on one, or
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * our buffer overflows (which must be an error)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_enter(ssp->hw_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel while (sio_data_ready(ssp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel data = sio_get_reg(ssp, SIO_RXD);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->reply[rcvd = ssp->index] = data;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (++rcvd >= LOMBUS_BUFSIZE)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->index = rcvd;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (data & LOMBUS_LAST)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_set_irq(ssp, B_TRUE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_exit(ssp->hw_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'S', "lombus_receive",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "rcvd %d: $%02x $%02x $%02x $%02x $%02x $%02x $%02x $%02x",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota rcvd,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->reply[0], ssp->reply[1],
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->reply[2], ssp->reply[3],
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->reply[4], ssp->reply[5],
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->reply[6], ssp->reply[7]);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->cmdstate != LOMBUS_CMDSTATE_WAITING) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * We're not expecting any data in this state, so if
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we DID receive any data, we just throw it away by
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * resetting the buffer index to 0.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->index = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else if (rcvd == 0) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * No bytes received this time through (though there
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * might be a partial packet sitting in the buffer).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If it seems the LOM is taking too long to respond,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we'll assume it's died and return an error.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_get_lbolt() > ssp->deadline) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_ERROR;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->error = LOMBUS_ERR_TIMEOUT;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ready = B_TRUE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else if (rcvd >= LOMBUS_BUFSIZE) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Buffer overflow; discard the data & treat as an error
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (even if the last byte read did claim to terminate a
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * packet, it can't be a valid one 'cos it's too long!)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->index = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_ERROR;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->error = LOMBUS_ERR_OFLOW;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ready = B_TRUE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else if ((data & LOMBUS_LAST) == 0) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Packet not yet complete; leave the partial packet in
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * the buffer for later ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(EMPTY)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else if ((data & LOMBUS_MASK) != LOMBUS_STATUS) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid "status" byte - maybe an echo of the command?
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * As a debugging feature, we allow for this, assuming
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * that if the LOM has echoed the command byte, it has
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * also echoed all the parameter bytes before starting
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * command processing. So, we dump out the buffer and
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * then clear it, so we can go back to looking for the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * real reply.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Otherwise, we just drop the data & flag an error.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->allow_echo) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'E', "lombus_receive",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "echo $%02x $%02x $%02x $%02x "
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "$%02x $%02x $%02x $%02x",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->reply[0], ssp->reply[1],
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->reply[2], ssp->reply[3],
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->reply[4], ssp->reply[5],
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->reply[6], ssp->reply[7]);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->index = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_ERROR;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->error = LOMBUS_ERR_BADSTATUS;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ready = B_TRUE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else if ((data & LOMBUS_SEQ) != ssp->sequence) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Wrong sequence number! Flag this as an error
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_ERROR;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->error = LOMBUS_ERR_SEQUENCE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ready = B_TRUE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Finally, we know that's it's a valid reply to our
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * last command. Update the ASYNC status, derive the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * reply parameter (if any), and check the ERROR bit
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * to find out what the parameter means.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Note that not all the values read/assigned here
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * are meaningful, but it doesn't matter; the waiting
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * thread will know which one(s) it should check.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->async = (data & LOMBUS_STATUS_ASYNC) ? 1 : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel tmp = ((data & LOMBUS_STATUS_MSB) ? 0x80 : 0) | ssp->reply[0];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (data & LOMBUS_STATUS_ERR) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_ERROR;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->error = tmp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_READY;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->result = tmp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ready = B_TRUE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'T', "lombus_receive",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "rcvd %d; last $%02x; state %d; error $%x; ready %d",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota rcvd, data, ssp->cmdstate, ssp->error, ready);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ready)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cv_broadcast(ssp->lo_cv);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Low-level softint handler
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This routine should be triggered whenever there's a byte to be read
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_softint(caddr_t arg)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp = (void *)arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_enter(ssp->lo_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_receive(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_exit(ssp->lo_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_INTR_CLAIMED);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Cyclic handler: just calls the receive routine, in case interrupts
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * are not being delivered and in order to handle command timeout
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_cyclic(void *arg)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp = (void *)arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_enter(ssp->lo_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_receive(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_exit(ssp->lo_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Serial protocol
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This routine builds a command and sets it in progress.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint8_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_cmd(HANDLE_TYPE *hdlp, ptrdiff_t vreg, uint_t val, uint_t cmd)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel clock_t start;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t *p;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * First of all, wait for the interface to be available.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * NOTE: we blow through all the mutex/cv/state checking and
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * preempt any command in progress if the system is panicking!
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp = HANDLE_PRIVATE(hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_enter(ssp->lo_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel while (ssp->cmdstate != LOMBUS_CMDSTATE_IDLE && !panicstr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cv_wait(ssp->lo_cv, ssp->lo_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_BUSY;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->sequence = (ssp->sequence + LOMBUS_SEQ_LSB) & LOMBUS_SEQ;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * We have exclusive ownership, so assemble the command (backwards):
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * [byte 0] Command: modified by XADDR and/or WMSB bits
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * [Optional] Parameter: Value to write (low 7 bits)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * [Optional] Parameter: Register number (high 7 bits)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * [Optional] Parameter: Register number (low 7 bits)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel p = &ssp->cmdbuf[0];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *p++ = LOMBUS_CMD | ssp->sequence | cmd;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (cmd) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_CMD_WRITE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *p++ = val & 0x7f;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (val >= 0x80)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdbuf[0] |= LOMBUS_CMD_WMSB;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*FALLTHRU*/
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_CMD_READ:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (LOMBUS_VREG_HI(vreg) != 0) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *p++ = LOMBUS_VREG_HI(vreg);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdbuf[0] |= LOMBUS_CMD_XADDR;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *p++ = LOMBUS_VREG_LO(vreg);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*FALLTHRU*/
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_CMD_NOP:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check and update the SIO h/w fault status before accessing
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * the chip registers. If there's a (new or previous) fault,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we'll run through the protocol but won't really touch the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * hardware and all commands will timeout. If a previously
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * discovered fault has now gone away (!), then we can (try to)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * proceed with the new command (probably a probe).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_check_fault_status(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Wait up to LOMBUS_CTS_TIMEOUT (2 seconds) for the LOM to tell
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * us that it's ready for the next command. If it doesn't, though,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we'll send it anyway, on the basis that the CTS signal might be
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * open- or short-circuited (or the LOM firmware forgot to set it,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * or the LOM just got reset, or whatever ...)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel start = ddi_get_lbolt();
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->deadline = start + drv_usectohz(LOMBUS_CTS_TIMEOUT/1000);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel while (!sio_lom_ready(ssp)) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (ddi_get_lbolt() > ssp->deadline)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) cv_reltimedwait(ssp->lo_cv, ssp->lo_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_usectohz(LOMBUS_CTS_POLL/1000), TR_CLOCK_TICK);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Either the LOM is ready, or we timed out waiting for CTS.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * In either case, we're going to send the command now by
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * stuffing the packet into the Tx FIFO, reversing it as we go.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * We call lombus_receive() first to ensure there isn't any
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * garbage left in the Rx FIFO from an earlier command that
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * timed out (or was pre-empted by a PANIC!). This also makes
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * sure that SIO interrupts are enabled so we'll see the reply
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * more quickly (the poll loop below will still work even if
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * interrupts aren't enabled, but it will take longer).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_receive(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_enter(ssp->hw_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel while (p > ssp->cmdbuf)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_TXD, *--p);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_exit(ssp->hw_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Prepare for the reply (to be processed by the interrupt/cyclic
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * handler and/or polling loop below), then wait for a response
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * or timeout.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel start = ddi_get_lbolt();
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->deadline = start + drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->error = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->index = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->result = DUMMY_VALUE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_WAITING;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel while (ssp->cmdstate == LOMBUS_CMDSTATE_WAITING) {
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (cv_reltimedwait(ssp->lo_cv, ssp->lo_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_usectohz(LOMBUS_CMD_POLL/1000), TR_CLOCK_TICK) == -1)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_receive(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The return value may not be meaningful but retrieve it anyway
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val = ssp->result;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (sio_faulty(ssp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val = DUMMY_VALUE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_SIOHW;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel } else if (ssp->cmdstate != LOMBUS_CMDSTATE_READY) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Some problem here ... transfer the error code from
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * the per-instance state to the per-handle fault flag.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The error code shouldn't be zero!
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->error != 0)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = ssp->error;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel else
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_BADERRCODE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * All done now!
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->index = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_IDLE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cv_broadcast(ssp->lo_cv);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_exit(ssp->lo_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (val);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Space 0 - LOM virtual register access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Only 8-bit accesses are supported.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint8_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_vreg_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ptrdiff_t offset;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel offset = ADDR_TO_OFFSET(addr, hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DUMMY_VALUE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Derive the virtual register number and run the command
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (lombus_cmd(hdlp, ADDR_TO_VREG(addr), 0, LOMBUS_CMD_READ));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_vreg_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ptrdiff_t offset;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel offset = ADDR_TO_OFFSET(addr, hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Derive the virtual register number and run the command
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) lombus_cmd(hdlp, ADDR_TO_VREG(addr), val, LOMBUS_CMD_WRITE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_vreg_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel size_t inc;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (; repcount--; dev_addr += inc)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *host_addr++ = lombus_vreg_get8(hdlp, dev_addr);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_vreg_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel size_t inc;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (; repcount--; dev_addr += inc)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_vreg_put8(hdlp, dev_addr, *host_addr++);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Space 1 - LOM watchdog pat register access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Only 8-bit accesses are supported.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Reads have no effect and return 0.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Writes pat the dog by toggling the RTS line iff enough time has
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * elapsed since last time we toggled it.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Multi-byte reads (using ddi_rep_get8(9F)) are a fairly inefficient
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * way of zeroing the destination area ;-) and still won't pat the dog.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Multi-byte writes (using ddi_rep_put8(9F)) will almost certainly
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * only count as a single pat, no matter how many bytes the caller
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * says to write, as the inter-pat time is VERY long compared with
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * the time it will take to read the memory source area.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint8_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_pat_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ptrdiff_t offset;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel offset = ADDR_TO_OFFSET(addr, hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DUMMY_VALUE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_pat_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ptrdiff_t offset;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hrtime_t now;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(val))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel offset = ADDR_TO_OFFSET(addr, hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp = HANDLE_PRIVATE(hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_enter(ssp->hw_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel now = gethrtime();
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((now - ssp->hw_last_pat) >= LOMBUS_MIN_PAT) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_toggle_rts(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->hw_last_pat = now;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_exit(ssp->hw_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_pat_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel size_t inc;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (; repcount--; dev_addr += inc)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *host_addr++ = lombus_pat_get8(hdlp, dev_addr);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_pat_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel size_t inc;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (; repcount--; dev_addr += inc)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_pat_put8(hdlp, dev_addr, *host_addr++);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Space 2 - LOM async event flag register access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Only 16-bit accesses are supported.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint16_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_event_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ptrdiff_t offset;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping orignally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel offset = ADDR_TO_OFFSET(addr, hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DUMMY_VALUE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Return the value of the asynchronous-event-pending flag
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * as passed back by the LOM at the end of the last command.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp = HANDLE_PRIVATE(hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (ssp->async);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_event_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ptrdiff_t offset;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(val))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel offset = ADDR_TO_OFFSET(addr, hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The user can't overwrite the asynchronous-event-pending flag!
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_RO;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_event_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint16_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel size_t inc;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (; repcount--; dev_addr += inc)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *host_addr++ = lombus_event_get16(hdlp, dev_addr);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_event_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint16_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel size_t inc;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (; repcount--; dev_addr += inc)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_event_put16(hdlp, dev_addr, *host_addr++);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * All spaces - access handle fault information
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Only 32-bit accesses are supported.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint32_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_meta_get32(HANDLE_TYPE *hdlp, uint32_t *addr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ptrdiff_t offset;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Derive the offset that the caller has added to the base
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * address originally returned, and use it to determine
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * which meta-register is to be accessed ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel offset = ADDR_TO_OFFSET(addr, hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (offset) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_FAULT_REG:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This meta-register provides a code for the most
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * recent virtual register access fault, if any.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (HANDLE_FAULT(hdlp));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_PROBE_REG:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Reading this meta-register clears any existing fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (at the virtual, not the hardware access layer), then
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * runs a NOP command and returns the fault code from that.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = 0;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) lombus_cmd(hdlp, 0, 0, LOMBUS_CMD_NOP);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (HANDLE_FAULT(hdlp));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_ASYNC_REG:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Obsolescent - but still supported for backwards
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * compatibility. This is an alias for the newer
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * LOMBUS_EVENT_REG, but doesn't require a separate
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * "reg" entry and ddi_regs_map_setup() call.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * It returns the value of the asynchronous-event-pending
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * flag as passed back by the LOM at the end of the last
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * completed command.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp = HANDLE_PRIVATE(hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (ssp->async);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DUMMY_VALUE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_meta_put32(HANDLE_TYPE *hdlp, uint32_t *addr, uint32_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ptrdiff_t offset;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Derive the offset that the caller has added to the base
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * address originally returned, and use it to determine
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * which meta-register is to be accessed ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel offset = ADDR_TO_OFFSET(addr, hdlp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (offset) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_FAULT_REG:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This meta-register contains a code for the most
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * recent virtual register access fault, if any.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * It can be cleared simply by writing 0 to it.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = val;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_PROBE_REG:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Writing this meta-register clears any existing fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (at the virtual, not the hardware acess layer), then
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * runs a NOP command. The caller can check the fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * code later if required.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = 0;
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) lombus_cmd(hdlp, 0, 0, LOMBUS_CMD_NOP);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_meta_rep_get32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint32_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel size_t inc;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (; repcount--; dev_addr += inc)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *host_addr++ = lombus_meta_get32(hdlp, dev_addr);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_meta_rep_put32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint32_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel size_t inc;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (; repcount--; dev_addr += inc)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_put32(hdlp, dev_addr, *host_addr++);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Finally, some dummy functions for all unsupported access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * space/size/mode combinations ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint8_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(addr))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DUMMY_VALUE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(addr, val))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint8_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint16_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(addr))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DUMMY_VALUE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(addr, val))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint16_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint16_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic uint64_t
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_get64(HANDLE_TYPE *hdlp, uint64_t *addr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(addr))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DUMMY_VALUE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_put64(HANDLE_TYPE *hdlp, uint64_t *addr, uint64_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(addr, val))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_get64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint64_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_put64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint64_t *dev_addr, size_t repcount, uint_t flags)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_acc_fault_check(HANDLE_TYPE *hdlp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (HANDLE_FAULT(hdlp) != 0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Hardware setup - put the SIO chip in the required operational
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * state, with all our favourite parameters programmed correctly.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This routine leaves all SIO interrupts disabled.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_hw_reset(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint16_t divisor;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Disable interrupts, soft reset Tx and Rx circuitry,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * reselect standard modes (bits/char, parity, etc).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_set_irq(ssp, B_FALSE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_FCR, SIO_FCR_RXSR | SIO_FCR_TXSR);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_LCR, SIO_LCR_STD);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Select the proper baud rate; if the value is invalid
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (presumably 0, i.e. not specified, but also if the
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * "baud" property is set to some silly value), we assume
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * the default.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->baud < SIO_BAUD_MIN || ssp->baud > SIO_BAUD_MAX)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel divisor = SIO_BAUD_TO_DIVISOR(SIO_BAUD_DEFAULT);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel else
3db86aab554edbb4244c8d1a1c90f152eee768afstevel divisor = SIO_BAUD_TO_DIVISOR(ssp->baud);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * According to the datasheet, it is forbidden for the divisor
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * register to be zero. So when loading the register in two
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * steps, we have to make sure that the temporary value formed
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * between loads is nonzero. However, we can't rely on either
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * half already having a nonzero value, as the datasheet also
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * says that these registers are indeterminate after a reset!
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * So, we explicitly set the low byte to a non-zero value first;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * then we can safely load the high byte, and then the correct
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * value for the low byte, without the result ever being zero.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_BSR, SIO_BSR_BANK1);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_LBGDL, 0xff);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_LBGDH, divisor >> 8);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_LBGDL, divisor & 0xff);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_BSR, SIO_BSR_BANK0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Program the remaining device registers as required
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_MCR, SIO_MCR_STD);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_FCR, SIO_FCR_STD);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Higher-level setup & teardown
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic void
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_offline(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->sio_handle != NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_regs_map_free(&ssp->sio_handle);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->sio_handle = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->sio_regs = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_online(struct lombus_state *ssp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_acc_handle_t h;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel caddr_t p;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int nregs;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int err;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_dev_nregs(ssp->dip, &nregs) != DDI_SUCCESS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nregs = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (nregs) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case 1:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * regset 0 represents the SIO operating registers
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err = ddi_regs_map_setup(ssp->dip, 0, &p, 0, 0,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_dev_acc_attr, &h);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'O', "online",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "regmap 0 status %d addr $%p", err, p);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (err != DDI_SUCCESS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (EIO);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->sio_handle = h;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->sio_regs = (void *)p;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case 0:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If no registers are defined, succeed vacuously;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * commands will be accepted, but we fake the accesses.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Now that the registers are mapped, we can initialise the SIO h/w
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_hw_reset(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Nexus routines
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#if defined(NDI_ACC_HDL_V2)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic const ndi_acc_fns_t lombus_vreg_acc_fns = {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel NDI_ACC_FNS_CURRENT,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel NDI_ACC_FNS_V1,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_vreg_get8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_vreg_put8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_vreg_rep_get8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_vreg_rep_put8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_get16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_put16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_get16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_put16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_get32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_put32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_rep_get32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_rep_put32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_get64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_put64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_get64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_put64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_acc_fault_check
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic const ndi_acc_fns_t lombus_pat_acc_fns = {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel NDI_ACC_FNS_CURRENT,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel NDI_ACC_FNS_V1,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_pat_get8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_pat_put8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_pat_rep_get8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_pat_rep_put8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_get16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_put16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_get16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_put16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_get32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_put32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_rep_get32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_rep_put32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_get64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_put64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_get64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_put64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_acc_fault_check
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic const ndi_acc_fns_t lombus_event_acc_fns = {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel NDI_ACC_FNS_CURRENT,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel NDI_ACC_FNS_V1,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_get8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_put8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_get8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_put8,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_event_get16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_event_put16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_event_rep_get16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_event_rep_put16,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_get32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_put32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_rep_get32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_meta_rep_put32,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_get64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_put64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_get64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_no_rep_put64,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_acc_fault_check
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_map_handle(struct lombus_state *ssp, ddi_map_op_t op,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int space, caddr_t vaddr, off_t len,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ndi_acc_handle_t *hdlp, caddr_t *addrp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (op) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_UNIMPLEMENTED);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_MO_MAP_LOCKED:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (space) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_REGSPEC_RANGE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_VREG_SPACE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ndi_set_acc_fns(hdlp, &lombus_vreg_acc_fns);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_PAT_SPACE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ndi_set_acc_fns(hdlp, &lombus_pat_acc_fns);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_EVENT_SPACE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ndi_set_acc_fns(hdlp, &lombus_event_acc_fns);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hdlp->ah_addr = *addrp = vaddr;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hdlp->ah_len = len;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hdlp->ah_bus_private = ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_MO_UNMAP:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *addrp = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hdlp->ah_bus_private = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#else
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_map_handle(struct lombus_state *ssp, ddi_map_op_t op,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int space, caddr_t vaddr, off_t len,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_acc_hdl_t *hdlp, caddr_t *addrp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_acc_impl_t *aip = hdlp->ah_platform_private;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (op) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_UNIMPLEMENTED);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_MO_MAP_LOCKED:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (space) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_REGSPEC_RANGE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_VREG_SPACE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get8 = lombus_vreg_get8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put8 = lombus_vreg_put8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get8 = lombus_vreg_rep_get8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put8 = lombus_vreg_rep_put8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get16 = lombus_no_get16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put16 = lombus_no_put16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get16 = lombus_no_rep_get16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put16 = lombus_no_rep_put16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get32 = lombus_meta_get32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put32 = lombus_meta_put32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get32 = lombus_meta_rep_get32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put32 = lombus_meta_rep_put32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get64 = lombus_no_get64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put64 = lombus_no_put64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get64 = lombus_no_rep_get64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put64 = lombus_no_rep_put64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_fault_check = lombus_acc_fault_check;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_PAT_SPACE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get8 = lombus_pat_get8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put8 = lombus_pat_put8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get8 = lombus_pat_rep_get8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put8 = lombus_pat_rep_put8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get16 = lombus_no_get16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put16 = lombus_no_put16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get16 = lombus_no_rep_get16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put16 = lombus_no_rep_put16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get32 = lombus_meta_get32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put32 = lombus_meta_put32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get32 = lombus_meta_rep_get32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put32 = lombus_meta_rep_put32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get64 = lombus_no_get64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put64 = lombus_no_put64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get64 = lombus_no_rep_get64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put64 = lombus_no_rep_put64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_fault_check = lombus_acc_fault_check;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_EVENT_SPACE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get8 = lombus_no_get8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put8 = lombus_no_put8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get8 = lombus_no_rep_get8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put8 = lombus_no_rep_put8;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get16 = lombus_event_get16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put16 = lombus_event_put16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get16 = lombus_event_rep_get16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put16 = lombus_event_rep_put16;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get32 = lombus_meta_get32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put32 = lombus_meta_put32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get32 = lombus_meta_rep_get32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put32 = lombus_meta_rep_put32;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_get64 = lombus_no_get64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_put64 = lombus_no_put64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_get64 = lombus_no_rep_get64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_rep_put64 = lombus_no_rep_put64;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel aip->ahi_fault_check = lombus_acc_fault_check;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hdlp->ah_addr = *addrp = vaddr;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hdlp->ah_len = len;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hdlp->ah_bus_private = ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_MO_UNMAP:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *addrp = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel hdlp->ah_bus_private = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#endif /* NDI_ACC_HDL_V2 */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel off_t off, off_t len, caddr_t *addrp)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_child_info *lcip;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_regspec_t *rsp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, -1, "lombus_map")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE); /* this "can't happen" */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Validate mapping request ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (mp->map_flags != DDI_MF_KERNEL_MAPPING)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_UNSUPPORTED);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (mp->map_handlep == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_UNSUPPORTED);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (mp->map_type != DDI_MT_RNUMBER)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_UNIMPLEMENTED);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((lcip = ddi_get_parent_data(rdip)) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_INVAL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((rsp = lcip->rsp) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_INVAL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (mp->map_obj.rnumber >= lcip->nregs)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_RNUMBER_RANGE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel rsp += mp->map_obj.rnumber;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (off < 0 || off >= rsp->lombus_size)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_INVAL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (len == 0)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel len = rsp->lombus_size-off;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (len < 0)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_INVAL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (off+len < 0 || off+len > rsp->lombus_size)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_ME_INVAL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (lombus_map_handle(ssp, mp->map_op,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota rsp->lombus_space, VREG_TO_ADDR(rsp->lombus_base+off), len,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota mp->map_handlep, addrp));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel void *arg, void *result)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_child_info *lcip;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_regspec_t *rsp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel dev_info_t *cdip;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel char addr[32];
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint_t nregs;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel uint_t rnum;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int *regs;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int limit;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int err;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int i;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, -1, "lombus_ctlops")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE); /* this "can't happen" */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (op) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_CTLOPS_INITCHILD:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * First, look up and validate the "reg" property.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * It must be a non-empty integer array containing a set
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * of triples. Once we've verified that, we can treat it
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * as an array of type lombus_regspec_t[], which defines
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * the meaning of the elements of each triple:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * + the first element of each triple must be a valid space
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * + the second and third elements (base, size) of each
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * triple must define a valid subrange of that space
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If it passes all the tests, we save it away for future
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * reference in the child's parent-private-data field.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cdip = arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_PROP_DONTPASS, "reg", &regs, &nregs);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'C', "initchild",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "prop status %d size %d", err, nregs);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (err != DDI_PROP_SUCCESS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err = (nregs <= 0 || (nregs % LOMBUS_REGSPEC_SIZE) != 0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nregs /= LOMBUS_REGSPEC_SIZE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel rsp = (lombus_regspec_t *)regs;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel for (i = 0; i < nregs && !err; ++i) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (rsp[i].lombus_space) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel limit = 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err = 1;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_VREG_SPACE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel limit = LOMBUS_MAX_REG+1;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_PAT_SPACE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel limit = LOMBUS_PAT_REG+1;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case LOMBUS_EVENT_SPACE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel limit = LOMBUS_EVENT_REG+1;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err |= (rsp[i].lombus_base < 0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err |= (rsp[i].lombus_base >= limit);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (rsp[i].lombus_size == 0)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel rsp[i].lombus_size = limit-rsp[i].lombus_base;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err |= (rsp[i].lombus_size < 0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err |= (rsp[i].lombus_base+rsp[i].lombus_size < 0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (err) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_prop_free(regs);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lcip = kmem_zalloc(sizeof (*lcip), KM_SLEEP);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lcip->nregs = nregs;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lcip->rsp = rsp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_set_parent_data(cdip, lcip);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) snprintf(addr, sizeof (addr),
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "%x,%x", rsp[0].lombus_space, rsp[0].lombus_base);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_set_name_addr(cdip, addr);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_CTLOPS_UNINITCHILD:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cdip = arg;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_set_name_addr(cdip, NULL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lcip = ddi_get_parent_data(cdip);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_set_parent_data(cdip, NULL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_prop_free(lcip->rsp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel kmem_free(lcip, sizeof (*lcip));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_CTLOPS_REPORTDEV:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (rdip == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cmn_err(CE_CONT, "?LOM device: %s@%s, %s#%d\n",
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ddi_node_name(rdip), ddi_get_name_addr(rdip),
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ddi_driver_name(dip), ddi_get_instance(dip));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_CTLOPS_REGSIZE:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((lcip = ddi_get_parent_data(rdip)) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((rnum = *(uint_t *)arg) >= lcip->nregs)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *(off_t *)result = lcip->rsp[rnum].lombus_size;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_CTLOPS_NREGS:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((lcip = ddi_get_parent_data(rdip)) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel *(int *)result = lcip->nregs;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (ddi_ctlops(dip, rdip, op, arg, result));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Clean up on detach or failure of attach
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_unattach(struct lombus_state *ssp, int instance)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp != NULL) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_hw_reset(ssp);
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota if (ssp->cycid != NULL) {
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ddi_periodic_delete(ssp->cycid);
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->cycid = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->sio_handle != NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_remove_intr(ssp->dip, 0, ssp->hw_iblk);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_remove_softintr(ssp->softid);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cv_destroy(ssp->lo_cv);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_destroy(ssp->lo_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_destroy(ssp->hw_mutex);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_offline(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_set_driver_private(ssp->dip, NULL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_soft_state_free(lombus_statep, instance);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Autoconfiguration routines
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int instance;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int err;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (cmd) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_ATTACH:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Allocate the soft-state structure
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel instance = ddi_get_instance(dip);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_soft_state_zalloc(lombus_statep, instance) != DDI_SUCCESS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, instance, "lombus_attach")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (lombus_unattach(ssp, instance));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_set_driver_private(dip, ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Initialise devinfo-related fields
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->dip = dip;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->majornum = ddi_driver_major(dip);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->instance = instance;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Set various options from .conf properties
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->allow_echo = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_PROP_DONTPASS, "allow-lom-echo", 0) != 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->baud = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_PROP_DONTPASS, "baud-rate", 0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_PROP_DONTPASS, "debug", 0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->fake_cts = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_PROP_DONTPASS, "fake-cts", 0) != 0;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Initialise current state & time
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->cmdstate = LOMBUS_CMDSTATE_IDLE;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->hw_last_pat = gethrtime();
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->cycid = NULL;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Online the hardware ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err = lombus_online(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (err != 0)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (lombus_unattach(ssp, instance));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Install soft and hard interrupt handler(s)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Initialise mutexes and cv
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Start cyclic callbacks
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Enable interrupts
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err = ddi_add_softintr(dip, DDI_SOFTINT_LOW, &ssp->softid,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota &ssp->lo_iblk, NULL, lombus_softint, (caddr_t)ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (err != DDI_SUCCESS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (lombus_unattach(ssp, instance));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ssp->sio_handle != NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err = ddi_add_intr(dip, 0, &ssp->hw_iblk, NULL,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota lombus_hi_intr, (caddr_t)ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_init(ssp->hw_mutex, NULL, MUTEX_DRIVER, ssp->hw_iblk);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_init(ssp->lo_mutex, NULL, MUTEX_DRIVER, ssp->lo_iblk);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel cv_init(ssp->lo_cv, NULL, CV_DRIVER, NULL);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota /*
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota * Register a periodical handler.
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota */
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->cycid = ddi_periodic_add(lombus_cyclic, ssp, LOMBUS_ONE_SEC,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota DDI_IPL_1);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Final check before enabling h/w interrupts - did
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we successfully install the h/w interrupt handler?
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (err != DDI_SUCCESS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (lombus_unattach(ssp, instance));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_set_irq(ssp, B_TRUE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * All done, report success
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_report_dev(dip);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int instance;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (cmd) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel default:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel case DDI_DETACH:
3db86aab554edbb4244c8d1a1c90f152eee768afstevel break;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel instance = ddi_get_instance(dip);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, instance, "lombus_detach")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE); /* this "can't happen" */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) lombus_unattach(ssp, instance);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic int
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel struct lombus_state *ssp;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(cmd))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, -1, "lombus_reset")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_FAILURE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_hw_reset(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (DDI_SUCCESS);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * System interface structures
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic struct cb_ops lombus_cb_ops =
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* b/c open */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* b/c close */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* b strategy */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* b print */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* b dump */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* c read */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* c write */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* c ioctl */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* c devmap */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* c mmap */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nodev, /* c segmap */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nochpoll, /* c poll */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_prop_op, /* b/c prop_op */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel NULL, /* c streamtab */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel D_MP | D_NEW /* b/c flags */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic struct bus_ops lombus_bus_ops =
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel BUSO_REV, /* revision */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_map, /* bus_map */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* get_intrspec */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* add_intrspec */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* remove_intrspec */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel i_ddi_map_fault, /* map_fault */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_no_dma_map, /* dma_map */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_no_dma_allochdl, /* allocate DMA handle */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_no_dma_freehdl, /* free DMA handle */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_no_dma_bindhdl, /* bind DMA handle */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_no_dma_unbindhdl, /* unbind DMA handle */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_no_dma_flush, /* flush DMA */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_no_dma_win, /* move DMA window */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_no_dma_mctl, /* generic DMA control */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_ctlops, /* generic control */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_bus_prop_op, /* prop_op */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ndi_busop_get_eventcookie, /* get_eventcookie */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ndi_busop_add_eventcall, /* add_eventcall */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ndi_busop_remove_eventcall, /* remove_eventcall */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ndi_post_event, /* post_event */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* interrupt control */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* bus_config */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* bus_unconfig */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* bus_fm_init */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* bus_fm_fini */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* bus_fm_access_enter */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* bus_fm_access_exit */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* bus_power */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel i_ddi_intr_ops /* bus_intr_op */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic struct dev_ops lombus_dev_ops =
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel DEVO_REV,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* refcount */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_no_info, /* getinfo */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nulldev, /* identify */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel nulldev, /* probe */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_attach, /* attach */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_detach, /* detach */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_reset, /* reset */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel &lombus_cb_ops, /* driver operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore &lombus_bus_ops, /* bus operations */
193974072f41a843678abf5f61979c748687e66bSherry Moore NULL, /* power */
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_supported, /* devo_quiesce */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic struct modldrv modldrv =
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel &mod_driverops,
193974072f41a843678abf5f61979c748687e66bSherry Moore "lombus driver",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel &lombus_dev_ops
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic struct modlinkage modlinkage =
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel MODREV_1,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel &modldrv,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel NULL
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel};
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel/*
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Dynamic loader interface code
3db86aab554edbb4244c8d1a1c90f152eee768afstevel */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelint
3db86aab554edbb4244c8d1a1c90f152eee768afstevel_init(void)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int err;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err = ddi_soft_state_init(&lombus_statep,
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota sizeof (struct lombus_state), 0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (err == DDI_SUCCESS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((err = mod_install(&modlinkage)) != 0) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_soft_state_fini(&lombus_statep);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (err);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelint
3db86aab554edbb4244c8d1a1c90f152eee768afstevel_info(struct modinfo *mip)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (mod_info(&modlinkage, mip));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevelint
3db86aab554edbb4244c8d1a1c90f152eee768afstevel_fini(void)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel{
3db86aab554edbb4244c8d1a1c90f152eee768afstevel int err;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((err = mod_remove(&modlinkage)) == 0) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_soft_state_fini(&lombus_statep);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_major = NOMAJOR;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel }
3db86aab554edbb4244c8d1a1c90f152eee768afstevel
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (err);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel}