1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  *
  25  * Copyright 2019 Joyent, Inc.
  26  *
  27  * The "bscbus" driver provides access to the LOMlite2 virtual registers,
  28  * so that its clients (children) need not be concerned with the details
  29  * of the access mechanism, which in this case is implemented via a
  30  * packet-based protocol over a Xbus (similar to ebus) parallel link to the
  31  * H8 host interface registers.
  32  *
  33  * On the other hand, this driver doesn't generally know what the virtual
  34  * registers signify - only the clients need this information.
  35  */
  36 
  37 
  38 #include <sys/note.h>
  39 #include <sys/types.h>
  40 #include <sys/conf.h>
  41 #include <sys/debug.h>
  42 #include <sys/errno.h>
  43 #include <sys/file.h>
  44 
  45 #if defined(__sparc)
  46 #include <sys/intr.h>
  47 #include <sys/membar.h>
  48 #endif
  49 
  50 #include <sys/kmem.h>
  51 #include <sys/modctl.h>
  52 #include <sys/note.h>
  53 #include <sys/open.h>
  54 #include <sys/poll.h>
  55 #include <sys/spl.h>
  56 #include <sys/stat.h>
  57 #include <sys/strlog.h>
  58 #include <sys/atomic.h>
  59 
  60 #include <sys/ddi.h>
  61 #include <sys/sunddi.h>
  62 #include <sys/sunndi.h>
  63 
  64 #include <sys/bscbus.h>
  65 
  66 #if     defined(NDI_ACC_HDL_V2)
  67 
  68 /*
  69  * Compiling for Solaris 10+ with access handle enhancements
  70  */
  71 #define HANDLE_TYPE             ndi_acc_handle_t
  72 #define HANDLE_ADDR(hdlp)       (hdlp->ah_addr)
  73 #define HANDLE_FAULT(hdlp)      (hdlp->ah_fault)
  74 #define HANDLE_MAPLEN(hdlp)     (hdlp->ah_len)
  75 #define HANDLE_PRIVATE(hdlp)    (hdlp->ah_bus_private)
  76 
  77 #else
  78 
  79 /*
  80  * Compatibility definitions for backport to Solaris 8/9
  81  */
  82 #define HANDLE_TYPE             ddi_acc_impl_t
  83 #define HANDLE_ADDR(hdlp)       (hdlp->ahi_common.ah_addr)
  84 #define HANDLE_FAULT(hdlp)      (hdlp->ahi_fault)
  85 #define HANDLE_MAPLEN(hdlp)     (hdlp->ahi_common.ah_len)
  86 #define HANDLE_PRIVATE(hdlp)    (hdlp->ahi_common.ah_bus_private)
  87 
  88 #define ddi_driver_major(dip)   ddi_name_to_major(ddi_binding_name(dip))
  89 
  90 #endif  /* NDI_ACC_HDL_V2 */
  91 
  92 
  93 /*
  94  * Local definitions
  95  */
  96 #define MYNAME                  "bscbus"
  97 #define NOMAJOR                 (~(major_t)0)
  98 #define DUMMY_VALUE             (~(int8_t)0)
  99 
 100 #define BSCBUS_INST_TO_MINOR(i) (i)
 101 #define BSCBUS_MINOR_TO_INST(m) (m)
 102 
 103 #define BSCBUS_MAX_CHANNELS     (4)
 104 
 105 #define BSCBUS_DUMMY_ADDRESS    ((caddr_t)0x0CADD1ED)
 106 #define ADDR_TO_OFFSET(a, hdlp) ((caddr_t)(a) - HANDLE_ADDR(hdlp))
 107 #define ADDR_TO_VREG(a)         ((caddr_t)(a) - BSCBUS_DUMMY_ADDRESS)
 108 #define VREG_TO_ADDR(v)         (BSCBUS_DUMMY_ADDRESS + (v))
 109 
 110 #ifdef DEBUG
 111 #define BSCBUS_LOGSTATUS
 112 #endif /* DEBUG */
 113 
 114 #ifdef BSCBUS_LOGSTATUS
 115 /*
 116  * BSC command logging routines.
 117  * Record the data passing to and from the BSC
 118  */
 119 
 120 typedef enum {
 121         BSC_CMD_BUSY = 1,               /* bsc reports busy     */
 122         BSC_CMD_CLEARING = 2,           /* clearing bsc busy    */
 123         BSC_CMD_CLEARED = 3,            /* cleared bsc busy     */
 124         BSC_CMD_SENDING = 4,            /* sending next byte    */
 125         BSC_CMD_SENT = 5,               /* sending last byte    */
 126         BSC_CMD_PENDING = 6,            /* got sent byte ack    */
 127         BSC_CMD_REPLY = 7,              /* got reply byte       */
 128         BSC_CMD_COMPLETE = 8,           /* command complete     */
 129         BSC_CMD_ERROR_SEQ = 9,          /* error status         */
 130         BSC_CMD_ERROR_STATUS = 10,      /* error status         */
 131         BSC_CMD_ERROR_OFLOW = 11,       /* error status         */
 132         BSC_CMD_ERROR_TOUT = 12,        /* error status         */
 133 
 134         BSC_CMD_PROCESS = 13,           /* async intr           */
 135         BSC_CMD_V1INTR = 14,            /* v1 intr              */
 136         BSC_CMD_V1INTRUNCL = 15,        /* v1 intr unclaim      */
 137         BSC_CMD_DOGPAT = 17             /* watchdog pat         */
 138 } bsc_cmd_stamp_t;
 139 
 140 typedef struct {
 141         hrtime_t        bcl_now;
 142         int             bcl_seq;
 143         bsc_cmd_stamp_t bcl_cat;
 144         uint8_t         bcl_chno;
 145         uint8_t         bcl_cmdstate;
 146         uint8_t         bcl_status;
 147         uint8_t         bcl_data;
 148 } bsc_cmd_log_t;
 149 
 150 uint32_t        bscbus_cmd_log_size = 1024;
 151 
 152 uint32_t        bscbus_cmd_log_flags = 0xffffffff;
 153 
 154 #endif /* BSCBUS_LOGSTATUS */
 155 
 156 /*
 157  * The following definitions are taken from the Hardware Manual for
 158  * the Hitachi H8S/2148 in conjunction with the hardware specification
 159  * for the Stiletto blade.
 160  *
 161  * Each instance of the host interface has 3 registers on the H8:
 162  * IDRn  - Input Data Register  - write-only for Solaris.
 163  *                                writes to this can be done via two
 164  *                                addresses - control and data.
 165  *                                The H8 can determine which address was
 166  *                                written by examining the C/D bit in
 167  *                                the status register.
 168  * ODRn  - Output Data Register - read-only for Solaris.
 169  *                                A read has the side effect of acknowledging
 170  *                                interrupts.
 171  * STRn  - Status Register      - read-only for Solaris.
 172  *
 173  *
 174  *
 175  * In terms of host access to this the Input and Output data registers are
 176  * mapped at the same address.
 177  */
 178 #define H8_IDRD 0
 179 #define H8_IDRC 1
 180 #define H8_ODR  0
 181 #define H8_STR  1
 182 
 183 #define H8_STR_OBF              0x01    /* data available in ODR */
 184 #define H8_STR_IBF              0x02    /* data for H8 in IDR */
 185 #define H8_STR_IDRC             0x08    /* last write to IDR was to IDRC */
 186                                         /* 0=data, 1=command */
 187 #define H8_STR_BUSY             0x04    /* H8 busy processing command */
 188 #define H8_STR_TOKENPROTOCOL    0x80    /* token-passing protocol */
 189 
 190 /*
 191  * Packet format ...
 192  */
 193 #define BSCBUS_MASK             0xc0    /* Byte-type bits               */
 194 #define BSCBUS_PARAM            0x00    /* Parameter byte: 0b0xxxxxxx   */
 195 #define BSCBUS_LAST             0x80    /* Last byte of packet          */
 196 #define BSCBUS_CMD              0x80    /* Command byte:   0b10###XWV   */
 197 #define BSCBUS_STATUS           0xc0    /* Status  byte:   0b11###AEV   */
 198 
 199 #define BSCBUS_SEQ              0x38    /* Sequence number bits         */
 200 #define BSCBUS_SEQ_LSB          0x08    /* Sequence number LSB          */
 201 #define BSCBUS_CMD_XADDR        0x04    /* Extended (2-byte) addressing */
 202 #define BSCBUS_CMD_WRITE        0x02    /* Write command                */
 203 #define BSCBUS_CMD_WMSB         0x01    /* Set MSB on Write             */
 204 #define BSCBUS_CMD_READ         0x01    /* Read command                 */
 205 #define BSCBUS_CMD_NOP          0x00    /* NOP command                  */
 206 
 207 #define BSCBUS_STATUS_ASYNC     0x04    /* Asynchronous event pending   */
 208 #define BSCBUS_STATUS_ERR       0x02    /* Error in command processing  */
 209 #define BSCBUS_STATUS_MSB       0x01    /* MSB of Value read            */
 210 
 211 #define BSCBUS_VREG_LO(x)       ((x) & ((1 << 7) - 1))
 212 #define BSCBUS_VREG_HI(x)       ((x) >> 7)
 213 
 214 #define BSCBUS_BUFSIZE          8
 215 
 216 #define BSCBUS_CHANNEL_TO_OFFSET(chno)  ((chno) * 2)    /* Register offset */
 217 
 218 /*
 219  * Time periods, in nanoseconds
 220  *
 221  * Note that LOMBUS_ONE_SEC and some other time
 222  * periods are defined in <sys/lombus.h>
 223  */
 224 #define BSCBUS_CMD_POLL                 (LOMBUS_ONE_SEC)
 225 #define BSCBUS_CMD_POLLNOINTS           (LOMBUS_ONE_SEC/20)
 226 #define BSCBUS_HWRESET_POLL             (LOMBUS_ONE_SEC/20)
 227 #define BSCBUS_HWRESET_TIMEOUT          (LOMBUS_ONE_SEC*2)
 228 
 229 #define BSCBUS_DOG_PAT_POLL_LIMIT       (1000)
 230 #define BSCBUS_DOG_PAT_POLL             (1)
 231 #define BSCBUS_PAT_RETRY_LIMIT  5
 232 
 233 /*
 234  * Local datatypes
 235  */
 236 enum bscbus_cmdstate {
 237         BSCBUS_CMDSTATE_IDLE,           /* No transaction in progress */
 238         BSCBUS_CMDSTATE_BUSY,           /* Setting up command */
 239         BSCBUS_CMDSTATE_CLEARING,       /* Clearing firmware busy status */
 240         BSCBUS_CMDSTATE_SENDING,        /* Waiting to send data to f/w */
 241         BSCBUS_CMDSTATE_PENDING,        /* Waiting for ack from f/w */
 242         BSCBUS_CMDSTATE_WAITING,        /* Waiting for status from f/w */
 243         BSCBUS_CMDSTATE_READY,          /* Status received/command done */
 244         BSCBUS_CMDSTATE_ERROR           /* Command failed with error */
 245 };
 246 
 247 struct bscbus_channel_state {
 248         /* Changes to these are protected by the instance ch_mutex mutex */
 249         struct bscbus_state     *ssp;
 250         uint8_t                 *ch_regs;
 251         ddi_acc_handle_t        ch_handle;  /* per channel access handle */
 252         unsigned int            chno;
 253         unsigned int            map_count; /* Number of mappings to channel */
 254         boolean_t               map_dog;   /* channel is mapped for watchdog */
 255 
 256         /*
 257          * Flag to indicate that we've incurred a hardware fault on
 258          * accesses to the H8; once this is set, we fake all further
 259          * accesses in order not to provoke additional bus errors.
 260          */
 261         boolean_t               xio_fault;
 262 
 263         /*
 264          * Data protected by the dog_mutex: the watchdog-patting
 265          * protocol data (since the dog can be patted from a high-level
 266          * cyclic), and the interrupt-enabled flag.
 267          */
 268         kmutex_t                dog_mutex[1];
 269         unsigned int            pat_retry_count;
 270         unsigned int            pat_fail_count;
 271 
 272         /*
 273          * Serial protocol state data, protected by lo_mutex
 274          * (which is initialised using <lo_iblk>)
 275          */
 276         kmutex_t                lo_mutex[1];
 277         ddi_iblock_cookie_t     lo_iblk;
 278         kcondvar_t              lo_cv[1];
 279         int                     unclaimed_count;
 280 
 281         volatile enum bscbus_cmdstate cmdstate;
 282         clock_t                 deadline;
 283         clock_t                 poll_hz;
 284         boolean_t               interrupt_failed;
 285         uint8_t                 cmdbuf[BSCBUS_BUFSIZE];
 286         uint8_t                 *cmdp;  /* Points to last tx'd in cmdbuf */
 287         uint8_t                 reply[BSCBUS_BUFSIZE];
 288         uint8_t                 async;
 289         uint8_t                 index;
 290         uint8_t                 result;
 291         uint8_t                 sequence;
 292         uint32_t                error;
 293 };
 294 
 295 #define BSCBUS_TX_PENDING(csp)          ((csp)->cmdp > (csp)->cmdbuf)
 296 
 297 /*
 298  * This driver's soft-state structure
 299  */
 300 
 301 struct bscbus_state {
 302         /*
 303          * Configuration data, set during attach
 304          */
 305         dev_info_t              *dip;
 306         major_t                 majornum;
 307         int                     instance;
 308 
 309         ddi_acc_handle_t        h8_handle;
 310         uint8_t                 *h8_regs;
 311 
 312         /*
 313          * Parameters derived from .conf properties
 314          */
 315         uint32_t                debug;
 316 
 317         /*
 318          * Flag to indicate that we are using per channel
 319          * mapping of the register sets and interrupts.
 320          * reg set 0 is chan 0
 321          * reg set 1 is chan 1 ...
 322          *
 323          * Interrupts are specified in that order but later
 324          * channels may not have interrupts.
 325          */
 326         boolean_t               per_channel_regs;
 327 
 328         /*
 329          * channel state data, protected by ch_mutex
 330          * channel claim/release requests are protected by this mutex.
 331          */
 332         kmutex_t                ch_mutex[1];
 333         struct bscbus_channel_state     channel[BSCBUS_MAX_CHANNELS];
 334 
 335 #ifdef BSCBUS_LOGSTATUS
 336         /*
 337          * Command logging buffer for recording transactions with the
 338          * BSC. This is useful for debugging failed transactions and other
 339          * such funnies.
 340          */
 341         bsc_cmd_log_t           *cmd_log;
 342         uint32_t                cmd_log_idx;
 343         uint32_t                cmd_log_size;
 344         uint32_t                cmd_log_flags;
 345 #endif /* BSCBUS_LOGSTATUS */
 346 };
 347 
 348 /*
 349  * The auxiliary structure attached to each child
 350  * (the child's parent-private-data points to this).
 351  */
 352 struct bscbus_child_info {
 353         lombus_regspec_t *rsp;
 354         int nregs;
 355 };
 356 
 357 #ifdef BSCBUS_LOGSTATUS
 358 void bscbus_cmd_log(struct bscbus_channel_state *, bsc_cmd_stamp_t,
 359     uint8_t, uint8_t);
 360 #else /* BSCBUS_LOGSTATUS */
 361 #define bscbus_cmd_log(state, stamp, status, data)
 362 #endif /* BSCBUS_LOGSTATUS */
 363 
 364 
 365 /*
 366  * Local data
 367  */
 368 
 369 static void *bscbus_statep;
 370 
 371 static major_t bscbus_major = NOMAJOR;
 372 
 373 static ddi_device_acc_attr_t bscbus_dev_acc_attr[1] = {
 374         DDI_DEVICE_ATTR_V0,
 375         DDI_STRUCTURE_LE_ACC,
 376         DDI_STRICTORDER_ACC
 377 };
 378 
 379 
 380 /*
 381  *  General utility routines ...
 382  */
 383 
 384 #ifdef DEBUG
 385 static void
 386 bscbus_trace(struct bscbus_channel_state *csp, char code, const char *caller,
 387         const char *fmt, ...)
 388 {
 389         char buf[256];
 390         char *p;
 391         va_list va;
 392 
 393         if (csp->ssp->debug & (1 << (code-'@'))) {
 394                 p = buf;
 395                 (void) snprintf(p, sizeof (buf) - (p - buf),
 396                     "%s/%s: ", MYNAME, caller);
 397                 p += strlen(p);
 398 
 399                 va_start(va, fmt);
 400                 (void) vsnprintf(p, sizeof (buf) - (p - buf), fmt, va);
 401                 va_end(va);
 402 
 403                 buf[sizeof (buf) - 1] = '\0';
 404                 (void) strlog(csp->ssp->majornum, csp->ssp->instance,
 405                     code, SL_TRACE, buf);
 406         }
 407 }
 408 #else /* DEBUG */
 409 #define bscbus_trace(...) (void)(0)
 410 #endif /* DEBUG */
 411 
 412 static struct bscbus_state *
 413 bscbus_getstate(dev_info_t *dip, int instance, const char *caller)
 414 {
 415         struct bscbus_state *ssp = NULL;
 416         dev_info_t *sdip = NULL;
 417         major_t dmaj = NOMAJOR;
 418 
 419         if (dip != NULL) {
 420                 /*
 421                  * Use the instance number from the <dip>; also,
 422                  * check that it really corresponds to this driver
 423                  */
 424                 instance = ddi_get_instance(dip);
 425                 dmaj = ddi_driver_major(dip);
 426                 if (bscbus_major == NOMAJOR && dmaj != NOMAJOR)
 427                         bscbus_major = dmaj;
 428                 else if (dmaj != bscbus_major) {
 429                         cmn_err(CE_WARN,
 430                             "%s: major number mismatch (%d vs. %d) in %s(),"
 431                             "probably due to child misconfiguration",
 432                             MYNAME, bscbus_major, dmaj, caller);
 433                         instance = -1;
 434                 }
 435         }
 436 
 437         if (instance >= 0)
 438                 ssp = ddi_get_soft_state(bscbus_statep, instance);
 439         if (ssp != NULL) {
 440                 sdip = ssp->dip;
 441                 if (dip == NULL && sdip == NULL)
 442                         ssp = NULL;
 443                 else if (dip != NULL && sdip != NULL && sdip != dip) {
 444                         cmn_err(CE_WARN,
 445                             "%s: devinfo mismatch (%p vs. %p) in %s(), "
 446                             "probably due to child misconfiguration",
 447                             MYNAME, (void *)dip, (void *)sdip, caller);
 448                         ssp = NULL;
 449                 }
 450         }
 451 
 452         return (ssp);
 453 }
 454 
 455 /*
 456  * Lowest-level I/O register read/write
 457  */
 458 
 459 static void
 460 bscbus_put_reg(struct bscbus_channel_state *csp, uint_t reg, uint8_t val)
 461 {
 462         if (csp->ch_handle != NULL && !csp->xio_fault) {
 463                 ddi_put8(csp->ch_handle,
 464                     csp->ch_regs + reg, val);
 465         }
 466 }
 467 
 468 static uint8_t
 469 bscbus_get_reg(struct bscbus_channel_state *csp, uint_t reg)
 470 {
 471         uint8_t val;
 472 
 473         if (csp->ch_handle != NULL && !csp->xio_fault)
 474                 val = ddi_get8(csp->ch_handle,
 475                     csp->ch_regs + reg);
 476         else
 477                 val = DUMMY_VALUE;
 478 
 479         return (val);
 480 }
 481 
 482 static void
 483 bscbus_check_fault_status(struct bscbus_channel_state *csp)
 484 {
 485         csp->xio_fault =
 486             ddi_check_acc_handle(csp->ch_handle) != DDI_SUCCESS;
 487 }
 488 
 489 static boolean_t
 490 bscbus_faulty(struct bscbus_channel_state *csp)
 491 {
 492         if (!csp->xio_fault)
 493                 bscbus_check_fault_status(csp);
 494         return (csp->xio_fault);
 495 }
 496 
 497 /*
 498  * Write data into h8 registers
 499  */
 500 static void
 501 bscbus_pat_dog(struct bscbus_channel_state *csp, uint8_t val)
 502 {
 503         uint8_t status;
 504         uint32_t doglimit = BSCBUS_DOG_PAT_POLL_LIMIT;
 505 
 506         bscbus_trace(csp, 'W', "bscbus_pat_dog:", "");
 507 
 508         bscbus_cmd_log(csp, BSC_CMD_DOGPAT, 0, val);
 509         status = bscbus_get_reg(csp, H8_STR);
 510         while (status & H8_STR_IBF) {
 511                 if (csp->pat_retry_count > BSCBUS_PAT_RETRY_LIMIT) {
 512                         /*
 513                          * Previous attempts to contact BSC have failed.
 514                          * Do not bother waiting for it to eat previous
 515                          * data.
 516                          * Pat anyway just in case the BSC is really alive
 517                          * and the IBF bit is lying.
 518                          */
 519                         bscbus_put_reg(csp, H8_IDRC, val);
 520                         bscbus_trace(csp, 'W', "bscbus_pat_dog:",
 521                             "retry count exceeded");
 522                         return;
 523                 }
 524                 if (--doglimit == 0) {
 525                         /* The BSC is not responding - give up */
 526                         csp->pat_fail_count++;
 527                         csp->pat_retry_count++;
 528                         /* Pat anyway just in case the BSC is really alive */
 529                         bscbus_put_reg(csp, H8_IDRC, val);
 530                         bscbus_trace(csp, 'W', "bscbus_pat_dog:",
 531                             "poll limit exceeded");
 532                         return;
 533                 }
 534                 drv_usecwait(BSCBUS_DOG_PAT_POLL);
 535                 status = bscbus_get_reg(csp, H8_STR);
 536         }
 537         bscbus_put_reg(csp, H8_IDRC, val);
 538         csp->pat_retry_count = 0;
 539 }
 540 
 541 /*
 542  * State diagrams for how bscbus_process works.
 543  *      BSCBUS_CMDSTATE_IDLE            No transaction in progress
 544  *      BSCBUS_CMDSTATE_BUSY            Setting up command
 545  *      BSCBUS_CMDSTATE_CLEARING        Clearing firmware busy status
 546  *      BSCBUS_CMDSTATE_SENDING         Waiting to send data to f/w
 547  *      BSCBUS_CMDSTATE_PENDING         Waiting for ack from f/w
 548  *      BSCBUS_CMDSTATE_WAITING         Waiting for status from f/w
 549  *      BSCBUS_CMDSTATE_READY           Status received/command done
 550  *      BSCBUS_CMDSTATE_ERROR           Command failed with error
 551  *
 552  *      +----------+
 553  *      |          |
 554  *      | IDLE/BUSY|
 555  *      |   (0/1)  |  abnormal
 556  *      +----------+  state
 557  *          |     \   detected
 558  *          |      \------>------+  +----<---+
 559  *      bsc |                    |  |        |
 560  *      is  |                    V  V        |
 561  *     ready|                +----------+    |
 562  *          |                |          |    ^
 563  *          |                | CLEARING |    |
 564  *          |                |   (2)    |    |
 565  *          |                +----------+    |
 566  *          |            cleared /  | \      | more to clear
 567  *          |                   /   |  \-->--+
 568  *          |  +-------<-------/    V
 569  *          |  |                    |
 570  *          V  V                    |timeout
 571  *      +----------+ timeout        |
 572  *      |          |------>---------+--------+
 573  *      | SENDING  |                         |
 574  *      |   (3)    |------<-------+       |
 575  *      +----------+              |          V
 576  *      sent|    \ send           ^ack       |
 577  *      last|     \ next          |received  |
 578  *          |      \         +----------+    |
 579  *          |       \        |          |    |
 580  *          |        \------>| PENDING       |-->-+
 581  *          |                |   (4)    |    |
 582  *          |                +----------+    |timeout
 583  *          |    +---<----+               |
 584  *          |    |        |                  |
 585  *          V    V        |                  |
 586  *      +----------+      |                  |
 587  *      |          |      |                  |
 588  *      | WAITING  |      ^                  |
 589  *      |   (5)    |      |                  |
 590  *      +----------+      |                  |
 591  *          |  | |more    |                  |
 592  *          |  V |required|                  |
 593  *      done|  | +--->----+               |
 594  *          |  +--->--------------+  +---<---+
 595  *          |   error/timeout     |  |
 596  *          V                     V  V
 597  *      +----------+          +----------+
 598  *      |          |          |          |
 599  *      | READY    |          |  ERROR   |
 600  *      |   (7)    |          |   (6)    |
 601  *      +----------+          +----------+
 602  *          |                     |
 603  *          V                     V
 604  *          |                     |
 605  *          +------>---+---<------+
 606  *                     |
 607  *                     |
 608  *                   Back to
 609  *                    Idle
 610  */
 611 
 612 static void
 613 bscbus_process_sending(struct bscbus_channel_state *csp, uint8_t status)
 614 {
 615         /*
 616          * When we get here we actually expect H8_STR_IBF to
 617          * be clear but we check just in case of problems.
 618          */
 619         ASSERT(BSCBUS_TX_PENDING(csp));
 620         if (!(status & H8_STR_IBF)) {
 621                 bscbus_put_reg(csp, H8_IDRD, *--csp->cmdp);
 622                 bscbus_trace(csp, 'P', "bscbus_process_sending",
 623                     "state %d; val $%x",
 624                     csp->cmdstate, *csp->cmdp);
 625                 if (!BSCBUS_TX_PENDING(csp)) {
 626                         bscbus_cmd_log(csp, BSC_CMD_SENT,
 627                             status, *csp->cmdp);
 628                         /* No more pending - move to waiting state */
 629                         bscbus_trace(csp, 'P', "bscbus_process_sending",
 630                             "moving to waiting");
 631                         csp->cmdstate = BSCBUS_CMDSTATE_WAITING;
 632                         /* Extend deadline because time has moved on */
 633                         csp->deadline = ddi_get_lbolt() +
 634                             drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
 635                 } else {
 636                         /* Wait for ack of this byte */
 637                         bscbus_cmd_log(csp, BSC_CMD_SENDING,
 638                             status, *csp->cmdp);
 639                         csp->cmdstate = BSCBUS_CMDSTATE_PENDING;
 640                         bscbus_trace(csp, 'P', "bscbus_process_sending",
 641                             "moving to pending");
 642                 }
 643         }
 644 }
 645 
 646 static void
 647 bscbus_process_clearing(struct bscbus_channel_state *csp,
 648     uint8_t status, uint8_t data)
 649 {
 650         /*
 651          * We only enter this state if H8_STR_BUSY was set when
 652          * we started the transaction. We just ignore all received
 653          * data until we see OBF set AND BUSY cleared.
 654          * It is not good enough to see BUSY clear on its own
 655          */
 656         if ((status & H8_STR_OBF) && !(status & H8_STR_BUSY)) {
 657                 bscbus_cmd_log(csp, BSC_CMD_CLEARED, status, data);
 658                 csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
 659                 /* Throw away any data received up until now */
 660                 bscbus_trace(csp, 'P', "bscbus_process_clearing",
 661                     "busy cleared");
 662                 /*
 663                  * Send the next byte immediately.
 664                  * At this stage we should clear the OBF flag because that
 665                  * data has been used. IBF is still valid so do not clear that.
 666                  */
 667                 status &= ~(H8_STR_OBF);
 668                 bscbus_process_sending(csp, status);
 669         } else {
 670                 if (status & H8_STR_OBF) {
 671                         bscbus_cmd_log(csp, BSC_CMD_CLEARING, status, data);
 672                 }
 673         }
 674 }
 675 
 676 static void
 677 bscbus_process_pending(struct bscbus_channel_state *csp, uint8_t status)
 678 {
 679         /* We are waiting for an acknowledgement of a byte */
 680         if (status & H8_STR_OBF) {
 681                 bscbus_cmd_log(csp, BSC_CMD_PENDING,
 682                     status, *csp->cmdp);
 683                 bscbus_trace(csp, 'P', "bscbus_process_pending",
 684                     "moving to sending");
 685                 csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
 686                 /*
 687                  * Send the next byte immediately.
 688                  * At this stage we should clear the OBF flag because that
 689                  * data has been used. IBF is still valid so do not clear that.
 690                  */
 691                 status &= ~(H8_STR_OBF);
 692                 bscbus_process_sending(csp, status);
 693         }
 694 }
 695 
 696 static boolean_t
 697 bscbus_process_waiting(struct bscbus_channel_state *csp,
 698     uint8_t status, uint8_t data)
 699 {
 700         uint8_t rcvd = 0;
 701         boolean_t ready = B_FALSE;
 702         uint8_t tmp;
 703 
 704         if (status & H8_STR_OBF) {
 705                 csp->reply[rcvd = csp->index] = data;
 706                 if (++rcvd < BSCBUS_BUFSIZE)
 707                         csp->index = rcvd;
 708 
 709                 bscbus_trace(csp, 'D', "bscbus_process_waiting",
 710                     "rcvd %d: $%02x $%02x $%02x $%02x $%02x $%02x $%02x $%02x",
 711                     rcvd,
 712                     csp->reply[0], csp->reply[1],
 713                     csp->reply[2], csp->reply[3],
 714                     csp->reply[4], csp->reply[5],
 715                     csp->reply[6], csp->reply[7]);
 716         }
 717 
 718         if (rcvd == 0) {
 719                 /*
 720                  * No bytes received this time through (though there
 721                  * might be a partial packet sitting in the buffer).
 722                  */
 723                 /* EMPTY */
 724                 ;
 725         } else if (rcvd >= BSCBUS_BUFSIZE) {
 726                 /*
 727                  * Buffer overflow; discard the data & treat as an error
 728                  * (even if the last byte read did claim to terminate a
 729                  * packet, it can't be a valid one 'cos it's too long!)
 730                  */
 731                 bscbus_cmd_log(csp, BSC_CMD_ERROR_OFLOW, status, data);
 732                 csp->index = 0;
 733                 csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
 734                 csp->error = LOMBUS_ERR_OFLOW;
 735                 ready = B_TRUE;
 736         } else if ((data & BSCBUS_LAST) == 0) {
 737                 /*
 738                  * Packet not yet complete; leave the partial packet in
 739                  * the buffer for later ...
 740                  */
 741                 bscbus_cmd_log(csp, BSC_CMD_REPLY, status, data);
 742         } else if ((data & BSCBUS_MASK) != BSCBUS_STATUS) {
 743                 /* Invalid "status" byte - maybe an echo of the command? */
 744                 bscbus_cmd_log(csp, BSC_CMD_ERROR_STATUS, status, data);
 745 
 746                 csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
 747                 csp->error = LOMBUS_ERR_BADSTATUS;
 748                 ready = B_TRUE;
 749         } else if ((data & BSCBUS_SEQ) != csp->sequence) {
 750                 /* Wrong sequence number!  Flag this as an error */
 751                 bscbus_cmd_log(csp, BSC_CMD_ERROR_SEQ, status, data);
 752 
 753                 csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
 754                 csp->error = LOMBUS_ERR_SEQUENCE;
 755                 ready = B_TRUE;
 756         } else {
 757                 /*
 758                  * Finally, we know that's it's a valid reply to our
 759                  * last command.  Update the ASYNC status, derive the
 760                  * reply parameter (if any), and check the ERROR bit
 761                  * to find out what the parameter means.
 762                  *
 763                  * Note that not all the values read/assigned here
 764                  * are meaningful, but it doesn't matter; the waiting
 765                  * thread will know which one(s) it should check.
 766                  */
 767                 bscbus_cmd_log(csp, BSC_CMD_COMPLETE, status, data);
 768                 csp->async = (data & BSCBUS_STATUS_ASYNC) ? 1 : 0;
 769 
 770                 tmp = ((data & BSCBUS_STATUS_MSB) ? 0x80 : 0) | csp->reply[0];
 771                 if (data & BSCBUS_STATUS_ERR) {
 772                         csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
 773                         csp->error = tmp;
 774                 } else {
 775                         csp->cmdstate = BSCBUS_CMDSTATE_READY;
 776                         csp->result = tmp;
 777                 }
 778                 ready = B_TRUE;
 779         }
 780         return (ready);
 781 }
 782 
 783 /*
 784  * Packet receive handler
 785  *
 786  * This routine should be called from the low-level softint,
 787  * or bscbus_cmd() (for polled operation), with the
 788  * low-level mutex already held.
 789  */
 790 static void
 791 bscbus_process(struct bscbus_channel_state *csp,
 792     uint8_t status, uint8_t data)
 793 {
 794         boolean_t ready = B_FALSE;
 795 
 796         ASSERT(mutex_owned(csp->lo_mutex));
 797 
 798         if ((status & H8_STR_OBF) || (status & H8_STR_IBF)) {
 799                 bscbus_trace(csp, 'D', "bscbus_process",
 800                     "state %d; error $%x",
 801                     csp->cmdstate, csp->error);
 802         }
 803 
 804         switch (csp->cmdstate) {
 805         case BSCBUS_CMDSTATE_CLEARING:
 806                 bscbus_process_clearing(csp, status, data);
 807                 break;
 808         case BSCBUS_CMDSTATE_SENDING:
 809                 bscbus_process_sending(csp, status);
 810                 break;
 811         case BSCBUS_CMDSTATE_PENDING:
 812                 bscbus_process_pending(csp, status);
 813                 break;
 814         case BSCBUS_CMDSTATE_WAITING:
 815                 ready = bscbus_process_waiting(csp, status, data);
 816                 break;
 817         default:
 818                 /* Nothing to do */
 819                 break;
 820         }
 821 
 822         /*
 823          * Check for timeouts - but only if the command has not yet
 824          * completed (ready is true when command completes in this
 825          * call to bscbus_process OR cmdstate is READY or ERROR if
 826          * this is a spurious call to bscbus_process i.e. a spurious
 827          * interrupt)
 828          */
 829         if (!ready &&
 830             ((ddi_get_lbolt() - csp->deadline) > 0) &&
 831             csp->cmdstate != BSCBUS_CMDSTATE_READY &&
 832             csp->cmdstate != BSCBUS_CMDSTATE_ERROR) {
 833                 bscbus_trace(csp, 'P', "bscbus_process",
 834                     "timeout previous state %d; error $%x",
 835                     csp->cmdstate, csp->error);
 836                 bscbus_cmd_log(csp, BSC_CMD_ERROR_TOUT, status, data);
 837                 if (csp->cmdstate == BSCBUS_CMDSTATE_CLEARING) {
 838                         /* Move onto sending because busy might be stuck */
 839                         csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
 840                         /* Extend timeout relative to original start time */
 841                         csp->deadline += drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
 842                 } else if (csp->cmdstate != BSCBUS_CMDSTATE_IDLE) {
 843                         csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
 844                         csp->error = LOMBUS_ERR_TIMEOUT;
 845                 }
 846                 ready = B_TRUE;
 847         }
 848 
 849         if ((status & H8_STR_OBF) || (status & H8_STR_IBF) || ready) {
 850                 bscbus_trace(csp, 'D', "bscbus_process",
 851                     "last $%02x; state %d; error $%x; ready %d",
 852                     data, csp->cmdstate, csp->error, ready);
 853         }
 854         if (ready)
 855                 cv_broadcast(csp->lo_cv);
 856 }
 857 
 858 static uint_t
 859 bscbus_hwintr(caddr_t arg)
 860 {
 861         struct bscbus_channel_state *csp = (void *)arg;
 862 
 863         uint8_t status;
 864         uint8_t data = 0xb0 /* Dummy value */;
 865 
 866         mutex_enter(csp->lo_mutex);
 867         /*
 868          * Read the registers to ensure that the interrupt is cleared.
 869          * Status must be read first because reading data changes the
 870          * status.
 871          * We always read the data because that clears the interrupt down.
 872          * This is horrible hardware semantics but we have to do it!
 873          */
 874         status = bscbus_get_reg(csp, H8_STR);
 875         data = bscbus_get_reg(csp, H8_ODR);
 876         if (!(status & H8_STR_OBF)) {
 877                 bscbus_cmd_log(csp, BSC_CMD_V1INTRUNCL, status, data);
 878                 csp->unclaimed_count++;
 879         } else {
 880                 bscbus_cmd_log(csp, BSC_CMD_V1INTR, status, data);
 881         }
 882         if (status & H8_STR_TOKENPROTOCOL) {
 883                 bscbus_process(csp, status, data);
 884                 if (csp->interrupt_failed) {
 885                         bscbus_trace(csp, 'I', "bscbus_hwintr:",
 886                             "interrupt fault cleared channel %d", csp->chno);
 887                         csp->interrupt_failed = B_FALSE;
 888                         csp->poll_hz = drv_usectohz(BSCBUS_CMD_POLL / 1000);
 889                 }
 890         }
 891 
 892         mutex_exit(csp->lo_mutex);
 893         return (DDI_INTR_CLAIMED);
 894 }
 895 
 896 void
 897 bscbus_poll(struct bscbus_channel_state *csp)
 898 {
 899         /*
 900          * This routine is only called if we timeout in userland
 901          * waiting for an interrupt. This generally means that we have
 902          * lost interrupt capabilities or that something has gone
 903          * wrong.  In this case we are allowed to access the hardware
 904          * and read the data register if necessary.
 905          * If interrupts return then recovery actions should mend us!
 906          */
 907         uint8_t status;
 908         uint8_t data = 0xfa; /* Dummy value */
 909 
 910         ASSERT(mutex_owned(csp->lo_mutex));
 911 
 912         /* Should look for data to receive */
 913         status = bscbus_get_reg(csp, H8_STR);
 914         if (status & H8_STR_OBF) {
 915                 /* There is data available */
 916                 data = bscbus_get_reg(csp, H8_ODR);
 917                 bscbus_cmd_log(csp, BSC_CMD_PROCESS, status, data);
 918         }
 919         bscbus_process(csp, status, data);
 920 }
 921 
 922 /*
 923  * Serial protocol
 924  *
 925  * This routine builds a command and sets it in progress.
 926  */
 927 static uint8_t
 928 bscbus_cmd(HANDLE_TYPE *hdlp, ptrdiff_t vreg, uint_t val, uint_t cmd)
 929 {
 930         struct bscbus_channel_state *csp;
 931         clock_t start;
 932         uint8_t status;
 933 
 934         /*
 935          * First of all, wait for the interface to be available.
 936          *
 937          * NOTE: we blow through all the mutex/cv/state checking and
 938          * preempt any command in progress if the system is panicking!
 939          */
 940         csp = HANDLE_PRIVATE(hdlp);
 941         mutex_enter(csp->lo_mutex);
 942         while (csp->cmdstate != BSCBUS_CMDSTATE_IDLE && !ddi_in_panic())
 943                 cv_wait(csp->lo_cv, csp->lo_mutex);
 944 
 945         csp->cmdstate = BSCBUS_CMDSTATE_BUSY;
 946         csp->sequence = (csp->sequence + BSCBUS_SEQ_LSB) & BSCBUS_SEQ;
 947 
 948         /*
 949          * We have exclusive ownership, so assemble the command (backwards):
 950          *
 951          * [byte 0]     Command:        modified by XADDR and/or WMSB bits
 952          * [Optional] Parameter:        Value to write (low 7 bits)
 953          * [Optional] Parameter:        Register number (high 7 bits)
 954          * [Optional] Parameter:        Register number (low 7 bits)
 955          */
 956         csp->cmdp = &csp->cmdbuf[0];
 957         *csp->cmdp++ = BSCBUS_CMD | csp->sequence | cmd;
 958         switch (cmd) {
 959         case BSCBUS_CMD_WRITE:
 960                 *csp->cmdp++ = val & 0x7f;
 961                 if (val >= 0x80)
 962                         csp->cmdbuf[0] |= BSCBUS_CMD_WMSB;
 963                 /*FALLTHRU*/
 964         case BSCBUS_CMD_READ:
 965                 if (BSCBUS_VREG_HI(vreg) != 0) {
 966                         *csp->cmdp++ = BSCBUS_VREG_HI(vreg);
 967                         csp->cmdbuf[0] |= BSCBUS_CMD_XADDR;
 968                 }
 969                 *csp->cmdp++ = BSCBUS_VREG_LO(vreg);
 970                 /*FALLTHRU*/
 971         case BSCBUS_CMD_NOP:
 972                 break;
 973         }
 974 
 975         /*
 976          * Check and update the H8 h/w fault status before accessing
 977          * the chip registers.  If there's a (new or previous) fault,
 978          * we'll run through the protocol but won't really touch the
 979          * hardware and all commands will timeout.  If a previously
 980          * discovered fault has now gone away (!), then we can (try to)
 981          * proceed with the new command (probably a probe).
 982          */
 983         bscbus_check_fault_status(csp);
 984 
 985         /*
 986          * Prepare for the command (to be processed by the interrupt
 987          * handler and/or polling loop below), and wait for a response
 988          * or timeout.
 989          */
 990         start = ddi_get_lbolt();
 991         csp->deadline = start + drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
 992         csp->error = 0;
 993         csp->index = 0;
 994         csp->result = DUMMY_VALUE;
 995 
 996         status = bscbus_get_reg(csp, H8_STR);
 997         if (status & H8_STR_BUSY) {
 998                 bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0xfd);
 999                 /*
1000                  * Must ensure that the busy state has cleared before
1001                  * sending the command
1002                  */
1003                 csp->cmdstate = BSCBUS_CMDSTATE_CLEARING;
1004                 bscbus_trace(csp, 'P', "bscbus_cmd",
1005                     "h8 reporting status (%x) busy - clearing", status);
1006         } else {
1007                 /* It is clear to send the command immediately */
1008                 csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
1009                 bscbus_trace(csp, 'P', "bscbus_cmd",
1010                     "sending first byte of command, status %x", status);
1011                 bscbus_poll(csp);
1012         }
1013 
1014         csp->poll_hz = drv_usectohz(
1015             (csp->interrupt_failed ?
1016             BSCBUS_CMD_POLLNOINTS : BSCBUS_CMD_POLL) / 1000);
1017 
1018         while ((csp->cmdstate != BSCBUS_CMDSTATE_READY) &&
1019             (csp->cmdstate != BSCBUS_CMDSTATE_ERROR)) {
1020                 ASSERT(csp->cmdstate != BSCBUS_CMDSTATE_IDLE);
1021 
1022                 if ((cv_reltimedwait(csp->lo_cv, csp->lo_mutex,
1023                     csp->poll_hz, TR_CLOCK_TICK) == -1) &&
1024                     csp->cmdstate != BSCBUS_CMDSTATE_READY &&
1025                     csp->cmdstate != BSCBUS_CMDSTATE_ERROR) {
1026                         if (!csp->interrupt_failed) {
1027                                 bscbus_trace(csp, 'I', "bscbus_cmd:",
1028                                     "interrupt_failed channel %d", csp->chno);
1029                                 csp->interrupt_failed = B_TRUE;
1030                                 csp->poll_hz = drv_usectohz(
1031                                     BSCBUS_CMD_POLLNOINTS / 1000);
1032                         }
1033                         bscbus_poll(csp);
1034                 }
1035         }
1036 
1037         /*
1038          * The return value may not be meaningful but retrieve it anyway
1039          */
1040         val = csp->result;
1041         if (bscbus_faulty(csp)) {
1042                 val = DUMMY_VALUE;
1043                 HANDLE_FAULT(hdlp) = LOMBUS_ERR_SIOHW;
1044         } else if (csp->cmdstate != BSCBUS_CMDSTATE_READY) {
1045                 /*
1046                  * Some problem here ... transfer the error code from
1047                  * the per-instance state to the per-handle fault flag.
1048                  * The error code shouldn't be zero!
1049                  */
1050                 if (csp->error != 0)
1051                         HANDLE_FAULT(hdlp) = csp->error;
1052                 else
1053                         HANDLE_FAULT(hdlp) = LOMBUS_ERR_BADERRCODE;
1054         }
1055 
1056         /*
1057          * All done now!
1058          */
1059         csp->index = 0;
1060         csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
1061         cv_broadcast(csp->lo_cv);
1062         mutex_exit(csp->lo_mutex);
1063 
1064         return (val);
1065 }
1066 
1067 /*
1068  * Space 0 - LOM virtual register access
1069  * Only 8-bit accesses are supported.
1070  */
1071 static uint8_t
1072 bscbus_vreg_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1073 {
1074         ptrdiff_t offset;
1075 
1076         /*
1077          * Check the offset that the caller has added to the base address
1078          * against the length of the mapping originally requested.
1079          */
1080         offset = ADDR_TO_OFFSET(addr, hdlp);
1081         if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1082                 /*
1083                  * Invalid access - flag a fault and return a dummy value
1084                  */
1085                 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1086                 return (DUMMY_VALUE);
1087         }
1088 
1089         /*
1090          * Derive the virtual register number and run the command
1091          */
1092         return (bscbus_cmd(hdlp, ADDR_TO_VREG(addr), 0, BSCBUS_CMD_READ));
1093 }
1094 
1095 static void
1096 bscbus_vreg_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1097 {
1098         ptrdiff_t offset;
1099 
1100         /*
1101          * Check the offset that the caller has added to the base address
1102          * against the length of the mapping originally requested.
1103          */
1104         offset = ADDR_TO_OFFSET(addr, hdlp);
1105         if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1106                 /*
1107                  * Invalid access - flag a fault and return
1108                  */
1109                 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1110                 return;
1111         }
1112 
1113         /*
1114          * Derive the virtual register number and run the command
1115          */
1116         (void) bscbus_cmd(hdlp, ADDR_TO_VREG(addr), val, BSCBUS_CMD_WRITE);
1117 }
1118 
1119 static void
1120 bscbus_vreg_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1121         uint8_t *dev_addr, size_t repcount, uint_t flags)
1122 {
1123         size_t inc;
1124 
1125         inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1126         for (; repcount--; dev_addr += inc)
1127                 *host_addr++ = bscbus_vreg_get8(hdlp, dev_addr);
1128 }
1129 
1130 static void
1131 bscbus_vreg_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1132         uint8_t *dev_addr, size_t repcount, uint_t flags)
1133 {
1134         size_t inc;
1135 
1136         inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1137         for (; repcount--; dev_addr += inc)
1138                 bscbus_vreg_put8(hdlp, dev_addr, *host_addr++);
1139 }
1140 
1141 
1142 /*
1143  * Space 1 - LOM watchdog pat register access
1144  * Only 8-bit accesses are supported.
1145  *
1146  * Reads have no effect and return 0.
1147  *
1148  * Multi-byte reads (using ddi_rep_get8(9F)) are a fairly inefficient
1149  * way of zeroing the destination area ;-) and still won't pat the dog.
1150  *
1151  * Multi-byte writes (using ddi_rep_put8(9F)) will almost certainly
1152  * only count as a single pat, no matter how many bytes the caller
1153  * says to write, as the inter-pat time is VERY long compared with
1154  * the time it will take to read the memory source area.
1155  */
1156 
1157 static uint8_t
1158 bscbus_pat_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1159 {
1160         ptrdiff_t offset;
1161 
1162         /*
1163          * Check the offset that the caller has added to the base address
1164          * against the length of the mapping originally requested.
1165          */
1166         offset = ADDR_TO_OFFSET(addr, hdlp);
1167         if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1168                 /*
1169                  * Invalid access - flag a fault and return a dummy value
1170                  */
1171                 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1172                 return (DUMMY_VALUE);
1173         }
1174 
1175         return (0);
1176 }
1177 
1178 static void
1179 bscbus_pat_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1180 {
1181         struct bscbus_channel_state *csp;
1182         ptrdiff_t offset;
1183 
1184         /*
1185          * Check the offset that the caller has added to the base address
1186          * against the length of the mapping originally requested.
1187          */
1188         offset = ADDR_TO_OFFSET(addr, hdlp);
1189         if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1190                 /*
1191                  * Invalid access - flag a fault and return
1192                  */
1193                 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1194                 return;
1195         }
1196 
1197         csp = HANDLE_PRIVATE(hdlp);
1198         mutex_enter(csp->dog_mutex);
1199         bscbus_pat_dog(csp, val);
1200         mutex_exit(csp->dog_mutex);
1201 }
1202 
1203 static void
1204 bscbus_pat_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1205         uint8_t *dev_addr, size_t repcount, uint_t flags)
1206 {
1207         size_t inc;
1208 
1209         inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1210         for (; repcount--; dev_addr += inc)
1211                 *host_addr++ = bscbus_pat_get8(hdlp, dev_addr);
1212 }
1213 
1214 static void
1215 bscbus_pat_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1216         uint8_t *dev_addr, size_t repcount, uint_t flags)
1217 {
1218         size_t inc;
1219 
1220         inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1221         for (; repcount--; dev_addr += inc)
1222                 bscbus_pat_put8(hdlp, dev_addr, *host_addr++);
1223 }
1224 
1225 
1226 /*
1227  * Space 2 - LOM async event flag register access
1228  * Only 16-bit accesses are supported.
1229  */
1230 static uint16_t
1231 bscbus_event_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
1232 {
1233         struct bscbus_channel_state *csp;
1234         ptrdiff_t offset;
1235 
1236         /*
1237          * Check the offset that the caller has added to the base address
1238          * against the length of the mapping orignally requested.
1239          */
1240         offset = ADDR_TO_OFFSET(addr, hdlp);
1241         if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1242                 /*
1243                  * Invalid access - flag a fault and return a dummy value
1244                  */
1245                 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1246                 return (DUMMY_VALUE);
1247         }
1248 
1249         /*
1250          * Return the value of the asynchronous-event-pending flag
1251          * as passed back by the LOM at the end of the last command.
1252          */
1253         csp = HANDLE_PRIVATE(hdlp);
1254         return (csp->async);
1255 }
1256 
1257 static void
1258 bscbus_event_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
1259 {
1260         ptrdiff_t offset;
1261 
1262         _NOTE(ARGUNUSED(val))
1263 
1264         /*
1265          * Check the offset that the caller has added to the base address
1266          * against the length of the mapping originally requested.
1267          */
1268         offset = ADDR_TO_OFFSET(addr, hdlp);
1269         if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1270                 /*
1271                  * Invalid access - flag a fault and return
1272                  */
1273                 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1274                 return;
1275         }
1276 
1277         /*
1278          * The user can't overwrite the asynchronous-event-pending flag!
1279          */
1280         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_RO;
1281 }
1282 
1283 static void
1284 bscbus_event_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1285         uint16_t *dev_addr, size_t repcount, uint_t flags)
1286 {
1287         size_t inc;
1288 
1289         inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1290         for (; repcount--; dev_addr += inc)
1291                 *host_addr++ = bscbus_event_get16(hdlp, dev_addr);
1292 }
1293 
1294 static void
1295 bscbus_event_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1296         uint16_t *dev_addr, size_t repcount, uint_t flags)
1297 {
1298         size_t inc;
1299 
1300         inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1301         for (; repcount--; dev_addr += inc)
1302                 bscbus_event_put16(hdlp, dev_addr, *host_addr++);
1303 }
1304 
1305 
1306 /*
1307  * All spaces - access handle fault information
1308  * Only 32-bit accesses are supported.
1309  */
1310 static uint32_t
1311 bscbus_meta_get32(HANDLE_TYPE *hdlp, uint32_t *addr)
1312 {
1313         struct bscbus_channel_state *csp;
1314         ptrdiff_t offset;
1315 
1316         /*
1317          * Derive the offset that the caller has added to the base
1318          * address originally returned, and use it to determine
1319          * which meta-register is to be accessed ...
1320          */
1321         offset = ADDR_TO_OFFSET(addr, hdlp);
1322         switch (offset) {
1323         case LOMBUS_FAULT_REG:
1324                 /*
1325                  * This meta-register provides a code for the most
1326                  * recent virtual register access fault, if any.
1327                  */
1328                 return (HANDLE_FAULT(hdlp));
1329 
1330         case LOMBUS_PROBE_REG:
1331                 /*
1332                  * Reading this meta-register clears any existing fault
1333                  * (at the virtual, not the hardware access layer), then
1334                  * runs a NOP command and returns the fault code from that.
1335                  */
1336                 HANDLE_FAULT(hdlp) = 0;
1337                 (void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
1338                 return (HANDLE_FAULT(hdlp));
1339 
1340         case LOMBUS_ASYNC_REG:
1341                 /*
1342                  * Obsolescent - but still supported for backwards
1343                  * compatibility.  This is an alias for the newer
1344                  * LOMBUS_EVENT_REG, but doesn't require a separate
1345                  * "reg" entry and ddi_regs_map_setup() call.
1346                  *
1347                  * It returns the value of the asynchronous-event-pending
1348                  * flag as passed back by the BSC at the end of the last
1349                  * completed command.
1350                  */
1351                 csp = HANDLE_PRIVATE(hdlp);
1352                 return (csp->async);
1353 
1354         default:
1355                 /*
1356                  * Invalid access - flag a fault and return a dummy value
1357                  */
1358                 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1359                 return (DUMMY_VALUE);
1360         }
1361 }
1362 
1363 static void
1364 bscbus_meta_put32(HANDLE_TYPE *hdlp, uint32_t *addr, uint32_t val)
1365 {
1366         ptrdiff_t offset;
1367 
1368         /*
1369          * Derive the offset that the caller has added to the base
1370          * address originally returned, and use it to determine
1371          * which meta-register is to be accessed ...
1372          */
1373         offset = ADDR_TO_OFFSET(addr, hdlp);
1374         switch (offset) {
1375         case LOMBUS_FAULT_REG:
1376                 /*
1377                  * This meta-register contains a code for the most
1378                  * recent virtual register access fault, if any.
1379                  * It can be cleared simply by writing 0 to it.
1380                  */
1381                 HANDLE_FAULT(hdlp) = val;
1382                 return;
1383 
1384         case LOMBUS_PROBE_REG:
1385                 /*
1386                  * Writing this meta-register clears any existing fault
1387                  * (at the virtual, not the hardware acess layer), then
1388                  * runs a NOP command.  The caller can check the fault
1389                  * code later if required.
1390                  */
1391                 HANDLE_FAULT(hdlp) = 0;
1392                 (void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
1393                 return;
1394 
1395         default:
1396                 /*
1397                  * Invalid access - flag a fault
1398                  */
1399                 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1400                 return;
1401         }
1402 }
1403 
1404 static void
1405 bscbus_meta_rep_get32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
1406         uint32_t *dev_addr, size_t repcount, uint_t flags)
1407 {
1408         size_t inc;
1409 
1410         inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1411         for (; repcount--; dev_addr += inc)
1412                 *host_addr++ = bscbus_meta_get32(hdlp, dev_addr);
1413 }
1414 
1415 static void
1416 bscbus_meta_rep_put32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
1417         uint32_t *dev_addr, size_t repcount, uint_t flags)
1418 {
1419         size_t inc;
1420 
1421         inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1422         for (; repcount--; dev_addr += inc)
1423                 bscbus_meta_put32(hdlp, dev_addr, *host_addr++);
1424 }
1425 
1426 
1427 /*
1428  * Finally, some dummy functions for all unsupported access
1429  * space/size/mode combinations ...
1430  */
1431 static uint8_t
1432 bscbus_no_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1433 {
1434         _NOTE(ARGUNUSED(addr))
1435 
1436         /*
1437          * Invalid access - flag a fault and return a dummy value
1438          */
1439         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1440         return (DUMMY_VALUE);
1441 }
1442 
1443 static void
1444 bscbus_no_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1445 {
1446         _NOTE(ARGUNUSED(addr, val))
1447 
1448         /*
1449          * Invalid access - flag a fault
1450          */
1451         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1452 }
1453 
1454 static void
1455 bscbus_no_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1456                 uint8_t *dev_addr, size_t repcount, uint_t flags)
1457 {
1458         _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1459 
1460         /*
1461          * Invalid access - flag a fault
1462          */
1463         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1464 }
1465 
1466 static void
1467 bscbus_no_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1468         uint8_t *dev_addr, size_t repcount, uint_t flags)
1469 {
1470         _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1471 
1472         /*
1473          * Invalid access - flag a fault
1474          */
1475         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1476 }
1477 
1478 static uint16_t
1479 bscbus_no_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
1480 {
1481         _NOTE(ARGUNUSED(addr))
1482 
1483         /*
1484          * Invalid access - flag a fault and return a dummy value
1485          */
1486         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1487         return (DUMMY_VALUE);
1488 }
1489 
1490 static void
1491 bscbus_no_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
1492 {
1493         _NOTE(ARGUNUSED(addr, val))
1494 
1495         /*
1496          * Invalid access - flag a fault
1497          */
1498         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1499 }
1500 
1501 static void
1502 bscbus_no_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1503                 uint16_t *dev_addr, size_t repcount, uint_t flags)
1504 {
1505         _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1506 
1507         /*
1508          * Invalid access - flag a fault
1509          */
1510         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1511 }
1512 
1513 static void
1514 bscbus_no_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1515         uint16_t *dev_addr, size_t repcount, uint_t flags)
1516 {
1517         _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1518 
1519         /*
1520          * Invalid access - flag a fault
1521          */
1522         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1523 }
1524 
1525 static uint64_t
1526 bscbus_no_get64(HANDLE_TYPE *hdlp, uint64_t *addr)
1527 {
1528         _NOTE(ARGUNUSED(addr))
1529 
1530         /*
1531          * Invalid access - flag a fault and return a dummy value
1532          */
1533         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1534         return (DUMMY_VALUE);
1535 }
1536 
1537 static void
1538 bscbus_no_put64(HANDLE_TYPE *hdlp, uint64_t *addr, uint64_t val)
1539 {
1540         _NOTE(ARGUNUSED(addr, val))
1541 
1542         /*
1543          * Invalid access - flag a fault
1544          */
1545         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1546 }
1547 
1548 static void
1549 bscbus_no_rep_get64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
1550         uint64_t *dev_addr, size_t repcount, uint_t flags)
1551 {
1552         _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1553 
1554         /*
1555          * Invalid access - flag a fault
1556          */
1557         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1558 }
1559 
1560 static void
1561 bscbus_no_rep_put64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
1562         uint64_t *dev_addr, size_t repcount, uint_t flags)
1563 {
1564         _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1565 
1566         /*
1567          * Invalid access - flag a fault
1568          */
1569         HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1570 }
1571 
1572 static int
1573 bscbus_acc_fault_check(HANDLE_TYPE *hdlp)
1574 {
1575         return (HANDLE_FAULT(hdlp) != 0);
1576 }
1577 
1578 /*
1579  * Hardware setup - ensure that there are no pending transactions and
1580  * hence no pending interrupts. We do this be ensuring that the BSC is
1581  * not reporting a busy condition and that it does not have any data
1582  * pending in its output buffer.
1583  * This is important because if we have pending interrupts at attach
1584  * time Solaris will hang due to bugs in ddi_get_iblock_cookie.
1585  */
1586 static void
1587 bscbus_hw_reset(struct bscbus_channel_state *csp)
1588 {
1589         int64_t timeout;
1590         uint8_t status;
1591 
1592         if (csp->map_count == 0) {
1593                 /* No-one using this instance - no need to reset hardware */
1594                 return;
1595         }
1596 
1597         bscbus_trace(csp, 'R', "bscbus_hw_reset",
1598             "resetting channel %d", csp->chno);
1599 
1600         status = bscbus_get_reg(csp, H8_STR);
1601         if (status & H8_STR_BUSY) {
1602                 /*
1603                  * Give the h8 time to complete a reply.
1604                  * In practice we should never worry about this
1605                  * because whenever we get here it will have been
1606                  * long enough for the h8 to complete a reply
1607                  */
1608                 bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0);
1609                 bscbus_trace(csp, 'R', "bscbus_hw_reset",
1610                     "h8 reporting status (%x) busy - waiting", status);
1611                 if (ddi_in_panic()) {
1612                         drv_usecwait(BSCBUS_HWRESET_POLL/1000);
1613                 } else {
1614                         delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
1615                 }
1616         }
1617         /* Reply should be completed by now. Try to clear busy status */
1618         status = bscbus_get_reg(csp, H8_STR);
1619         if (status & (H8_STR_BUSY | H8_STR_OBF)) {
1620                 bscbus_trace(csp, 'R', "bscbus_hw_reset",
1621                     "clearing busy status for channel %d", csp->chno);
1622 
1623                 for (timeout = BSCBUS_HWRESET_TIMEOUT;
1624                     (timeout > 0);
1625                     timeout -= BSCBUS_HWRESET_POLL) {
1626                         if (status & H8_STR_OBF) {
1627                                 (void) bscbus_get_reg(csp, H8_ODR);
1628                                 if (!(status & H8_STR_BUSY)) {
1629                                         /* We are done */
1630                                         break;
1631                                 }
1632                         }
1633                         if (ddi_in_panic()) {
1634                                 drv_usecwait(BSCBUS_HWRESET_POLL/1000);
1635                         } else {
1636                                 delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
1637                         }
1638                         status = bscbus_get_reg(csp, H8_STR);
1639                 }
1640                 if (timeout <= 0) {
1641                         cmn_err(CE_WARN, "bscbus_hw_reset: timed out "
1642                             "clearing busy status");
1643                 }
1644         }
1645         /*
1646          * We read ODR just in case there is a pending interrupt with
1647          * no data. This is potentially dangerous because we could get
1648          * out of sync due to race conditions BUT at this point the
1649          * channel should be idle so it is safe.
1650          */
1651         (void) bscbus_get_reg(csp, H8_ODR);
1652 }
1653 
1654 /*
1655  * Higher-level setup & teardown
1656  */
1657 
1658 static void
1659 bscbus_offline(struct bscbus_state *ssp)
1660 {
1661         if (ssp->h8_handle != NULL)
1662                 ddi_regs_map_free(&ssp->h8_handle);
1663         ssp->h8_handle = NULL;
1664         ssp->h8_regs = NULL;
1665 }
1666 
1667 static int
1668 bscbus_online(struct bscbus_state *ssp)
1669 {
1670         ddi_acc_handle_t h;
1671         caddr_t p;
1672         int nregs;
1673         int err;
1674 
1675         ssp->h8_handle = NULL;
1676         ssp->h8_regs = (void *)NULL;
1677         ssp->per_channel_regs = B_FALSE;
1678 
1679         if (ddi_dev_nregs(ssp->dip, &nregs) != DDI_SUCCESS)
1680                 nregs = 0;
1681 
1682         switch (nregs) {
1683         case 1:
1684                 /*
1685                  *  regset 0 represents the H8 interface registers
1686                  */
1687                 err = ddi_regs_map_setup(ssp->dip, 0, &p, 0, 0,
1688                     bscbus_dev_acc_attr, &h);
1689                 if (err != DDI_SUCCESS)
1690                         return (EIO);
1691 
1692                 ssp->h8_handle = h;
1693                 ssp->h8_regs = (void *)p;
1694                 break;
1695 
1696         case 0:
1697                 /*
1698                  *  If no registers are defined, succeed vacuously;
1699                  *  commands will be accepted, but we fake the accesses.
1700                  */
1701                 break;
1702 
1703         default:
1704                 /*
1705                  * Remember that we are using the new register scheme.
1706                  * reg set 0 is chan 0
1707                  * reg set 1 is chan 1 ...
1708                  * Interrupts are specified in that order but later
1709                  * channels may not have interrupts.
1710                  * We map the regs later on a per channel basis.
1711                  */
1712                 ssp->per_channel_regs = B_TRUE;
1713                 break;
1714         }
1715         return (0);
1716 }
1717 
1718 static int
1719 bscbus_claim_channel(struct bscbus_channel_state *csp, boolean_t map_dog)
1720 {
1721         int err;
1722 
1723         mutex_enter(csp->ssp->ch_mutex);
1724         csp->map_count++;
1725         bscbus_trace(csp, 'C', "bscbus_claim_channel",
1726             "claim channel for channel %d, count %d",
1727             csp->chno, csp->map_count);
1728 
1729         if (csp->map_count == 1) {
1730                 /* No-one is using this channel - initialise it */
1731                 bscbus_trace(csp, 'C', "bscbus_claim_channel",
1732                     "initialise channel %d, count %d",
1733                     csp->chno, csp->map_count);
1734 
1735                 mutex_init(csp->dog_mutex, NULL, MUTEX_DRIVER,
1736                     (void *)(uintptr_t)__ipltospl(SPL7 - 1));
1737                 csp->map_dog = map_dog;
1738                 csp->interrupt_failed = B_FALSE;
1739                 csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
1740                 csp->pat_retry_count = 0;
1741                 csp->pat_fail_count = 0;
1742 
1743                 /* Map appropriate register set for this channel */
1744                 if (csp->ssp->per_channel_regs == B_TRUE) {
1745                         ddi_acc_handle_t h;
1746                         caddr_t p;
1747 
1748                         err = ddi_regs_map_setup(csp->ssp->dip, csp->chno,
1749                             &p, 0, 0, bscbus_dev_acc_attr, &h);
1750 
1751                         if (err != DDI_SUCCESS) {
1752                                 goto failed1;
1753                         }
1754 
1755                         csp->ch_handle = h;
1756                         csp->ch_regs = (void *)p;
1757 
1758                         bscbus_trace(csp, 'C', "bscbus_claim_channel",
1759                             "mapped chno=%d ch_handle=%d ch_regs=%p",
1760                             csp->chno, h, p);
1761                 } else {
1762                         /*
1763                          * if using the old reg property scheme use the
1764                          * common mapping.
1765                          */
1766                         csp->ch_handle = csp->ssp->h8_handle;
1767                         csp->ch_regs =
1768                             csp->ssp->h8_regs +
1769                             BSCBUS_CHANNEL_TO_OFFSET(csp->chno);
1770                 }
1771 
1772                 /* Ensure no interrupts pending prior to getting iblk cookie */
1773                 bscbus_hw_reset(csp);
1774 
1775                 if (csp->map_dog == 1) {
1776                         /*
1777                          * we don't want lo_mutex to be initialised
1778                          * with an iblock cookie if we are the wdog,
1779                          * because we don't use interrupts.
1780                          */
1781                         mutex_init(csp->lo_mutex, NULL,
1782                             MUTEX_DRIVER, NULL);
1783                         cv_init(csp->lo_cv, NULL,
1784                             CV_DRIVER, NULL);
1785                         csp->unclaimed_count = 0;
1786                 } else {
1787                         int ninterrupts;
1788 
1789                         /*
1790                          * check that there is an interrupt for this
1791                          * this channel. If we fail to setup interrupts we
1792                          * must unmap the registers and fail.
1793                          */
1794                         err = ddi_dev_nintrs(csp->ssp->dip, &ninterrupts);
1795 
1796                         if (err != DDI_SUCCESS) {
1797                                 ninterrupts = 0;
1798                         }
1799 
1800                         if (ninterrupts <= csp->chno) {
1801                                 cmn_err(CE_WARN,
1802                                     "no interrupt available for "
1803                                     "bscbus channel %d", csp->chno);
1804                                 goto failed2;
1805                         }
1806 
1807                         if (ddi_intr_hilevel(csp->ssp->dip, csp->chno) != 0) {
1808                                 cmn_err(CE_WARN,
1809                                     "bscbus interrupts are high "
1810                                     "level - channel not usable.");
1811                                 goto failed2;
1812                         } else {
1813                                 err = ddi_get_iblock_cookie(csp->ssp->dip,
1814                                     csp->chno, &csp->lo_iblk);
1815                                 if (err != DDI_SUCCESS) {
1816                                         goto failed2;
1817                                 }
1818 
1819                                 mutex_init(csp->lo_mutex, NULL,
1820                                     MUTEX_DRIVER, csp->lo_iblk);
1821                                 cv_init(csp->lo_cv, NULL,
1822                                     CV_DRIVER, NULL);
1823                                 csp->unclaimed_count = 0;
1824 
1825                                 err = ddi_add_intr(csp->ssp->dip, csp->chno,
1826                                     &csp->lo_iblk, NULL,
1827                                     bscbus_hwintr, (caddr_t)csp);
1828                                 if (err != DDI_SUCCESS) {
1829                                         cv_destroy(csp->lo_cv);
1830                                         mutex_destroy(csp->lo_mutex);
1831                                         goto failed2;
1832                                 }
1833                         }
1834                 }
1835                 /*
1836                  * The channel is now live and may
1837                  * receive interrupts
1838                  */
1839         } else if (csp->map_dog != map_dog) {
1840                 bscbus_trace(csp, 'C', "bscbus_claim_channel",
1841                     "request conflicts with previous mapping. old %x, new %x.",
1842                     csp->map_dog, map_dog);
1843                 goto failed1;
1844         }
1845         mutex_exit(csp->ssp->ch_mutex);
1846         return (1);
1847 
1848 failed2:
1849         /* unmap regs for failed channel */
1850         if (csp->ssp->per_channel_regs == B_TRUE) {
1851                 ddi_regs_map_free(&csp->ch_handle);
1852         }
1853         csp->ch_handle = NULL;
1854         csp->ch_regs = (void *)NULL;
1855 failed1:
1856         csp->map_count--;
1857         mutex_exit(csp->ssp->ch_mutex);
1858         return (0);
1859 }
1860 
1861 static void
1862 bscbus_release_channel(struct bscbus_channel_state *csp)
1863 {
1864         mutex_enter(csp->ssp->ch_mutex);
1865         if (csp->map_count == 1) {
1866                 /* No-one is now using this channel - shutdown channel */
1867                 bscbus_trace(csp, 'C', "bscbus_release_channel",
1868                     "shutdown channel %d, count %d",
1869                     csp->chno, csp->map_count);
1870 
1871                 if (csp->map_dog == 0) {
1872                         ASSERT(!ddi_intr_hilevel(csp->ssp->dip, csp->chno));
1873                         ddi_remove_intr(csp->ssp->dip, csp->chno, csp->lo_iblk);
1874                 }
1875                 cv_destroy(csp->lo_cv);
1876                 mutex_destroy(csp->lo_mutex);
1877                 mutex_destroy(csp->dog_mutex);
1878                 bscbus_hw_reset(csp);
1879 
1880                 /* unmap registers if using the new register scheme */
1881                 if (csp->ssp->per_channel_regs == B_TRUE) {
1882                         ddi_regs_map_free(&csp->ch_handle);
1883                 }
1884                 csp->ch_handle = NULL;
1885                 csp->ch_regs = (void *)NULL;
1886         }
1887         csp->map_count--;
1888         bscbus_trace(csp, 'C', "bscbus_release_channel",
1889             "release channel %d, count %d",
1890             csp->chno, csp->map_count);
1891         mutex_exit(csp->ssp->ch_mutex);
1892 }
1893 
1894 
1895 /*
1896  *  Nexus routines
1897  */
1898 
1899 #if     defined(NDI_ACC_HDL_V2)
1900 
1901 static const ndi_acc_fns_t bscbus_vreg_acc_fns = {
1902         NDI_ACC_FNS_CURRENT,
1903         NDI_ACC_FNS_V1,
1904 
1905         bscbus_vreg_get8,
1906         bscbus_vreg_put8,
1907         bscbus_vreg_rep_get8,
1908         bscbus_vreg_rep_put8,
1909 
1910         bscbus_no_get16,
1911         bscbus_no_put16,
1912         bscbus_no_rep_get16,
1913         bscbus_no_rep_put16,
1914 
1915         bscbus_meta_get32,
1916         bscbus_meta_put32,
1917         bscbus_meta_rep_get32,
1918         bscbus_meta_rep_put32,
1919 
1920         bscbus_no_get64,
1921         bscbus_no_put64,
1922         bscbus_no_rep_get64,
1923         bscbus_no_rep_put64,
1924 
1925         bscbus_acc_fault_check
1926 };
1927 
1928 static const ndi_acc_fns_t bscbus_pat_acc_fns = {
1929         NDI_ACC_FNS_CURRENT,
1930         NDI_ACC_FNS_V1,
1931 
1932         bscbus_pat_get8,
1933         bscbus_pat_put8,
1934         bscbus_pat_rep_get8,
1935         bscbus_pat_rep_put8,
1936 
1937         bscbus_no_get16,
1938         bscbus_no_put16,
1939         bscbus_no_rep_get16,
1940         bscbus_no_rep_put16,
1941 
1942         bscbus_meta_get32,
1943         bscbus_meta_put32,
1944         bscbus_meta_rep_get32,
1945         bscbus_meta_rep_put32,
1946 
1947         bscbus_no_get64,
1948         bscbus_no_put64,
1949         bscbus_no_rep_get64,
1950         bscbus_no_rep_put64,
1951 
1952         bscbus_acc_fault_check
1953 };
1954 
1955 static const ndi_acc_fns_t bscbus_event_acc_fns = {
1956         NDI_ACC_FNS_CURRENT,
1957         NDI_ACC_FNS_V1,
1958 
1959         bscbus_no_get8,
1960         bscbus_no_put8,
1961         bscbus_no_rep_get8,
1962         bscbus_no_rep_put8,
1963 
1964         bscbus_event_get16,
1965         bscbus_event_put16,
1966         bscbus_event_rep_get16,
1967         bscbus_event_rep_put16,
1968 
1969         bscbus_meta_get32,
1970         bscbus_meta_put32,
1971         bscbus_meta_rep_get32,
1972         bscbus_meta_rep_put32,
1973 
1974         bscbus_no_get64,
1975         bscbus_no_put64,
1976         bscbus_no_rep_get64,
1977         bscbus_no_rep_put64,
1978 
1979         bscbus_acc_fault_check
1980 };
1981 
1982 static int
1983 bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
1984         int space, caddr_t vaddr, off_t len,
1985         ndi_acc_handle_t *hdlp, caddr_t *addrp)
1986 {
1987         switch (op) {
1988         default:
1989                 return (DDI_ME_UNIMPLEMENTED);
1990 
1991         case DDI_MO_MAP_LOCKED:
1992                 if (bscbus_claim_channel(csp,
1993                     (space == LOMBUS_PAT_SPACE)) == 0) {
1994                         return (DDI_ME_GENERIC);
1995                 }
1996 
1997                 switch (space) {
1998                 default:
1999                         return (DDI_ME_REGSPEC_RANGE);
2000 
2001                 case LOMBUS_VREG_SPACE:
2002                         ndi_set_acc_fns(hdlp, &bscbus_vreg_acc_fns);
2003                         break;
2004 
2005                 case LOMBUS_PAT_SPACE:
2006                         ndi_set_acc_fns(hdlp, &bscbus_pat_acc_fns);
2007                         break;
2008 
2009                 case LOMBUS_EVENT_SPACE:
2010                         ndi_set_acc_fns(hdlp, &bscbus_event_acc_fns);
2011                         break;
2012                 }
2013                 hdlp->ah_addr = *addrp = vaddr;
2014                 hdlp->ah_len = len;
2015                 hdlp->ah_bus_private = csp;
2016                 return (DDI_SUCCESS);
2017 
2018         case DDI_MO_UNMAP:
2019                 *addrp = NULL;
2020                 hdlp->ah_bus_private = NULL;
2021                 bscbus_release_channel(csp);
2022                 return (DDI_SUCCESS);
2023         }
2024 }
2025 
2026 #else
2027 
2028 static int
2029 bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
2030         int space, caddr_t vaddr, off_t len,
2031         ddi_acc_hdl_t *hdlp, caddr_t *addrp)
2032 {
2033         ddi_acc_impl_t *aip = hdlp->ah_platform_private;
2034 
2035         switch (op) {
2036         default:
2037                 return (DDI_ME_UNIMPLEMENTED);
2038 
2039         case DDI_MO_MAP_LOCKED:
2040                 if (bscbus_claim_channel(csp,
2041                     (space == LOMBUS_PAT_SPACE)) == 0) {
2042                         return (DDI_ME_GENERIC);
2043                 }
2044 
2045                 switch (space) {
2046                 default:
2047                         return (DDI_ME_REGSPEC_RANGE);
2048 
2049                 case LOMBUS_VREG_SPACE:
2050                         aip->ahi_get8 = bscbus_vreg_get8;
2051                         aip->ahi_put8 = bscbus_vreg_put8;
2052                         aip->ahi_rep_get8 = bscbus_vreg_rep_get8;
2053                         aip->ahi_rep_put8 = bscbus_vreg_rep_put8;
2054 
2055                         aip->ahi_get16 = bscbus_no_get16;
2056                         aip->ahi_put16 = bscbus_no_put16;
2057                         aip->ahi_rep_get16 = bscbus_no_rep_get16;
2058                         aip->ahi_rep_put16 = bscbus_no_rep_put16;
2059 
2060                         aip->ahi_get32 = bscbus_meta_get32;
2061                         aip->ahi_put32 = bscbus_meta_put32;
2062                         aip->ahi_rep_get32 = bscbus_meta_rep_get32;
2063                         aip->ahi_rep_put32 = bscbus_meta_rep_put32;
2064 
2065                         aip->ahi_get64 = bscbus_no_get64;
2066                         aip->ahi_put64 = bscbus_no_put64;
2067                         aip->ahi_rep_get64 = bscbus_no_rep_get64;
2068                         aip->ahi_rep_put64 = bscbus_no_rep_put64;
2069 
2070                         aip->ahi_fault_check = bscbus_acc_fault_check;
2071                         break;
2072 
2073                 case LOMBUS_PAT_SPACE:
2074                         aip->ahi_get8 = bscbus_pat_get8;
2075                         aip->ahi_put8 = bscbus_pat_put8;
2076                         aip->ahi_rep_get8 = bscbus_pat_rep_get8;
2077                         aip->ahi_rep_put8 = bscbus_pat_rep_put8;
2078 
2079                         aip->ahi_get16 = bscbus_no_get16;
2080                         aip->ahi_put16 = bscbus_no_put16;
2081                         aip->ahi_rep_get16 = bscbus_no_rep_get16;
2082                         aip->ahi_rep_put16 = bscbus_no_rep_put16;
2083 
2084                         aip->ahi_get32 = bscbus_meta_get32;
2085                         aip->ahi_put32 = bscbus_meta_put32;
2086                         aip->ahi_rep_get32 = bscbus_meta_rep_get32;
2087                         aip->ahi_rep_put32 = bscbus_meta_rep_put32;
2088 
2089                         aip->ahi_get64 = bscbus_no_get64;
2090                         aip->ahi_put64 = bscbus_no_put64;
2091                         aip->ahi_rep_get64 = bscbus_no_rep_get64;
2092                         aip->ahi_rep_put64 = bscbus_no_rep_put64;
2093 
2094                         aip->ahi_fault_check = bscbus_acc_fault_check;
2095                         break;
2096 
2097                 case LOMBUS_EVENT_SPACE:
2098                         aip->ahi_get8 = bscbus_no_get8;
2099                         aip->ahi_put8 = bscbus_no_put8;
2100                         aip->ahi_rep_get8 = bscbus_no_rep_get8;
2101                         aip->ahi_rep_put8 = bscbus_no_rep_put8;
2102 
2103                         aip->ahi_get16 = bscbus_event_get16;
2104                         aip->ahi_put16 = bscbus_event_put16;
2105                         aip->ahi_rep_get16 = bscbus_event_rep_get16;
2106                         aip->ahi_rep_put16 = bscbus_event_rep_put16;
2107 
2108                         aip->ahi_get32 = bscbus_meta_get32;
2109                         aip->ahi_put32 = bscbus_meta_put32;
2110                         aip->ahi_rep_get32 = bscbus_meta_rep_get32;
2111                         aip->ahi_rep_put32 = bscbus_meta_rep_put32;
2112 
2113                         aip->ahi_get64 = bscbus_no_get64;
2114                         aip->ahi_put64 = bscbus_no_put64;
2115                         aip->ahi_rep_get64 = bscbus_no_rep_get64;
2116                         aip->ahi_rep_put64 = bscbus_no_rep_put64;
2117 
2118                         aip->ahi_fault_check = bscbus_acc_fault_check;
2119                         break;
2120                 }
2121                 hdlp->ah_addr = *addrp = vaddr;
2122                 hdlp->ah_len = len;
2123                 hdlp->ah_bus_private = csp;
2124                 return (DDI_SUCCESS);
2125 
2126         case DDI_MO_UNMAP:
2127                 *addrp = NULL;
2128                 hdlp->ah_bus_private = NULL;
2129                 bscbus_release_channel(csp);
2130                 return (DDI_SUCCESS);
2131         }
2132 }
2133 
2134 #endif  /* NDI_ACC_HDL_V2 */
2135 
2136 static int
2137 bscbus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
2138         off_t off, off_t len, caddr_t *addrp)
2139 {
2140         struct bscbus_child_info *lcip;
2141         struct bscbus_state *ssp;
2142         lombus_regspec_t *rsp;
2143 
2144         if ((ssp = bscbus_getstate(dip, -1, "bscbus_map")) == NULL)
2145                 return (DDI_FAILURE);   /* this "can't happen" */
2146 
2147         /*
2148          * Validate mapping request ...
2149          */
2150 
2151         if (mp->map_flags != DDI_MF_KERNEL_MAPPING)
2152                 return (DDI_ME_UNSUPPORTED);
2153         if (mp->map_handlep == NULL)
2154                 return (DDI_ME_UNSUPPORTED);
2155         if (mp->map_type != DDI_MT_RNUMBER)
2156                 return (DDI_ME_UNIMPLEMENTED);
2157         if ((lcip = ddi_get_parent_data(rdip)) == NULL)
2158                 return (DDI_ME_INVAL);
2159         if ((rsp = lcip->rsp) == NULL)
2160                 return (DDI_ME_INVAL);
2161         if (mp->map_obj.rnumber >= lcip->nregs)
2162                 return (DDI_ME_RNUMBER_RANGE);
2163         rsp += mp->map_obj.rnumber;
2164         if (off < 0 || off >= rsp->lombus_size)
2165                 return (DDI_ME_INVAL);
2166         if (len == 0)
2167                 len = rsp->lombus_size-off;
2168         if (len < 0)
2169                 return (DDI_ME_INVAL);
2170         if (off+len < 0 || off+len > rsp->lombus_size)
2171                 return (DDI_ME_INVAL);
2172 
2173         return (bscbus_map_handle(
2174             &ssp->channel[LOMBUS_SPACE_TO_CHANNEL(rsp->lombus_space)],
2175             mp->map_op, LOMBUS_SPACE_TO_REGSET(rsp->lombus_space),
2176             VREG_TO_ADDR(rsp->lombus_base+off), len, mp->map_handlep, addrp));
2177 }
2178 
2179 
2180 static int
2181 bscbus_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op,
2182         void *arg, void *result)
2183 {
2184         struct bscbus_child_info *lcip;
2185         lombus_regspec_t *rsp;
2186         dev_info_t *cdip;
2187         char addr[32];
2188         uint_t nregs;
2189         uint_t rnum;
2190         int *regs;
2191         int limit;
2192         int err;
2193         int i;
2194 
2195         if (bscbus_getstate(dip, -1, "bscbus_ctlops") == NULL)
2196                 return (DDI_FAILURE);   /* this "can't happen" */
2197 
2198         switch (op) {
2199         default:
2200                 break;
2201 
2202         case DDI_CTLOPS_INITCHILD:
2203                 /*
2204                  * First, look up and validate the "reg" property.
2205                  *
2206                  * It must be a non-empty integer array containing a set
2207                  * of triples.  Once we've verified that, we can treat it
2208                  * as an array of type lombus_regspec_t[], which defines
2209                  * the meaning of the elements of each triple:
2210                  * +  the first element of each triple must be a valid space
2211                  * +  the second and third elements (base, size) of each
2212                  *      triple must define a valid subrange of that space
2213                  * If it passes all the tests, we save it away for future
2214                  * reference in the child's parent-private-data field.
2215                  */
2216                 cdip = arg;
2217                 err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
2218                     DDI_PROP_DONTPASS, "reg", &regs, &nregs);
2219                 if (err != DDI_PROP_SUCCESS)
2220                         return (DDI_FAILURE);
2221 
2222                 err = (nregs <= 0 || (nregs % LOMBUS_REGSPEC_SIZE) != 0);
2223                 nregs /= LOMBUS_REGSPEC_SIZE;
2224                 rsp = (lombus_regspec_t *)regs;
2225                 for (i = 0; i < nregs && !err; ++i) {
2226                         switch (LOMBUS_SPACE_TO_REGSET(rsp[i].lombus_space)) {
2227                         default:
2228                                 limit = 0;
2229                                 err = 1;
2230                                 cmn_err(CE_WARN,
2231                                     "child(%p): unknown reg space %d",
2232                                     (void *)cdip, rsp[i].lombus_space);
2233                                 break;
2234 
2235                         case LOMBUS_VREG_SPACE:
2236                                 limit = LOMBUS_MAX_REG+1;
2237                                 break;
2238 
2239                         case LOMBUS_PAT_SPACE:
2240                                 limit = LOMBUS_PAT_REG+1;
2241                                 break;
2242 
2243                         case LOMBUS_EVENT_SPACE:
2244                                 limit = LOMBUS_EVENT_REG+1;
2245                                 break;
2246                         }
2247 
2248                         err |= (rsp[i].lombus_base < 0);
2249                         err |= (rsp[i].lombus_base >= limit);
2250 
2251                         if (rsp[i].lombus_size == 0)
2252                                 rsp[i].lombus_size = limit-rsp[i].lombus_base;
2253 
2254                         err |= (rsp[i].lombus_size < 0);
2255                         err |= (rsp[i].lombus_base+rsp[i].lombus_size < 0);
2256                         err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
2257 
2258                         err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
2259 
2260                 }
2261 
2262                 if (err) {
2263                         ddi_prop_free(regs);
2264                         return (DDI_FAILURE);
2265                 }
2266 
2267                 lcip = kmem_zalloc(sizeof (*lcip), KM_SLEEP);
2268                 lcip->nregs = nregs;
2269                 lcip->rsp = rsp;
2270                 ddi_set_parent_data(cdip, lcip);
2271 
2272                 (void) snprintf(addr, sizeof (addr),
2273                     "%x,%x", rsp[0].lombus_space, rsp[0].lombus_base);
2274                 ddi_set_name_addr(cdip, addr);
2275 
2276                 return (DDI_SUCCESS);
2277 
2278         case DDI_CTLOPS_UNINITCHILD:
2279                 cdip = arg;
2280                 ddi_set_name_addr(cdip, NULL);
2281                 lcip = ddi_get_parent_data(cdip);
2282                 ddi_set_parent_data(cdip, NULL);
2283                 ddi_prop_free(lcip->rsp);
2284                 kmem_free(lcip, sizeof (*lcip));
2285                 return (DDI_SUCCESS);
2286 
2287         case DDI_CTLOPS_REPORTDEV:
2288                 if (rdip == NULL)
2289                         return (DDI_FAILURE);
2290 
2291                 cmn_err(CE_CONT, "?BSC device: %s@%s, %s#%d\n",
2292                     ddi_node_name(rdip), ddi_get_name_addr(rdip),
2293                     ddi_driver_name(dip), ddi_get_instance(dip));
2294 
2295                 return (DDI_SUCCESS);
2296 
2297         case DDI_CTLOPS_REGSIZE:
2298                 if ((lcip = ddi_get_parent_data(rdip)) == NULL)
2299                         return (DDI_FAILURE);
2300                 if ((rnum = *(uint_t *)arg) >= lcip->nregs)
2301                         return (DDI_FAILURE);
2302                 *(off_t *)result = lcip->rsp[rnum].lombus_size;
2303                 return (DDI_SUCCESS);
2304 
2305         case DDI_CTLOPS_NREGS:
2306                 if ((lcip = ddi_get_parent_data(rdip)) == NULL)
2307                         return (DDI_FAILURE);
2308                 *(int *)result = lcip->nregs;
2309                 return (DDI_SUCCESS);
2310         }
2311 
2312         return (ddi_ctlops(dip, rdip, op, arg, result));
2313 }
2314 
2315 
2316 /*
2317  * This nexus does not support passing interrupts to leaf drivers, so
2318  * all the intrspec-related operations just fail as cleanly as possible.
2319  */
2320 
2321 /*ARGSUSED*/
2322 static int
2323 bscbus_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
2324     ddi_intr_handle_impl_t *hdlp, void *result)
2325 {
2326 #if defined(__sparc)
2327         return (i_ddi_intr_ops(dip, rdip, op, hdlp, result));
2328 #else
2329         _NOTE(ARGUNUSED(dip, rdip, op, hdlp, result))
2330         return (DDI_FAILURE);
2331 #endif
2332 }
2333 
2334 /*
2335  *  Clean up on detach or failure of attach
2336  */
2337 static int
2338 bscbus_unattach(struct bscbus_state *ssp, int instance)
2339 {
2340         int chno;
2341 
2342         if (ssp != NULL) {
2343                 for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
2344                         ASSERT(ssp->channel[chno].map_count == 0);
2345                 }
2346                 bscbus_offline(ssp);
2347                 ddi_set_driver_private(ssp->dip, NULL);
2348                 mutex_destroy(ssp->ch_mutex);
2349         }
2350 #ifdef BSCBUS_LOGSTATUS
2351         if (ssp->cmd_log_size != 0) {
2352                 kmem_free(ssp->cmd_log,
2353                     ssp->cmd_log_size * sizeof (bsc_cmd_log_t));
2354         }
2355 #endif /* BSCBUS_LOGSTATUS */
2356 
2357 
2358         ddi_soft_state_free(bscbus_statep, instance);
2359         return (DDI_FAILURE);
2360 }
2361 
2362 /*
2363  *  Autoconfiguration routines
2364  */
2365 
2366 static int
2367 bscbus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2368 {
2369         struct bscbus_state *ssp = NULL;
2370         int chno;
2371         int instance;
2372         int err;
2373 
2374         switch (cmd) {
2375         default:
2376                 return (DDI_FAILURE);
2377 
2378         case DDI_ATTACH:
2379                 break;
2380         }
2381 
2382         /*
2383          *  Allocate the soft-state structure
2384          */
2385         instance = ddi_get_instance(dip);
2386         if (ddi_soft_state_zalloc(bscbus_statep, instance) != DDI_SUCCESS)
2387                 return (DDI_FAILURE);
2388         if ((ssp = bscbus_getstate(dip, instance, "bscbus_attach")) == NULL)
2389                 return (bscbus_unattach(ssp, instance));
2390         ddi_set_driver_private(dip, ssp);
2391 
2392         /*
2393          *  Initialise devinfo-related fields
2394          */
2395         ssp->dip = dip;
2396         ssp->majornum = ddi_driver_major(dip);
2397         ssp->instance = instance;
2398 
2399         /*
2400          *  Set various options from .conf properties
2401          */
2402         ssp->debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2403             DDI_PROP_DONTPASS, "debug", 0);
2404 
2405         mutex_init(ssp->ch_mutex, NULL, MUTEX_DRIVER, NULL);
2406 
2407 #ifdef BSCBUS_LOGSTATUS
2408         ssp->cmd_log_size = bscbus_cmd_log_size;
2409         if (ssp->cmd_log_size != 0) {
2410                 ssp->cmd_log_idx = 0;
2411                 ssp->cmd_log = kmem_zalloc(ssp->cmd_log_size *
2412                     sizeof (bsc_cmd_log_t), KM_SLEEP);
2413         }
2414 #endif /* BSCBUS_LOGSTATUS */
2415 
2416         /*
2417          *  Online the hardware ...
2418          */
2419         err = bscbus_online(ssp);
2420         if (err != 0)
2421                 return (bscbus_unattach(ssp, instance));
2422 
2423         for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
2424                 struct bscbus_channel_state *csp = &ssp->channel[chno];
2425 
2426                 /*
2427                  * Initialise state
2428                  * The hardware/interrupts are setup at map time to
2429                  * avoid claiming hardware that OBP is using
2430                  */
2431                 csp->ssp = ssp;
2432                 csp->chno = chno;
2433                 csp->map_count = 0;
2434                 csp->map_dog = B_FALSE;
2435         }
2436 
2437         /*
2438          *  All done, report success
2439          */
2440         ddi_report_dev(dip);
2441         return (DDI_SUCCESS);
2442 }
2443 
2444 static int
2445 bscbus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2446 {
2447         struct bscbus_state *ssp;
2448         int instance;
2449 
2450         switch (cmd) {
2451         default:
2452                 return (DDI_FAILURE);
2453 
2454         case DDI_DETACH:
2455                 break;
2456         }
2457 
2458         instance = ddi_get_instance(dip);
2459         if ((ssp = bscbus_getstate(dip, instance, "bscbus_detach")) == NULL)
2460                 return (DDI_FAILURE);   /* this "can't happen" */
2461 
2462         (void) bscbus_unattach(ssp, instance);
2463         return (DDI_SUCCESS);
2464 }
2465 
2466 static int
2467 bscbus_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
2468 {
2469         struct bscbus_state *ssp;
2470         int chno;
2471 
2472         _NOTE(ARGUNUSED(cmd))
2473 
2474         if ((ssp = bscbus_getstate(dip, -1, "bscbus_reset")) == NULL)
2475                 return (DDI_FAILURE);
2476 
2477         for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
2478                 bscbus_hw_reset(&ssp->channel[chno]);
2479         }
2480         return (DDI_SUCCESS);
2481 }
2482 
2483 
2484 /*
2485  * System interface structures
2486  */
2487 
2488 static struct cb_ops bscbus_cb_ops =
2489 {
2490         nodev,                  /* b/c open     */
2491         nodev,                  /* b/c close    */
2492         nodev,                  /* b   strategy */
2493         nodev,                  /* b   print    */
2494         nodev,                  /* b   dump     */
2495         nodev,                  /* c   read     */
2496         nodev,                  /* c   write    */
2497         nodev,                  /* c   ioctl    */
2498         nodev,                  /* c   devmap   */
2499         nodev,                  /* c   mmap     */
2500         nodev,                  /* c   segmap   */
2501         nochpoll,               /* c   poll     */
2502         ddi_prop_op,            /* b/c prop_op  */
2503         NULL,                   /* c   streamtab */
2504         D_MP | D_NEW            /* b/c flags    */
2505 };
2506 
2507 static struct bus_ops bscbus_bus_ops =
2508 {
2509         BUSO_REV,                       /* revision             */
2510         bscbus_map,                     /* bus_map              */
2511         0,                              /* get_intrspec         */
2512         0,                              /* add_intrspec         */
2513         0,                              /* remove_intrspec      */
2514         i_ddi_map_fault,                /* map_fault            */
2515         ddi_no_dma_map,                 /* dma_map              */
2516         ddi_no_dma_allochdl,            /* allocate DMA handle  */
2517         ddi_no_dma_freehdl,             /* free DMA handle      */
2518         ddi_no_dma_bindhdl,             /* bind DMA handle      */
2519         ddi_no_dma_unbindhdl,           /* unbind DMA handle    */
2520         ddi_no_dma_flush,               /* flush DMA            */
2521         ddi_no_dma_win,                 /* move DMA window      */
2522         ddi_no_dma_mctl,                /* generic DMA control  */
2523         bscbus_ctlops,                  /* generic control      */
2524         ddi_bus_prop_op,                /* prop_op              */
2525         ndi_busop_get_eventcookie,      /* get_eventcookie      */
2526         ndi_busop_add_eventcall,        /* add_eventcall        */
2527         ndi_busop_remove_eventcall,     /* remove_eventcall     */
2528         ndi_post_event,                 /* post_event           */
2529         0,                              /* interrupt control    */
2530         0,                              /* bus_config           */
2531         0,                              /* bus_unconfig         */
2532         0,                              /* bus_fm_init          */
2533         0,                              /* bus_fm_fini          */
2534         0,                              /* bus_fm_access_enter  */
2535         0,                              /* bus_fm_access_exit   */
2536         0,                              /* bus_power            */
2537         bscbus_intr_op                  /* bus_intr_op          */
2538 };
2539 
2540 static struct dev_ops bscbus_dev_ops =
2541 {
2542         DEVO_REV,
2543         0,                              /* refcount             */
2544         ddi_no_info,                    /* getinfo              */
2545         nulldev,                        /* identify             */
2546         nulldev,                        /* probe                */
2547         bscbus_attach,                  /* attach               */
2548         bscbus_detach,                  /* detach               */
2549         bscbus_reset,                   /* reset                */
2550         &bscbus_cb_ops,                     /* driver operations    */
2551         &bscbus_bus_ops,            /* bus operations       */
2552         NULL,                           /* power                */
2553         ddi_quiesce_not_needed,                 /* quiesce              */
2554 };
2555 
2556 static struct modldrv modldrv =
2557 {
2558         &mod_driverops,
2559         "bscbus driver",
2560         &bscbus_dev_ops
2561 };
2562 
2563 static struct modlinkage modlinkage =
2564 {
2565         MODREV_1,
2566         {
2567                 &modldrv,
2568                 NULL
2569         }
2570 };
2571 
2572 
2573 /*
2574  *  Dynamic loader interface code
2575  */
2576 
2577 int
2578 _init(void)
2579 {
2580         int err;
2581 
2582         err = ddi_soft_state_init(&bscbus_statep,
2583             sizeof (struct bscbus_state), 0);
2584         if (err == DDI_SUCCESS)
2585                 if ((err = mod_install(&modlinkage)) != DDI_SUCCESS) {
2586                         ddi_soft_state_fini(&bscbus_statep);
2587                 }
2588 
2589         return (err);
2590 }
2591 
2592 int
2593 _info(struct modinfo *mip)
2594 {
2595         return (mod_info(&modlinkage, mip));
2596 }
2597 
2598 int
2599 _fini(void)
2600 {
2601         int err;
2602 
2603         if ((err = mod_remove(&modlinkage)) == DDI_SUCCESS) {
2604                 ddi_soft_state_fini(&bscbus_statep);
2605                 bscbus_major = NOMAJOR;
2606         }
2607 
2608         return (err);
2609 }
2610 
2611 #ifdef BSCBUS_LOGSTATUS
2612 void bscbus_cmd_log(struct bscbus_channel_state *csp, bsc_cmd_stamp_t cat,
2613     uint8_t status, uint8_t data)
2614 {
2615         int idx;
2616         bsc_cmd_log_t *logp;
2617         struct bscbus_state *ssp;
2618 
2619         if ((csp) == NULL)
2620                 return;
2621         if ((ssp = (csp)->ssp) == NULL)
2622                 return;
2623         if (ssp->cmd_log_size == 0)
2624                 return;
2625         if ((bscbus_cmd_log_flags & (1 << cat)) == 0)
2626                 return;
2627         idx = atomic_inc_32_nv(&ssp->cmd_log_idx);
2628         logp = &ssp->cmd_log[idx % ssp->cmd_log_size];
2629         logp->bcl_seq = idx;
2630         logp->bcl_cat = cat;
2631         logp->bcl_now = gethrtime();
2632         logp->bcl_chno = csp->chno;
2633         logp->bcl_cmdstate = csp->cmdstate;
2634         logp->bcl_status = status;
2635         logp->bcl_data = data;
2636 }
2637 #endif /* BSCBUS_LOGSTATUS */