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