3db86aab554edbb4244c8d1a1c90f152eee768afstevel * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * See the License for the specific language governing permissions
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * and limitations under the License.
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 * CDDL HEADER END
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Use is subject to license terms.
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 * On the other hand, this driver doesn't generally know what the virtual
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * registers signify - only the clients need this information.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Header files
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Compiling for Solaris 9+ with access handle enhancements
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Compatibility definitions for backport to Solaris 8
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define HANDLE_PRIVATE(hdlp) (hdlp->ahi_common.ah_bus_private)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define ddi_driver_major(dip) ddi_name_to_major(ddi_binding_name(dip))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#endif /* NDI_ACC_HDL_V2 */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Local definitions
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 * The following definitions are taken from the datasheet
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * for the National Semiconductor PC87317 (SuperIO) chip.
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 * Hardware: serial chip register numbers
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Hardware: serial chip register bits
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 * Packet format ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_PARAM 0x00 /* Parameter byte: 0b0xxxxxxx */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CMD 0x80 /* Command byte: 0b10###XWV */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_STATUS 0xc0 /* Status byte: 0b11###AEV */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#define LOMBUS_CMD_XADDR 0x04 /* Extended (2-byte) addressing */
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 * Time periods, in nanoseconds
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Note that LOMBUS_ONE_SEC and some other time
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * periods are defined in <sys/lombus.h>
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Local datatypes
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This driver's soft-state structure
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Configuration data, set during attach
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Parameters derived from .conf properties
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 * 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 * 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 * Serial protocol state data, protected by lo_mutex
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (which is initialised using <lo_iblk>)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The auxiliary structure attached to each child
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (the child's parent-private-data points to this).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Local data
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * General utility routines ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_trace(struct lombus_state *ssp, char code, const char *caller,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel const char *fmt, ...)
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) vsnprintf(p, sizeof (buf) - (p - buf), fmt, va);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) strlog(ssp->majornum, ssp->instance, code, SL_TRACE,
3db86aab554edbb4244c8d1a1c90f152eee768afstevelstatic struct lombus_state *
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_getstate(dev_info_t *dip, int instance, const char *caller)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Use the instance number from the <dip>; also,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * check that it really corresponds to this driver
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "%s: major number mismatch (%d vs. %d) in %s(),"
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "probably due to child misconfiguration",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel else if (dip != NULL && sdip != NULL && sdip != dip) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "%s: devinfo mismatch (%p vs. %p) in %s(), "
3db86aab554edbb4244c8d1a1c90f152eee768afstevel "probably due to child misconfiguration",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Lowest-level serial I/O chip register read/write
3db86aab554edbb4244c8d1a1c90f152eee768afstevelsio_put_reg(struct lombus_state *ssp, uint_t reg, uint8_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'P', "sio_put_reg", "REG[%d] <- $%02x", reg, val);
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 * 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 * 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 * This will no longer be needed once "synchronous" access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * handles are available (see PSARC/2000/269 and 2000/531).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ddi_put8(ssp->sio_handle, ssp->sio_regs + SIO_SCR, val);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) ddi_get8(ssp->sio_handle, ssp->sio_regs + SIO_SCR);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel val = ddi_get8(ssp->sio_handle, ssp->sio_regs + reg);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'G', "sio_get_reg", "$%02x <- REG[%d]", val, reg);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->sio_fault = ddi_check_acc_handle(ssp->sio_handle) != DDI_SUCCESS;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check for data ready.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Data is available if the RXDA bit in the LSR is nonzero
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * (if reading it didn't incur a fault).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return ((status & SIO_LSR_RXDA) != 0 && !sio_faulty(ssp));
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check for LOM ready
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 * For debugging, we force the result to TRUE if the FAKE flag is set
3db86aab554edbb4244c8d1a1c90f152eee768afstevel rslt = (status & SIO_MSR_CTS) != 0 && !sio_faulty(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'R', "sio_lom_ready", "S $%02x R %d F %d",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check for interrupt pending
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 * 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 rslt = (status & SIO_EIR_IPF) == 0 && !sio_faulty(ssp);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel lombus_trace(ssp, 'I', "sio_irq_pending", "S $%02x R %d",
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#endif /* 0 */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Enable/disable interrupts
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_set_irq(struct lombus_state *ssp, boolean_t newstate)
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 * 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 * 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 * Packet receive handler
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.
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "state %d; error $%x",
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 * 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)
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "rcvd %d: $%02x $%02x $%02x $%02x $%02x $%02x $%02x $%02x",
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 } else if (rcvd == 0) {
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 * 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 * Packet not yet complete; leave the partial packet in
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * the buffer for later ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid "status" byte - maybe an echo of the command?
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 * Otherwise, we just drop the data & flag an error.
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "echo $%02x $%02x $%02x $%02x "
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "$%02x $%02x $%02x $%02x",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Wrong sequence number! Flag this as an error
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 * 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 tmp = ((data & LOMBUS_STATUS_MSB) ? 0x80 : 0) | ssp->reply[0];
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota "rcvd %d; last $%02x; state %d; error $%x; ready %d",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Low-level softint handler
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This routine should be triggered whenever there's a byte to be read
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Cyclic handler: just calls the receive routine, in case interrupts
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * are not being delivered and in order to handle command timeout
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Serial protocol
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * This routine builds a command and sets it in progress.
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_cmd(HANDLE_TYPE *hdlp, ptrdiff_t vreg, uint_t val, uint_t cmd)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * First of all, wait for the interface to be available.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * NOTE: we blow through all the mutex/cv/state checking and
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * preempt any command in progress if the system is panicking!
3db86aab554edbb4244c8d1a1c90f152eee768afstevel while (ssp->cmdstate != LOMBUS_CMDSTATE_IDLE && !panicstr)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->sequence = (ssp->sequence + LOMBUS_SEQ_LSB) & LOMBUS_SEQ;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * We have exclusive ownership, so assemble the command (backwards):
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 /*FALLTHRU*/
3db86aab554edbb4244c8d1a1c90f152eee768afstevel /*FALLTHRU*/
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 * 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 ssp->deadline = start + drv_usectohz(LOMBUS_CTS_TIMEOUT/1000);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) cv_reltimedwait(ssp->lo_cv, ssp->lo_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_usectohz(LOMBUS_CTS_POLL/1000), TR_CLOCK_TICK);
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 * 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 ssp->deadline = start + drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (cv_reltimedwait(ssp->lo_cv, ssp->lo_mutex,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni drv_usectohz(LOMBUS_CMD_POLL/1000), TR_CLOCK_TICK) == -1)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The return value may not be meaningful but retrieve it anyway
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 * All done now!
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Space 0 - LOM virtual register access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Only 8-bit accesses are supported.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Derive the virtual register number and run the command
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (lombus_cmd(hdlp, ADDR_TO_VREG(addr), 0, LOMBUS_CMD_READ));
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_vreg_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Derive the virtual register number and run the command
3db86aab554edbb4244c8d1a1c90f152eee768afstevel (void) lombus_cmd(hdlp, ADDR_TO_VREG(addr), val, LOMBUS_CMD_WRITE);
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_vreg_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_vreg_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Space 1 - LOM watchdog pat register access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Only 8-bit accesses are supported.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Reads have no effect and return 0.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Writes pat the dog by toggling the RTS line iff enough time has
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * elapsed since last time we toggled it.
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 * 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 * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_pat_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_pat_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_pat_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Space 2 - LOM async event flag register access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Only 16-bit accesses are supported.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping orignally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Return the value of the asynchronous-event-pending flag
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * as passed back by the LOM at the end of the last command.
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_event_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Check the offset that the caller has added to the base address
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * against the length of the mapping originally requested.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * The user can't overwrite the asynchronous-event-pending flag!
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_event_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_event_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * All spaces - access handle fault information
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Only 32-bit accesses are supported.
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 * This meta-register provides a code for the most
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * recent virtual register access fault, if any.
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 * 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 * 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 * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_meta_put32(HANDLE_TYPE *hdlp, uint32_t *addr, uint32_t val)
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 * 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 * 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 * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_meta_rep_get32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_meta_rep_put32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Finally, some dummy functions for all unsupported access
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * space/size/mode combinations ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault and return a dummy value
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_put64(HANDLE_TYPE *hdlp, uint64_t *addr, uint64_t val)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_get64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_no_rep_put64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Invalid access - flag a fault
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 * Disable interrupts, soft reset Tx and Rx circuitry,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * reselect standard modes (bits/char, parity, etc).
3db86aab554edbb4244c8d1a1c90f152eee768afstevel sio_put_reg(ssp, SIO_FCR, SIO_FCR_RXSR | SIO_FCR_TXSR);
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 if (ssp->baud < SIO_BAUD_MIN || ssp->baud > SIO_BAUD_MAX)
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 * Program the remaining device registers as required
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Higher-level setup & teardown
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * regset 0 represents the SIO operating registers
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * If no registers are defined, succeed vacuously;
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * commands will be accepted, but we fake the accesses.
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Now that the registers are mapped, we can initialise the SIO h/w
3db86aab554edbb4244c8d1a1c90f152eee768afstevel return (0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Nexus routines
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_map_handle(struct lombus_state *ssp, ddi_map_op_t op,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (op) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_map_handle(struct lombus_state *ssp, ddi_map_op_t op,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (op) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel#endif /* NDI_ACC_HDL_V2 */
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, -1, "lombus_map")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Validate mapping request ...
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota rsp->lombus_space, VREG_TO_ADDR(rsp->lombus_base+off), len,
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, -1, "lombus_ctlops")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel switch (op) {
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * First, look up and validate the "reg" property.
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 err = (nregs <= 0 || (nregs % LOMBUS_REGSPEC_SIZE) != 0);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Clean up on detach or failure of attach
3db86aab554edbb4244c8d1a1c90f152eee768afstevellombus_unattach(struct lombus_state *ssp, int instance)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Autoconfiguration routines
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Allocate the soft-state structure
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if (ddi_soft_state_zalloc(lombus_statep, instance) != DDI_SUCCESS)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, instance, "lombus_attach")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Initialise devinfo-related fields
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Set various options from .conf properties
3db86aab554edbb4244c8d1a1c90f152eee768afstevel ssp->allow_echo = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Initialise current state & time
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Online the hardware ...
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Install soft and hard interrupt handler(s)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Initialise mutexes and cv
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Start cyclic callbacks
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Enable interrupts
3db86aab554edbb4244c8d1a1c90f152eee768afstevel err = ddi_add_softintr(dip, DDI_SOFTINT_LOW, &ssp->softid,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_init(ssp->hw_mutex, NULL, MUTEX_DRIVER, ssp->hw_iblk);
3db86aab554edbb4244c8d1a1c90f152eee768afstevel mutex_init(ssp->lo_mutex, NULL, MUTEX_DRIVER, ssp->lo_iblk);
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota * Register a periodical handler.
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota ssp->cycid = ddi_periodic_add(lombus_cyclic, ssp, LOMBUS_ONE_SEC,
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Final check before enabling h/w interrupts - did
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * we successfully install the h/w interrupt handler?
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * All done, report success
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, instance, "lombus_detach")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel if ((ssp = lombus_getstate(dip, -1, "lombus_reset")) == NULL)
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * System interface structures
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* get_intrspec */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* add_intrspec */
3db86aab554edbb4244c8d1a1c90f152eee768afstevel 0, /* remove_intrspec */
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 0, /* refcount */
193974072f41a843678abf5f61979c748687e66bSherry Moore "lombus driver",
3db86aab554edbb4244c8d1a1c90f152eee768afstevel * Dynamic loader interface code
dd4eeefdb8e4583c47e28a7f315db6087931ef06eota sizeof (struct lombus_state), 0);