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