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