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 2008 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 clock_t tick; 931 uint8_t status; 932 933 /* 934 * First of all, wait for the interface to be available. 935 * 936 * NOTE: we blow through all the mutex/cv/state checking and 937 * preempt any command in progress if the system is panicking! 938 */ 939 csp = HANDLE_PRIVATE(hdlp); 940 mutex_enter(csp->lo_mutex); 941 while (csp->cmdstate != BSCBUS_CMDSTATE_IDLE && !ddi_in_panic()) 942 cv_wait(csp->lo_cv, csp->lo_mutex); 943 944 csp->cmdstate = BSCBUS_CMDSTATE_BUSY; 945 csp->sequence = (csp->sequence + BSCBUS_SEQ_LSB) & BSCBUS_SEQ; 946 947 /* 948 * We have exclusive ownership, so assemble the command (backwards): 949 * 950 * [byte 0] Command: modified by XADDR and/or WMSB bits 951 * [Optional] Parameter: Value to write (low 7 bits) 952 * [Optional] Parameter: Register number (high 7 bits) 953 * [Optional] Parameter: Register number (low 7 bits) 954 */ 955 csp->cmdp = &csp->cmdbuf[0]; 956 *csp->cmdp++ = BSCBUS_CMD | csp->sequence | cmd; 957 switch (cmd) { 958 case BSCBUS_CMD_WRITE: 959 *csp->cmdp++ = val & 0x7f; 960 if (val >= 0x80) 961 csp->cmdbuf[0] |= BSCBUS_CMD_WMSB; 962 /*FALLTHRU*/ 963 case BSCBUS_CMD_READ: 964 if (BSCBUS_VREG_HI(vreg) != 0) { 965 *csp->cmdp++ = BSCBUS_VREG_HI(vreg); 966 csp->cmdbuf[0] |= BSCBUS_CMD_XADDR; 967 } 968 *csp->cmdp++ = BSCBUS_VREG_LO(vreg); 969 /*FALLTHRU*/ 970 case BSCBUS_CMD_NOP: 971 break; 972 } 973 974 /* 975 * Check and update the H8 h/w fault status before accessing 976 * the chip registers. If there's a (new or previous) fault, 977 * we'll run through the protocol but won't really touch the 978 * hardware and all commands will timeout. If a previously 979 * discovered fault has now gone away (!), then we can (try to) 980 * proceed with the new command (probably a probe). 981 */ 982 bscbus_check_fault_status(csp); 983 984 /* 985 * Prepare for the command (to be processed by the interrupt 986 * handler and/or polling loop below), and wait for a response 987 * or timeout. 988 */ 989 start = ddi_get_lbolt(); 990 csp->deadline = start + drv_usectohz(LOMBUS_CMD_TIMEOUT/1000); 991 csp->error = 0; 992 csp->index = 0; 993 csp->result = DUMMY_VALUE; 994 995 status = bscbus_get_reg(csp, H8_STR); 996 if (status & H8_STR_BUSY) { 997 bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0xfd); 998 /* 999 * Must ensure that the busy state has cleared before 1000 * sending the command 1001 */ 1002 csp->cmdstate = BSCBUS_CMDSTATE_CLEARING; 1003 bscbus_trace(csp, 'P', "bscbus_cmd", 1004 "h8 reporting status (%x) busy - clearing", status); 1005 } else { 1006 /* It is clear to send the command immediately */ 1007 csp->cmdstate = BSCBUS_CMDSTATE_SENDING; 1008 bscbus_trace(csp, 'P', "bscbus_cmd", 1009 "sending first byte of command, status %x", status); 1010 bscbus_poll(csp); 1011 } 1012 1013 csp->poll_hz = drv_usectohz( 1014 (csp->interrupt_failed ? 1015 BSCBUS_CMD_POLLNOINTS : BSCBUS_CMD_POLL) / 1000); 1016 1017 while ((csp->cmdstate != BSCBUS_CMDSTATE_READY) && 1018 (csp->cmdstate != BSCBUS_CMDSTATE_ERROR)) { 1019 ASSERT(csp->cmdstate != BSCBUS_CMDSTATE_IDLE); 1020 1021 tick = ddi_get_lbolt() + csp->poll_hz; 1022 if ((cv_timedwait(csp->lo_cv, csp->lo_mutex, tick) == -1) && 1023 csp->cmdstate != BSCBUS_CMDSTATE_READY && 1024 csp->cmdstate != BSCBUS_CMDSTATE_ERROR) { 1025 if (!csp->interrupt_failed) { 1026 bscbus_trace(csp, 'I', "bscbus_cmd:", 1027 "interrupt_failed channel %d", csp->chno); 1028 csp->interrupt_failed = B_TRUE; 1029 csp->poll_hz = drv_usectohz( 1030 BSCBUS_CMD_POLLNOINTS / 1000); 1031 } 1032 bscbus_poll(csp); 1033 } 1034 } 1035 1036 /* 1037 * The return value may not be meaningful but retrieve it anyway 1038 */ 1039 val = csp->result; 1040 if (bscbus_faulty(csp)) { 1041 val = DUMMY_VALUE; 1042 HANDLE_FAULT(hdlp) = LOMBUS_ERR_SIOHW; 1043 } else if (csp->cmdstate != BSCBUS_CMDSTATE_READY) { 1044 /* 1045 * Some problem here ... transfer the error code from 1046 * the per-instance state to the per-handle fault flag. 1047 * The error code shouldn't be zero! 1048 */ 1049 if (csp->error != 0) 1050 HANDLE_FAULT(hdlp) = csp->error; 1051 else 1052 HANDLE_FAULT(hdlp) = LOMBUS_ERR_BADERRCODE; 1053 } 1054 1055 /* 1056 * All done now! 1057 */ 1058 csp->index = 0; 1059 csp->cmdstate = BSCBUS_CMDSTATE_IDLE; 1060 cv_broadcast(csp->lo_cv); 1061 mutex_exit(csp->lo_mutex); 1062 1063 return (val); 1064 } 1065 1066 /* 1067 * Space 0 - LOM virtual register access 1068 * Only 8-bit accesses are supported. 1069 */ 1070 static uint8_t 1071 bscbus_vreg_get8(HANDLE_TYPE *hdlp, uint8_t *addr) 1072 { 1073 ptrdiff_t offset; 1074 1075 /* 1076 * Check the offset that the caller has added to the base address 1077 * against the length of the mapping originally requested. 1078 */ 1079 offset = ADDR_TO_OFFSET(addr, hdlp); 1080 if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) { 1081 /* 1082 * Invalid access - flag a fault and return a dummy value 1083 */ 1084 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM; 1085 return (DUMMY_VALUE); 1086 } 1087 1088 /* 1089 * Derive the virtual register number and run the command 1090 */ 1091 return (bscbus_cmd(hdlp, ADDR_TO_VREG(addr), 0, BSCBUS_CMD_READ)); 1092 } 1093 1094 static void 1095 bscbus_vreg_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val) 1096 { 1097 ptrdiff_t offset; 1098 1099 /* 1100 * Check the offset that the caller has added to the base address 1101 * against the length of the mapping originally requested. 1102 */ 1103 offset = ADDR_TO_OFFSET(addr, hdlp); 1104 if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) { 1105 /* 1106 * Invalid access - flag a fault and return 1107 */ 1108 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM; 1109 return; 1110 } 1111 1112 /* 1113 * Derive the virtual register number and run the command 1114 */ 1115 (void) bscbus_cmd(hdlp, ADDR_TO_VREG(addr), val, BSCBUS_CMD_WRITE); 1116 } 1117 1118 static void 1119 bscbus_vreg_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr, 1120 uint8_t *dev_addr, size_t repcount, uint_t flags) 1121 { 1122 size_t inc; 1123 1124 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0; 1125 for (; repcount--; dev_addr += inc) 1126 *host_addr++ = bscbus_vreg_get8(hdlp, dev_addr); 1127 } 1128 1129 static void 1130 bscbus_vreg_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr, 1131 uint8_t *dev_addr, size_t repcount, uint_t flags) 1132 { 1133 size_t inc; 1134 1135 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0; 1136 for (; repcount--; dev_addr += inc) 1137 bscbus_vreg_put8(hdlp, dev_addr, *host_addr++); 1138 } 1139 1140 1141 /* 1142 * Space 1 - LOM watchdog pat register access 1143 * Only 8-bit accesses are supported. 1144 * 1145 * Reads have no effect and return 0. 1146 * 1147 * Multi-byte reads (using ddi_rep_get8(9F)) are a fairly inefficient 1148 * way of zeroing the destination area ;-) and still won't pat the dog. 1149 * 1150 * Multi-byte writes (using ddi_rep_put8(9F)) will almost certainly 1151 * only count as a single pat, no matter how many bytes the caller 1152 * says to write, as the inter-pat time is VERY long compared with 1153 * the time it will take to read the memory source area. 1154 */ 1155 1156 static uint8_t 1157 bscbus_pat_get8(HANDLE_TYPE *hdlp, uint8_t *addr) 1158 { 1159 ptrdiff_t offset; 1160 1161 /* 1162 * Check the offset that the caller has added to the base address 1163 * against the length of the mapping originally requested. 1164 */ 1165 offset = ADDR_TO_OFFSET(addr, hdlp); 1166 if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) { 1167 /* 1168 * Invalid access - flag a fault and return a dummy value 1169 */ 1170 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM; 1171 return (DUMMY_VALUE); 1172 } 1173 1174 return (0); 1175 } 1176 1177 static void 1178 bscbus_pat_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val) 1179 { 1180 struct bscbus_channel_state *csp; 1181 ptrdiff_t offset; 1182 1183 /* 1184 * Check the offset that the caller has added to the base address 1185 * against the length of the mapping originally requested. 1186 */ 1187 offset = ADDR_TO_OFFSET(addr, hdlp); 1188 if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) { 1189 /* 1190 * Invalid access - flag a fault and return 1191 */ 1192 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM; 1193 return; 1194 } 1195 1196 csp = HANDLE_PRIVATE(hdlp); 1197 mutex_enter(csp->dog_mutex); 1198 bscbus_pat_dog(csp, val); 1199 mutex_exit(csp->dog_mutex); 1200 } 1201 1202 static void 1203 bscbus_pat_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr, 1204 uint8_t *dev_addr, size_t repcount, uint_t flags) 1205 { 1206 size_t inc; 1207 1208 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0; 1209 for (; repcount--; dev_addr += inc) 1210 *host_addr++ = bscbus_pat_get8(hdlp, dev_addr); 1211 } 1212 1213 static void 1214 bscbus_pat_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr, 1215 uint8_t *dev_addr, size_t repcount, uint_t flags) 1216 { 1217 size_t inc; 1218 1219 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0; 1220 for (; repcount--; dev_addr += inc) 1221 bscbus_pat_put8(hdlp, dev_addr, *host_addr++); 1222 } 1223 1224 1225 /* 1226 * Space 2 - LOM async event flag register access 1227 * Only 16-bit accesses are supported. 1228 */ 1229 static uint16_t 1230 bscbus_event_get16(HANDLE_TYPE *hdlp, uint16_t *addr) 1231 { 1232 struct bscbus_channel_state *csp; 1233 ptrdiff_t offset; 1234 1235 /* 1236 * Check the offset that the caller has added to the base address 1237 * against the length of the mapping orignally requested. 1238 */ 1239 offset = ADDR_TO_OFFSET(addr, hdlp); 1240 if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) { 1241 /* 1242 * Invalid access - flag a fault and return a dummy value 1243 */ 1244 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM; 1245 return (DUMMY_VALUE); 1246 } 1247 1248 /* 1249 * Return the value of the asynchronous-event-pending flag 1250 * as passed back by the LOM at the end of the last command. 1251 */ 1252 csp = HANDLE_PRIVATE(hdlp); 1253 return (csp->async); 1254 } 1255 1256 static void 1257 bscbus_event_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val) 1258 { 1259 ptrdiff_t offset; 1260 1261 _NOTE(ARGUNUSED(val)) 1262 1263 /* 1264 * Check the offset that the caller has added to the base address 1265 * against the length of the mapping originally requested. 1266 */ 1267 offset = ADDR_TO_OFFSET(addr, hdlp); 1268 if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) { 1269 /* 1270 * Invalid access - flag a fault and return 1271 */ 1272 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM; 1273 return; 1274 } 1275 1276 /* 1277 * The user can't overwrite the asynchronous-event-pending flag! 1278 */ 1279 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_RO; 1280 } 1281 1282 static void 1283 bscbus_event_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr, 1284 uint16_t *dev_addr, size_t repcount, uint_t flags) 1285 { 1286 size_t inc; 1287 1288 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0; 1289 for (; repcount--; dev_addr += inc) 1290 *host_addr++ = bscbus_event_get16(hdlp, dev_addr); 1291 } 1292 1293 static void 1294 bscbus_event_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr, 1295 uint16_t *dev_addr, size_t repcount, uint_t flags) 1296 { 1297 size_t inc; 1298 1299 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0; 1300 for (; repcount--; dev_addr += inc) 1301 bscbus_event_put16(hdlp, dev_addr, *host_addr++); 1302 } 1303 1304 1305 /* 1306 * All spaces - access handle fault information 1307 * Only 32-bit accesses are supported. 1308 */ 1309 static uint32_t 1310 bscbus_meta_get32(HANDLE_TYPE *hdlp, uint32_t *addr) 1311 { 1312 struct bscbus_channel_state *csp; 1313 ptrdiff_t offset; 1314 1315 /* 1316 * Derive the offset that the caller has added to the base 1317 * address originally returned, and use it to determine 1318 * which meta-register is to be accessed ... 1319 */ 1320 offset = ADDR_TO_OFFSET(addr, hdlp); 1321 switch (offset) { 1322 case LOMBUS_FAULT_REG: 1323 /* 1324 * This meta-register provides a code for the most 1325 * recent virtual register access fault, if any. 1326 */ 1327 return (HANDLE_FAULT(hdlp)); 1328 1329 case LOMBUS_PROBE_REG: 1330 /* 1331 * Reading this meta-register clears any existing fault 1332 * (at the virtual, not the hardware access layer), then 1333 * runs a NOP command and returns the fault code from that. 1334 */ 1335 HANDLE_FAULT(hdlp) = 0; 1336 (void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP); 1337 return (HANDLE_FAULT(hdlp)); 1338 1339 case LOMBUS_ASYNC_REG: 1340 /* 1341 * Obsolescent - but still supported for backwards 1342 * compatibility. This is an alias for the newer 1343 * LOMBUS_EVENT_REG, but doesn't require a separate 1344 * "reg" entry and ddi_regs_map_setup() call. 1345 * 1346 * It returns the value of the asynchronous-event-pending 1347 * flag as passed back by the BSC at the end of the last 1348 * completed command. 1349 */ 1350 csp = HANDLE_PRIVATE(hdlp); 1351 return (csp->async); 1352 1353 default: 1354 /* 1355 * Invalid access - flag a fault and return a dummy value 1356 */ 1357 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1358 return (DUMMY_VALUE); 1359 } 1360 } 1361 1362 static void 1363 bscbus_meta_put32(HANDLE_TYPE *hdlp, uint32_t *addr, uint32_t val) 1364 { 1365 ptrdiff_t offset; 1366 1367 /* 1368 * Derive the offset that the caller has added to the base 1369 * address originally returned, and use it to determine 1370 * which meta-register is to be accessed ... 1371 */ 1372 offset = ADDR_TO_OFFSET(addr, hdlp); 1373 switch (offset) { 1374 case LOMBUS_FAULT_REG: 1375 /* 1376 * This meta-register contains a code for the most 1377 * recent virtual register access fault, if any. 1378 * It can be cleared simply by writing 0 to it. 1379 */ 1380 HANDLE_FAULT(hdlp) = val; 1381 return; 1382 1383 case LOMBUS_PROBE_REG: 1384 /* 1385 * Writing this meta-register clears any existing fault 1386 * (at the virtual, not the hardware acess layer), then 1387 * runs a NOP command. The caller can check the fault 1388 * code later if required. 1389 */ 1390 HANDLE_FAULT(hdlp) = 0; 1391 (void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP); 1392 return; 1393 1394 default: 1395 /* 1396 * Invalid access - flag a fault 1397 */ 1398 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1399 return; 1400 } 1401 } 1402 1403 static void 1404 bscbus_meta_rep_get32(HANDLE_TYPE *hdlp, uint32_t *host_addr, 1405 uint32_t *dev_addr, size_t repcount, uint_t flags) 1406 { 1407 size_t inc; 1408 1409 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0; 1410 for (; repcount--; dev_addr += inc) 1411 *host_addr++ = bscbus_meta_get32(hdlp, dev_addr); 1412 } 1413 1414 static void 1415 bscbus_meta_rep_put32(HANDLE_TYPE *hdlp, uint32_t *host_addr, 1416 uint32_t *dev_addr, size_t repcount, uint_t flags) 1417 { 1418 size_t inc; 1419 1420 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0; 1421 for (; repcount--; dev_addr += inc) 1422 bscbus_meta_put32(hdlp, dev_addr, *host_addr++); 1423 } 1424 1425 1426 /* 1427 * Finally, some dummy functions for all unsupported access 1428 * space/size/mode combinations ... 1429 */ 1430 static uint8_t 1431 bscbus_no_get8(HANDLE_TYPE *hdlp, uint8_t *addr) 1432 { 1433 _NOTE(ARGUNUSED(addr)) 1434 1435 /* 1436 * Invalid access - flag a fault and return a dummy value 1437 */ 1438 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1439 return (DUMMY_VALUE); 1440 } 1441 1442 static void 1443 bscbus_no_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val) 1444 { 1445 _NOTE(ARGUNUSED(addr, val)) 1446 1447 /* 1448 * Invalid access - flag a fault 1449 */ 1450 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1451 } 1452 1453 static void 1454 bscbus_no_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr, 1455 uint8_t *dev_addr, size_t repcount, uint_t flags) 1456 { 1457 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags)) 1458 1459 /* 1460 * Invalid access - flag a fault 1461 */ 1462 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1463 } 1464 1465 static void 1466 bscbus_no_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr, 1467 uint8_t *dev_addr, size_t repcount, uint_t flags) 1468 { 1469 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags)) 1470 1471 /* 1472 * Invalid access - flag a fault 1473 */ 1474 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1475 } 1476 1477 static uint16_t 1478 bscbus_no_get16(HANDLE_TYPE *hdlp, uint16_t *addr) 1479 { 1480 _NOTE(ARGUNUSED(addr)) 1481 1482 /* 1483 * Invalid access - flag a fault and return a dummy value 1484 */ 1485 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1486 return (DUMMY_VALUE); 1487 } 1488 1489 static void 1490 bscbus_no_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val) 1491 { 1492 _NOTE(ARGUNUSED(addr, val)) 1493 1494 /* 1495 * Invalid access - flag a fault 1496 */ 1497 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1498 } 1499 1500 static void 1501 bscbus_no_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr, 1502 uint16_t *dev_addr, size_t repcount, uint_t flags) 1503 { 1504 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags)) 1505 1506 /* 1507 * Invalid access - flag a fault 1508 */ 1509 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1510 } 1511 1512 static void 1513 bscbus_no_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr, 1514 uint16_t *dev_addr, size_t repcount, uint_t flags) 1515 { 1516 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags)) 1517 1518 /* 1519 * Invalid access - flag a fault 1520 */ 1521 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1522 } 1523 1524 static uint64_t 1525 bscbus_no_get64(HANDLE_TYPE *hdlp, uint64_t *addr) 1526 { 1527 _NOTE(ARGUNUSED(addr)) 1528 1529 /* 1530 * Invalid access - flag a fault and return a dummy value 1531 */ 1532 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1533 return (DUMMY_VALUE); 1534 } 1535 1536 static void 1537 bscbus_no_put64(HANDLE_TYPE *hdlp, uint64_t *addr, uint64_t val) 1538 { 1539 _NOTE(ARGUNUSED(addr, val)) 1540 1541 /* 1542 * Invalid access - flag a fault 1543 */ 1544 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1545 } 1546 1547 static void 1548 bscbus_no_rep_get64(HANDLE_TYPE *hdlp, uint64_t *host_addr, 1549 uint64_t *dev_addr, size_t repcount, uint_t flags) 1550 { 1551 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags)) 1552 1553 /* 1554 * Invalid access - flag a fault 1555 */ 1556 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1557 } 1558 1559 static void 1560 bscbus_no_rep_put64(HANDLE_TYPE *hdlp, uint64_t *host_addr, 1561 uint64_t *dev_addr, size_t repcount, uint_t flags) 1562 { 1563 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags)) 1564 1565 /* 1566 * Invalid access - flag a fault 1567 */ 1568 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE; 1569 } 1570 1571 static int 1572 bscbus_acc_fault_check(HANDLE_TYPE *hdlp) 1573 { 1574 return (HANDLE_FAULT(hdlp) != 0); 1575 } 1576 1577 /* 1578 * Hardware setup - ensure that there are no pending transactions and 1579 * hence no pending interrupts. We do this be ensuring that the BSC is 1580 * not reporting a busy condition and that it does not have any data 1581 * pending in its output buffer. 1582 * This is important because if we have pending interrupts at attach 1583 * time Solaris will hang due to bugs in ddi_get_iblock_cookie. 1584 */ 1585 static void 1586 bscbus_hw_reset(struct bscbus_channel_state *csp) 1587 { 1588 int64_t timeout; 1589 uint8_t status; 1590 1591 if (csp->map_count == 0) { 1592 /* No-one using this instance - no need to reset hardware */ 1593 return; 1594 } 1595 1596 bscbus_trace(csp, 'R', "bscbus_hw_reset", 1597 "resetting channel %d", csp->chno); 1598 1599 status = bscbus_get_reg(csp, H8_STR); 1600 if (status & H8_STR_BUSY) { 1601 /* 1602 * Give the h8 time to complete a reply. 1603 * In practice we should never worry about this 1604 * because whenever we get here it will have been 1605 * long enough for the h8 to complete a reply 1606 */ 1607 bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0); 1608 bscbus_trace(csp, 'R', "bscbus_hw_reset", 1609 "h8 reporting status (%x) busy - waiting", status); 1610 if (ddi_in_panic()) { 1611 drv_usecwait(BSCBUS_HWRESET_POLL/1000); 1612 } else { 1613 delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000)); 1614 } 1615 } 1616 /* Reply should be completed by now. Try to clear busy status */ 1617 status = bscbus_get_reg(csp, H8_STR); 1618 if (status & (H8_STR_BUSY | H8_STR_OBF)) { 1619 bscbus_trace(csp, 'R', "bscbus_hw_reset", 1620 "clearing busy status for channel %d", csp->chno); 1621 1622 for (timeout = BSCBUS_HWRESET_TIMEOUT; 1623 (timeout > 0); 1624 timeout -= BSCBUS_HWRESET_POLL) { 1625 if (status & H8_STR_OBF) { 1626 (void) bscbus_get_reg(csp, H8_ODR); 1627 if (!(status & H8_STR_BUSY)) { 1628 /* We are done */ 1629 break; 1630 } 1631 } 1632 if (ddi_in_panic()) { 1633 drv_usecwait(BSCBUS_HWRESET_POLL/1000); 1634 } else { 1635 delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000)); 1636 } 1637 status = bscbus_get_reg(csp, H8_STR); 1638 } 1639 if (timeout <= 0) { 1640 cmn_err(CE_WARN, "bscbus_hw_reset: timed out " 1641 "clearing busy status"); 1642 } 1643 } 1644 /* 1645 * We read ODR just in case there is a pending interrupt with 1646 * no data. This is potentially dangerous because we could get 1647 * out of sync due to race conditions BUT at this point the 1648 * channel should be idle so it is safe. 1649 */ 1650 (void) bscbus_get_reg(csp, H8_ODR); 1651 } 1652 1653 /* 1654 * Higher-level setup & teardown 1655 */ 1656 1657 static void 1658 bscbus_offline(struct bscbus_state *ssp) 1659 { 1660 if (ssp->h8_handle != NULL) 1661 ddi_regs_map_free(&ssp->h8_handle); 1662 ssp->h8_handle = NULL; 1663 ssp->h8_regs = NULL; 1664 } 1665 1666 static int 1667 bscbus_online(struct bscbus_state *ssp) 1668 { 1669 ddi_acc_handle_t h; 1670 caddr_t p; 1671 int nregs; 1672 int err; 1673 1674 ssp->h8_handle = NULL; 1675 ssp->h8_regs = (void *)NULL; 1676 ssp->per_channel_regs = B_FALSE; 1677 1678 if (ddi_dev_nregs(ssp->dip, &nregs) != DDI_SUCCESS) 1679 nregs = 0; 1680 1681 switch (nregs) { 1682 case 1: 1683 /* 1684 * regset 0 represents the H8 interface registers 1685 */ 1686 err = ddi_regs_map_setup(ssp->dip, 0, &p, 0, 0, 1687 bscbus_dev_acc_attr, &h); 1688 if (err != DDI_SUCCESS) 1689 return (EIO); 1690 1691 ssp->h8_handle = h; 1692 ssp->h8_regs = (void *)p; 1693 break; 1694 1695 case 0: 1696 /* 1697 * If no registers are defined, succeed vacuously; 1698 * commands will be accepted, but we fake the accesses. 1699 */ 1700 break; 1701 1702 default: 1703 /* 1704 * Remember that we are using the new register scheme. 1705 * reg set 0 is chan 0 1706 * reg set 1 is chan 1 ... 1707 * Interrupts are specified in that order but later 1708 * channels may not have interrupts. 1709 * We map the regs later on a per channel basis. 1710 */ 1711 ssp->per_channel_regs = B_TRUE; 1712 break; 1713 } 1714 return (0); 1715 } 1716 1717 static int 1718 bscbus_claim_channel(struct bscbus_channel_state *csp, boolean_t map_dog) 1719 { 1720 int err; 1721 1722 mutex_enter(csp->ssp->ch_mutex); 1723 csp->map_count++; 1724 bscbus_trace(csp, 'C', "bscbus_claim_channel", 1725 "claim channel for channel %d, count %d", 1726 csp->chno, csp->map_count); 1727 1728 if (csp->map_count == 1) { 1729 /* No-one is using this channel - initialise it */ 1730 bscbus_trace(csp, 'C', "bscbus_claim_channel", 1731 "initialise channel %d, count %d", 1732 csp->chno, csp->map_count); 1733 1734 mutex_init(csp->dog_mutex, NULL, MUTEX_DRIVER, 1735 (void *)(uintptr_t)__ipltospl(SPL7 - 1)); 1736 csp->map_dog = map_dog; 1737 csp->interrupt_failed = B_FALSE; 1738 csp->cmdstate = BSCBUS_CMDSTATE_IDLE; 1739 csp->pat_retry_count = 0; 1740 csp->pat_fail_count = 0; 1741 1742 /* Map appropriate register set for this channel */ 1743 if (csp->ssp->per_channel_regs == B_TRUE) { 1744 ddi_acc_handle_t h; 1745 caddr_t p; 1746 1747 err = ddi_regs_map_setup(csp->ssp->dip, csp->chno, 1748 &p, 0, 0, bscbus_dev_acc_attr, &h); 1749 1750 if (err != DDI_SUCCESS) { 1751 goto failed1; 1752 } 1753 1754 csp->ch_handle = h; 1755 csp->ch_regs = (void *)p; 1756 1757 bscbus_trace(csp, 'C', "bscbus_claim_channel", 1758 "mapped chno=%d ch_handle=%d ch_regs=%p", 1759 csp->chno, h, p); 1760 } else { 1761 /* 1762 * if using the old reg property scheme use the 1763 * common mapping. 1764 */ 1765 csp->ch_handle = csp->ssp->h8_handle; 1766 csp->ch_regs = 1767 csp->ssp->h8_regs + 1768 BSCBUS_CHANNEL_TO_OFFSET(csp->chno); 1769 } 1770 1771 /* Ensure no interrupts pending prior to getting iblk cookie */ 1772 bscbus_hw_reset(csp); 1773 1774 if (csp->map_dog == 1) { 1775 /* 1776 * we don't want lo_mutex to be initialised 1777 * with an iblock cookie if we are the wdog, 1778 * because we don't use interrupts. 1779 */ 1780 mutex_init(csp->lo_mutex, NULL, 1781 MUTEX_DRIVER, NULL); 1782 cv_init(csp->lo_cv, NULL, 1783 CV_DRIVER, NULL); 1784 csp->unclaimed_count = 0; 1785 } else { 1786 int ninterrupts; 1787 1788 /* 1789 * check that there is an interrupt for this 1790 * this channel. If we fail to setup interrupts we 1791 * must unmap the registers and fail. 1792 */ 1793 err = ddi_dev_nintrs(csp->ssp->dip, &ninterrupts); 1794 1795 if (err != DDI_SUCCESS) { 1796 ninterrupts = 0; 1797 } 1798 1799 if (ninterrupts <= csp->chno) { 1800 cmn_err(CE_WARN, 1801 "no interrupt available for " 1802 "bscbus channel %d", csp->chno); 1803 goto failed2; 1804 } 1805 1806 if (ddi_intr_hilevel(csp->ssp->dip, csp->chno) != 0) { 1807 cmn_err(CE_WARN, 1808 "bscbus interrupts are high " 1809 "level - channel not usable."); 1810 goto failed2; 1811 } else { 1812 err = ddi_get_iblock_cookie(csp->ssp->dip, 1813 csp->chno, &csp->lo_iblk); 1814 if (err != DDI_SUCCESS) { 1815 goto failed2; 1816 } 1817 1818 mutex_init(csp->lo_mutex, NULL, 1819 MUTEX_DRIVER, csp->lo_iblk); 1820 cv_init(csp->lo_cv, NULL, 1821 CV_DRIVER, NULL); 1822 csp->unclaimed_count = 0; 1823 1824 err = ddi_add_intr(csp->ssp->dip, csp->chno, 1825 &csp->lo_iblk, NULL, 1826 bscbus_hwintr, (caddr_t)csp); 1827 if (err != DDI_SUCCESS) { 1828 cv_destroy(csp->lo_cv); 1829 mutex_destroy(csp->lo_mutex); 1830 goto failed2; 1831 } 1832 } 1833 } 1834 /* 1835 * The channel is now live and may 1836 * receive interrupts 1837 */ 1838 } else if (csp->map_dog != map_dog) { 1839 bscbus_trace(csp, 'C', "bscbus_claim_channel", 1840 "request conflicts with previous mapping. old %x, new %x.", 1841 csp->map_dog, map_dog); 1842 goto failed1; 1843 } 1844 mutex_exit(csp->ssp->ch_mutex); 1845 return (1); 1846 1847 failed2: 1848 /* unmap regs for failed channel */ 1849 if (csp->ssp->per_channel_regs == B_TRUE) { 1850 ddi_regs_map_free(&csp->ch_handle); 1851 } 1852 csp->ch_handle = NULL; 1853 csp->ch_regs = (void *)NULL; 1854 failed1: 1855 csp->map_count--; 1856 mutex_exit(csp->ssp->ch_mutex); 1857 return (0); 1858 } 1859 1860 static void 1861 bscbus_release_channel(struct bscbus_channel_state *csp) 1862 { 1863 mutex_enter(csp->ssp->ch_mutex); 1864 if (csp->map_count == 1) { 1865 /* No-one is now using this channel - shutdown channel */ 1866 bscbus_trace(csp, 'C', "bscbus_release_channel", 1867 "shutdown channel %d, count %d", 1868 csp->chno, csp->map_count); 1869 1870 if (csp->map_dog == 0) { 1871 ASSERT(!ddi_intr_hilevel(csp->ssp->dip, csp->chno)); 1872 ddi_remove_intr(csp->ssp->dip, csp->chno, csp->lo_iblk); 1873 } 1874 cv_destroy(csp->lo_cv); 1875 mutex_destroy(csp->lo_mutex); 1876 mutex_destroy(csp->dog_mutex); 1877 bscbus_hw_reset(csp); 1878 1879 /* unmap registers if using the new register scheme */ 1880 if (csp->ssp->per_channel_regs == B_TRUE) { 1881 ddi_regs_map_free(&csp->ch_handle); 1882 } 1883 csp->ch_handle = NULL; 1884 csp->ch_regs = (void *)NULL; 1885 } 1886 csp->map_count--; 1887 bscbus_trace(csp, 'C', "bscbus_release_channel", 1888 "release channel %d, count %d", 1889 csp->chno, csp->map_count); 1890 mutex_exit(csp->ssp->ch_mutex); 1891 } 1892 1893 1894 /* 1895 * Nexus routines 1896 */ 1897 1898 #if defined(NDI_ACC_HDL_V2) 1899 1900 static const ndi_acc_fns_t bscbus_vreg_acc_fns = { 1901 NDI_ACC_FNS_CURRENT, 1902 NDI_ACC_FNS_V1, 1903 1904 bscbus_vreg_get8, 1905 bscbus_vreg_put8, 1906 bscbus_vreg_rep_get8, 1907 bscbus_vreg_rep_put8, 1908 1909 bscbus_no_get16, 1910 bscbus_no_put16, 1911 bscbus_no_rep_get16, 1912 bscbus_no_rep_put16, 1913 1914 bscbus_meta_get32, 1915 bscbus_meta_put32, 1916 bscbus_meta_rep_get32, 1917 bscbus_meta_rep_put32, 1918 1919 bscbus_no_get64, 1920 bscbus_no_put64, 1921 bscbus_no_rep_get64, 1922 bscbus_no_rep_put64, 1923 1924 bscbus_acc_fault_check 1925 }; 1926 1927 static const ndi_acc_fns_t bscbus_pat_acc_fns = { 1928 NDI_ACC_FNS_CURRENT, 1929 NDI_ACC_FNS_V1, 1930 1931 bscbus_pat_get8, 1932 bscbus_pat_put8, 1933 bscbus_pat_rep_get8, 1934 bscbus_pat_rep_put8, 1935 1936 bscbus_no_get16, 1937 bscbus_no_put16, 1938 bscbus_no_rep_get16, 1939 bscbus_no_rep_put16, 1940 1941 bscbus_meta_get32, 1942 bscbus_meta_put32, 1943 bscbus_meta_rep_get32, 1944 bscbus_meta_rep_put32, 1945 1946 bscbus_no_get64, 1947 bscbus_no_put64, 1948 bscbus_no_rep_get64, 1949 bscbus_no_rep_put64, 1950 1951 bscbus_acc_fault_check 1952 }; 1953 1954 static const ndi_acc_fns_t bscbus_event_acc_fns = { 1955 NDI_ACC_FNS_CURRENT, 1956 NDI_ACC_FNS_V1, 1957 1958 bscbus_no_get8, 1959 bscbus_no_put8, 1960 bscbus_no_rep_get8, 1961 bscbus_no_rep_put8, 1962 1963 bscbus_event_get16, 1964 bscbus_event_put16, 1965 bscbus_event_rep_get16, 1966 bscbus_event_rep_put16, 1967 1968 bscbus_meta_get32, 1969 bscbus_meta_put32, 1970 bscbus_meta_rep_get32, 1971 bscbus_meta_rep_put32, 1972 1973 bscbus_no_get64, 1974 bscbus_no_put64, 1975 bscbus_no_rep_get64, 1976 bscbus_no_rep_put64, 1977 1978 bscbus_acc_fault_check 1979 }; 1980 1981 static int 1982 bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op, 1983 int space, caddr_t vaddr, off_t len, 1984 ndi_acc_handle_t *hdlp, caddr_t *addrp) 1985 { 1986 switch (op) { 1987 default: 1988 return (DDI_ME_UNIMPLEMENTED); 1989 1990 case DDI_MO_MAP_LOCKED: 1991 if (bscbus_claim_channel(csp, 1992 (space == LOMBUS_PAT_SPACE)) == 0) { 1993 return (DDI_ME_GENERIC); 1994 } 1995 1996 switch (space) { 1997 default: 1998 return (DDI_ME_REGSPEC_RANGE); 1999 2000 case LOMBUS_VREG_SPACE: 2001 ndi_set_acc_fns(hdlp, &bscbus_vreg_acc_fns); 2002 break; 2003 2004 case LOMBUS_PAT_SPACE: 2005 ndi_set_acc_fns(hdlp, &bscbus_pat_acc_fns); 2006 break; 2007 2008 case LOMBUS_EVENT_SPACE: 2009 ndi_set_acc_fns(hdlp, &bscbus_event_acc_fns); 2010 break; 2011 } 2012 hdlp->ah_addr = *addrp = vaddr; 2013 hdlp->ah_len = len; 2014 hdlp->ah_bus_private = csp; 2015 return (DDI_SUCCESS); 2016 2017 case DDI_MO_UNMAP: 2018 *addrp = NULL; 2019 hdlp->ah_bus_private = NULL; 2020 bscbus_release_channel(csp); 2021 return (DDI_SUCCESS); 2022 } 2023 } 2024 2025 #else 2026 2027 static int 2028 bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op, 2029 int space, caddr_t vaddr, off_t len, 2030 ddi_acc_hdl_t *hdlp, caddr_t *addrp) 2031 { 2032 ddi_acc_impl_t *aip = hdlp->ah_platform_private; 2033 2034 switch (op) { 2035 default: 2036 return (DDI_ME_UNIMPLEMENTED); 2037 2038 case DDI_MO_MAP_LOCKED: 2039 if (bscbus_claim_channel(csp, 2040 (space == LOMBUS_PAT_SPACE)) == 0) { 2041 return (DDI_ME_GENERIC); 2042 } 2043 2044 switch (space) { 2045 default: 2046 return (DDI_ME_REGSPEC_RANGE); 2047 2048 case LOMBUS_VREG_SPACE: 2049 aip->ahi_get8 = bscbus_vreg_get8; 2050 aip->ahi_put8 = bscbus_vreg_put8; 2051 aip->ahi_rep_get8 = bscbus_vreg_rep_get8; 2052 aip->ahi_rep_put8 = bscbus_vreg_rep_put8; 2053 2054 aip->ahi_get16 = bscbus_no_get16; 2055 aip->ahi_put16 = bscbus_no_put16; 2056 aip->ahi_rep_get16 = bscbus_no_rep_get16; 2057 aip->ahi_rep_put16 = bscbus_no_rep_put16; 2058 2059 aip->ahi_get32 = bscbus_meta_get32; 2060 aip->ahi_put32 = bscbus_meta_put32; 2061 aip->ahi_rep_get32 = bscbus_meta_rep_get32; 2062 aip->ahi_rep_put32 = bscbus_meta_rep_put32; 2063 2064 aip->ahi_get64 = bscbus_no_get64; 2065 aip->ahi_put64 = bscbus_no_put64; 2066 aip->ahi_rep_get64 = bscbus_no_rep_get64; 2067 aip->ahi_rep_put64 = bscbus_no_rep_put64; 2068 2069 aip->ahi_fault_check = bscbus_acc_fault_check; 2070 break; 2071 2072 case LOMBUS_PAT_SPACE: 2073 aip->ahi_get8 = bscbus_pat_get8; 2074 aip->ahi_put8 = bscbus_pat_put8; 2075 aip->ahi_rep_get8 = bscbus_pat_rep_get8; 2076 aip->ahi_rep_put8 = bscbus_pat_rep_put8; 2077 2078 aip->ahi_get16 = bscbus_no_get16; 2079 aip->ahi_put16 = bscbus_no_put16; 2080 aip->ahi_rep_get16 = bscbus_no_rep_get16; 2081 aip->ahi_rep_put16 = bscbus_no_rep_put16; 2082 2083 aip->ahi_get32 = bscbus_meta_get32; 2084 aip->ahi_put32 = bscbus_meta_put32; 2085 aip->ahi_rep_get32 = bscbus_meta_rep_get32; 2086 aip->ahi_rep_put32 = bscbus_meta_rep_put32; 2087 2088 aip->ahi_get64 = bscbus_no_get64; 2089 aip->ahi_put64 = bscbus_no_put64; 2090 aip->ahi_rep_get64 = bscbus_no_rep_get64; 2091 aip->ahi_rep_put64 = bscbus_no_rep_put64; 2092 2093 aip->ahi_fault_check = bscbus_acc_fault_check; 2094 break; 2095 2096 case LOMBUS_EVENT_SPACE: 2097 aip->ahi_get8 = bscbus_no_get8; 2098 aip->ahi_put8 = bscbus_no_put8; 2099 aip->ahi_rep_get8 = bscbus_no_rep_get8; 2100 aip->ahi_rep_put8 = bscbus_no_rep_put8; 2101 2102 aip->ahi_get16 = bscbus_event_get16; 2103 aip->ahi_put16 = bscbus_event_put16; 2104 aip->ahi_rep_get16 = bscbus_event_rep_get16; 2105 aip->ahi_rep_put16 = bscbus_event_rep_put16; 2106 2107 aip->ahi_get32 = bscbus_meta_get32; 2108 aip->ahi_put32 = bscbus_meta_put32; 2109 aip->ahi_rep_get32 = bscbus_meta_rep_get32; 2110 aip->ahi_rep_put32 = bscbus_meta_rep_put32; 2111 2112 aip->ahi_get64 = bscbus_no_get64; 2113 aip->ahi_put64 = bscbus_no_put64; 2114 aip->ahi_rep_get64 = bscbus_no_rep_get64; 2115 aip->ahi_rep_put64 = bscbus_no_rep_put64; 2116 2117 aip->ahi_fault_check = bscbus_acc_fault_check; 2118 break; 2119 } 2120 hdlp->ah_addr = *addrp = vaddr; 2121 hdlp->ah_len = len; 2122 hdlp->ah_bus_private = csp; 2123 return (DDI_SUCCESS); 2124 2125 case DDI_MO_UNMAP: 2126 *addrp = NULL; 2127 hdlp->ah_bus_private = NULL; 2128 bscbus_release_channel(csp); 2129 return (DDI_SUCCESS); 2130 } 2131 } 2132 2133 #endif /* NDI_ACC_HDL_V2 */ 2134 2135 static int 2136 bscbus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp, 2137 off_t off, off_t len, caddr_t *addrp) 2138 { 2139 struct bscbus_child_info *lcip; 2140 struct bscbus_state *ssp; 2141 lombus_regspec_t *rsp; 2142 2143 if ((ssp = bscbus_getstate(dip, -1, "bscbus_map")) == NULL) 2144 return (DDI_FAILURE); /* this "can't happen" */ 2145 2146 /* 2147 * Validate mapping request ... 2148 */ 2149 2150 if (mp->map_flags != DDI_MF_KERNEL_MAPPING) 2151 return (DDI_ME_UNSUPPORTED); 2152 if (mp->map_handlep == NULL) 2153 return (DDI_ME_UNSUPPORTED); 2154 if (mp->map_type != DDI_MT_RNUMBER) 2155 return (DDI_ME_UNIMPLEMENTED); 2156 if ((lcip = ddi_get_parent_data(rdip)) == NULL) 2157 return (DDI_ME_INVAL); 2158 if ((rsp = lcip->rsp) == NULL) 2159 return (DDI_ME_INVAL); 2160 if (mp->map_obj.rnumber >= lcip->nregs) 2161 return (DDI_ME_RNUMBER_RANGE); 2162 rsp += mp->map_obj.rnumber; 2163 if (off < 0 || off >= rsp->lombus_size) 2164 return (DDI_ME_INVAL); 2165 if (len == 0) 2166 len = rsp->lombus_size-off; 2167 if (len < 0) 2168 return (DDI_ME_INVAL); 2169 if (off+len < 0 || off+len > rsp->lombus_size) 2170 return (DDI_ME_INVAL); 2171 2172 return (bscbus_map_handle( 2173 &ssp->channel[LOMBUS_SPACE_TO_CHANNEL(rsp->lombus_space)], 2174 mp->map_op, LOMBUS_SPACE_TO_REGSET(rsp->lombus_space), 2175 VREG_TO_ADDR(rsp->lombus_base+off), len, mp->map_handlep, addrp)); 2176 } 2177 2178 2179 static int 2180 bscbus_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, 2181 void *arg, void *result) 2182 { 2183 struct bscbus_child_info *lcip; 2184 lombus_regspec_t *rsp; 2185 dev_info_t *cdip; 2186 char addr[32]; 2187 uint_t nregs; 2188 uint_t rnum; 2189 int *regs; 2190 int limit; 2191 int err; 2192 int i; 2193 2194 if (bscbus_getstate(dip, -1, "bscbus_ctlops") == NULL) 2195 return (DDI_FAILURE); /* this "can't happen" */ 2196 2197 switch (op) { 2198 default: 2199 break; 2200 2201 case DDI_CTLOPS_INITCHILD: 2202 /* 2203 * First, look up and validate the "reg" property. 2204 * 2205 * It must be a non-empty integer array containing a set 2206 * of triples. Once we've verified that, we can treat it 2207 * as an array of type lombus_regspec_t[], which defines 2208 * the meaning of the elements of each triple: 2209 * + the first element of each triple must be a valid space 2210 * + the second and third elements (base, size) of each 2211 * triple must define a valid subrange of that space 2212 * If it passes all the tests, we save it away for future 2213 * reference in the child's parent-private-data field. 2214 */ 2215 cdip = arg; 2216 err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip, 2217 DDI_PROP_DONTPASS, "reg", ®s, &nregs); 2218 if (err != DDI_PROP_SUCCESS) 2219 return (DDI_FAILURE); 2220 2221 err = (nregs <= 0 || (nregs % LOMBUS_REGSPEC_SIZE) != 0); 2222 nregs /= LOMBUS_REGSPEC_SIZE; 2223 rsp = (lombus_regspec_t *)regs; 2224 for (i = 0; i < nregs && !err; ++i) { 2225 switch (LOMBUS_SPACE_TO_REGSET(rsp[i].lombus_space)) { 2226 default: 2227 limit = 0; 2228 err = 1; 2229 cmn_err(CE_WARN, 2230 "child(%p): unknown reg space %d", 2231 (void *)cdip, rsp[i].lombus_space); 2232 break; 2233 2234 case LOMBUS_VREG_SPACE: 2235 limit = LOMBUS_MAX_REG+1; 2236 break; 2237 2238 case LOMBUS_PAT_SPACE: 2239 limit = LOMBUS_PAT_REG+1; 2240 break; 2241 2242 case LOMBUS_EVENT_SPACE: 2243 limit = LOMBUS_EVENT_REG+1; 2244 break; 2245 } 2246 2247 err |= (rsp[i].lombus_base < 0); 2248 err |= (rsp[i].lombus_base >= limit); 2249 2250 if (rsp[i].lombus_size == 0) 2251 rsp[i].lombus_size = limit-rsp[i].lombus_base; 2252 2253 err |= (rsp[i].lombus_size < 0); 2254 err |= (rsp[i].lombus_base+rsp[i].lombus_size < 0); 2255 err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit); 2256 2257 err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit); 2258 2259 } 2260 2261 if (err) { 2262 ddi_prop_free(regs); 2263 return (DDI_FAILURE); 2264 } 2265 2266 lcip = kmem_zalloc(sizeof (*lcip), KM_SLEEP); 2267 lcip->nregs = nregs; 2268 lcip->rsp = rsp; 2269 ddi_set_parent_data(cdip, lcip); 2270 2271 (void) snprintf(addr, sizeof (addr), 2272 "%x,%x", rsp[0].lombus_space, rsp[0].lombus_base); 2273 ddi_set_name_addr(cdip, addr); 2274 2275 return (DDI_SUCCESS); 2276 2277 case DDI_CTLOPS_UNINITCHILD: 2278 cdip = arg; 2279 ddi_set_name_addr(cdip, NULL); 2280 lcip = ddi_get_parent_data(cdip); 2281 ddi_set_parent_data(cdip, NULL); 2282 ddi_prop_free(lcip->rsp); 2283 kmem_free(lcip, sizeof (*lcip)); 2284 return (DDI_SUCCESS); 2285 2286 case DDI_CTLOPS_REPORTDEV: 2287 if (rdip == NULL) 2288 return (DDI_FAILURE); 2289 2290 cmn_err(CE_CONT, "?BSC device: %s@%s, %s#%d\n", 2291 ddi_node_name(rdip), ddi_get_name_addr(rdip), 2292 ddi_driver_name(dip), ddi_get_instance(dip)); 2293 2294 return (DDI_SUCCESS); 2295 2296 case DDI_CTLOPS_REGSIZE: 2297 if ((lcip = ddi_get_parent_data(rdip)) == NULL) 2298 return (DDI_FAILURE); 2299 if ((rnum = *(uint_t *)arg) >= lcip->nregs) 2300 return (DDI_FAILURE); 2301 *(off_t *)result = lcip->rsp[rnum].lombus_size; 2302 return (DDI_SUCCESS); 2303 2304 case DDI_CTLOPS_NREGS: 2305 if ((lcip = ddi_get_parent_data(rdip)) == NULL) 2306 return (DDI_FAILURE); 2307 *(int *)result = lcip->nregs; 2308 return (DDI_SUCCESS); 2309 } 2310 2311 return (ddi_ctlops(dip, rdip, op, arg, result)); 2312 } 2313 2314 2315 /* 2316 * This nexus does not support passing interrupts to leaf drivers, so 2317 * all the intrspec-related operations just fail as cleanly as possible. 2318 */ 2319 2320 /*ARGSUSED*/ 2321 static int 2322 bscbus_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, 2323 ddi_intr_handle_impl_t *hdlp, void *result) 2324 { 2325 #if defined(__sparc) 2326 return (i_ddi_intr_ops(dip, rdip, op, hdlp, result)); 2327 #else 2328 _NOTE(ARGUNUSED(dip, rdip, op, hdlp, result)) 2329 return (DDI_FAILURE); 2330 #endif 2331 } 2332 2333 /* 2334 * Clean up on detach or failure of attach 2335 */ 2336 static int 2337 bscbus_unattach(struct bscbus_state *ssp, int instance) 2338 { 2339 int chno; 2340 2341 if (ssp != NULL) { 2342 for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) { 2343 ASSERT(ssp->channel[chno].map_count == 0); 2344 } 2345 bscbus_offline(ssp); 2346 ddi_set_driver_private(ssp->dip, NULL); 2347 mutex_destroy(ssp->ch_mutex); 2348 } 2349 #ifdef BSCBUS_LOGSTATUS 2350 if (ssp->cmd_log_size != 0) { 2351 kmem_free(ssp->cmd_log, 2352 ssp->cmd_log_size * sizeof (bsc_cmd_log_t)); 2353 } 2354 #endif /* BSCBUS_LOGSTATUS */ 2355 2356 2357 ddi_soft_state_free(bscbus_statep, instance); 2358 return (DDI_FAILURE); 2359 } 2360 2361 /* 2362 * Autoconfiguration routines 2363 */ 2364 2365 static int 2366 bscbus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 2367 { 2368 struct bscbus_state *ssp = NULL; 2369 int chno; 2370 int instance; 2371 int err; 2372 2373 switch (cmd) { 2374 default: 2375 return (DDI_FAILURE); 2376 2377 case DDI_ATTACH: 2378 break; 2379 } 2380 2381 /* 2382 * Allocate the soft-state structure 2383 */ 2384 instance = ddi_get_instance(dip); 2385 if (ddi_soft_state_zalloc(bscbus_statep, instance) != DDI_SUCCESS) 2386 return (DDI_FAILURE); 2387 if ((ssp = bscbus_getstate(dip, instance, "bscbus_attach")) == NULL) 2388 return (bscbus_unattach(ssp, instance)); 2389 ddi_set_driver_private(dip, ssp); 2390 2391 /* 2392 * Initialise devinfo-related fields 2393 */ 2394 ssp->dip = dip; 2395 ssp->majornum = ddi_driver_major(dip); 2396 ssp->instance = instance; 2397 2398 /* 2399 * Set various options from .conf properties 2400 */ 2401 ssp->debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 2402 DDI_PROP_DONTPASS, "debug", 0); 2403 2404 mutex_init(ssp->ch_mutex, NULL, MUTEX_DRIVER, NULL); 2405 2406 #ifdef BSCBUS_LOGSTATUS 2407 ssp->cmd_log_size = bscbus_cmd_log_size; 2408 if (ssp->cmd_log_size != 0) { 2409 ssp->cmd_log_idx = 0; 2410 ssp->cmd_log = kmem_zalloc(ssp->cmd_log_size * 2411 sizeof (bsc_cmd_log_t), KM_SLEEP); 2412 } 2413 #endif /* BSCBUS_LOGSTATUS */ 2414 2415 /* 2416 * Online the hardware ... 2417 */ 2418 err = bscbus_online(ssp); 2419 if (err != 0) 2420 return (bscbus_unattach(ssp, instance)); 2421 2422 for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) { 2423 struct bscbus_channel_state *csp = &ssp->channel[chno]; 2424 2425 /* 2426 * Initialise state 2427 * The hardware/interrupts are setup at map time to 2428 * avoid claiming hardware that OBP is using 2429 */ 2430 csp->ssp = ssp; 2431 csp->chno = chno; 2432 csp->map_count = 0; 2433 csp->map_dog = B_FALSE; 2434 } 2435 2436 /* 2437 * All done, report success 2438 */ 2439 ddi_report_dev(dip); 2440 return (DDI_SUCCESS); 2441 } 2442 2443 static int 2444 bscbus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 2445 { 2446 struct bscbus_state *ssp; 2447 int instance; 2448 2449 switch (cmd) { 2450 default: 2451 return (DDI_FAILURE); 2452 2453 case DDI_DETACH: 2454 break; 2455 } 2456 2457 instance = ddi_get_instance(dip); 2458 if ((ssp = bscbus_getstate(dip, instance, "bscbus_detach")) == NULL) 2459 return (DDI_FAILURE); /* this "can't happen" */ 2460 2461 (void) bscbus_unattach(ssp, instance); 2462 return (DDI_SUCCESS); 2463 } 2464 2465 static int 2466 bscbus_reset(dev_info_t *dip, ddi_reset_cmd_t cmd) 2467 { 2468 struct bscbus_state *ssp; 2469 int chno; 2470 2471 _NOTE(ARGUNUSED(cmd)) 2472 2473 if ((ssp = bscbus_getstate(dip, -1, "bscbus_reset")) == NULL) 2474 return (DDI_FAILURE); 2475 2476 for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) { 2477 bscbus_hw_reset(&ssp->channel[chno]); 2478 } 2479 return (DDI_SUCCESS); 2480 } 2481 2482 2483 /* 2484 * System interface structures 2485 */ 2486 2487 static struct cb_ops bscbus_cb_ops = 2488 { 2489 nodev, /* b/c open */ 2490 nodev, /* b/c close */ 2491 nodev, /* b strategy */ 2492 nodev, /* b print */ 2493 nodev, /* b dump */ 2494 nodev, /* c read */ 2495 nodev, /* c write */ 2496 nodev, /* c ioctl */ 2497 nodev, /* c devmap */ 2498 nodev, /* c mmap */ 2499 nodev, /* c segmap */ 2500 nochpoll, /* c poll */ 2501 ddi_prop_op, /* b/c prop_op */ 2502 NULL, /* c streamtab */ 2503 D_MP | D_NEW /* b/c flags */ 2504 }; 2505 2506 static struct bus_ops bscbus_bus_ops = 2507 { 2508 BUSO_REV, /* revision */ 2509 bscbus_map, /* bus_map */ 2510 0, /* get_intrspec */ 2511 0, /* add_intrspec */ 2512 0, /* remove_intrspec */ 2513 i_ddi_map_fault, /* map_fault */ 2514 ddi_no_dma_map, /* dma_map */ 2515 ddi_no_dma_allochdl, /* allocate DMA handle */ 2516 ddi_no_dma_freehdl, /* free DMA handle */ 2517 ddi_no_dma_bindhdl, /* bind DMA handle */ 2518 ddi_no_dma_unbindhdl, /* unbind DMA handle */ 2519 ddi_no_dma_flush, /* flush DMA */ 2520 ddi_no_dma_win, /* move DMA window */ 2521 ddi_no_dma_mctl, /* generic DMA control */ 2522 bscbus_ctlops, /* generic control */ 2523 ddi_bus_prop_op, /* prop_op */ 2524 ndi_busop_get_eventcookie, /* get_eventcookie */ 2525 ndi_busop_add_eventcall, /* add_eventcall */ 2526 ndi_busop_remove_eventcall, /* remove_eventcall */ 2527 ndi_post_event, /* post_event */ 2528 0, /* interrupt control */ 2529 0, /* bus_config */ 2530 0, /* bus_unconfig */ 2531 0, /* bus_fm_init */ 2532 0, /* bus_fm_fini */ 2533 0, /* bus_fm_access_enter */ 2534 0, /* bus_fm_access_exit */ 2535 0, /* bus_power */ 2536 bscbus_intr_op /* bus_intr_op */ 2537 }; 2538 2539 static struct dev_ops bscbus_dev_ops = 2540 { 2541 DEVO_REV, 2542 0, /* refcount */ 2543 ddi_no_info, /* getinfo */ 2544 nulldev, /* identify */ 2545 nulldev, /* probe */ 2546 bscbus_attach, /* attach */ 2547 bscbus_detach, /* detach */ 2548 bscbus_reset, /* reset */ 2549 &bscbus_cb_ops, /* driver operations */ 2550 &bscbus_bus_ops, /* bus operations */ 2551 NULL, /* power */ 2552 ddi_quiesce_not_needed, /* quiesce */ 2553 }; 2554 2555 static struct modldrv modldrv = 2556 { 2557 &mod_driverops, 2558 "bscbus driver", 2559 &bscbus_dev_ops 2560 }; 2561 2562 static struct modlinkage modlinkage = 2563 { 2564 MODREV_1, 2565 { 2566 &modldrv, 2567 NULL 2568 } 2569 }; 2570 2571 2572 /* 2573 * Dynamic loader interface code 2574 */ 2575 2576 int 2577 _init(void) 2578 { 2579 int err; 2580 2581 err = ddi_soft_state_init(&bscbus_statep, 2582 sizeof (struct bscbus_state), 0); 2583 if (err == DDI_SUCCESS) 2584 if ((err = mod_install(&modlinkage)) != DDI_SUCCESS) { 2585 ddi_soft_state_fini(&bscbus_statep); 2586 } 2587 2588 return (err); 2589 } 2590 2591 int 2592 _info(struct modinfo *mip) 2593 { 2594 return (mod_info(&modlinkage, mip)); 2595 } 2596 2597 int 2598 _fini(void) 2599 { 2600 int err; 2601 2602 if ((err = mod_remove(&modlinkage)) == DDI_SUCCESS) { 2603 ddi_soft_state_fini(&bscbus_statep); 2604 bscbus_major = NOMAJOR; 2605 } 2606 2607 return (err); 2608 } 2609 2610 #ifdef BSCBUS_LOGSTATUS 2611 void bscbus_cmd_log(struct bscbus_channel_state *csp, bsc_cmd_stamp_t cat, 2612 uint8_t status, uint8_t data) 2613 { 2614 int idx; 2615 bsc_cmd_log_t *logp; 2616 struct bscbus_state *ssp; 2617 2618 if ((csp) == NULL) 2619 return; 2620 if ((ssp = (csp)->ssp) == NULL) 2621 return; 2622 if (ssp->cmd_log_size == 0) 2623 return; 2624 if ((bscbus_cmd_log_flags & (1 << cat)) == 0) 2625 return; 2626 idx = atomic_add_32_nv(&ssp->cmd_log_idx, 1); 2627 logp = &ssp->cmd_log[idx % ssp->cmd_log_size]; 2628 logp->bcl_seq = idx; 2629 logp->bcl_cat = cat; 2630 logp->bcl_now = gethrtime(); 2631 logp->bcl_chno = csp->chno; 2632 logp->bcl_cmdstate = csp->cmdstate; 2633 logp->bcl_status = status; 2634 logp->bcl_data = data; 2635 } 2636 #endif /* BSCBUS_LOGSTATUS */ 2637