Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / bscbus.c
blob8b64a9807bd1f5fe9af19c439c5ebce05a2c72f9
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
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.
31 * On the other hand, this driver doesn't generally know what the virtual
32 * registers signify - only the clients need this information.
36 #include <sys/note.h>
37 #include <sys/types.h>
38 #include <sys/conf.h>
39 #include <sys/debug.h>
40 #include <sys/errno.h>
41 #include <sys/file.h>
44 #include <sys/kmem.h>
45 #include <sys/modctl.h>
46 #include <sys/note.h>
47 #include <sys/open.h>
48 #include <sys/poll.h>
49 #include <sys/spl.h>
50 #include <sys/stat.h>
51 #include <sys/strlog.h>
52 #include <sys/atomic.h>
54 #include <sys/ddi.h>
55 #include <sys/sunddi.h>
56 #include <sys/sunndi.h>
58 #include <sys/bscbus.h>
60 #if defined(NDI_ACC_HDL_V2)
63 * Compiling for Solaris 10+ with access handle enhancements
65 #define HANDLE_TYPE ndi_acc_handle_t
66 #define HANDLE_ADDR(hdlp) (hdlp->ah_addr)
67 #define HANDLE_FAULT(hdlp) (hdlp->ah_fault)
68 #define HANDLE_MAPLEN(hdlp) (hdlp->ah_len)
69 #define HANDLE_PRIVATE(hdlp) (hdlp->ah_bus_private)
71 #else
74 * Compatibility definitions for backport to Solaris 8/9
76 #define HANDLE_TYPE ddi_acc_impl_t
77 #define HANDLE_ADDR(hdlp) (hdlp->ahi_common.ah_addr)
78 #define HANDLE_FAULT(hdlp) (hdlp->ahi_fault)
79 #define HANDLE_MAPLEN(hdlp) (hdlp->ahi_common.ah_len)
80 #define HANDLE_PRIVATE(hdlp) (hdlp->ahi_common.ah_bus_private)
82 #define ddi_driver_major(dip) ddi_name_to_major(ddi_binding_name(dip))
84 #endif /* NDI_ACC_HDL_V2 */
88 * Local definitions
90 #define MYNAME "bscbus"
91 #define NOMAJOR (~(major_t)0)
92 #define DUMMY_VALUE (~(int8_t)0)
94 #define BSCBUS_INST_TO_MINOR(i) (i)
95 #define BSCBUS_MINOR_TO_INST(m) (m)
97 #define BSCBUS_MAX_CHANNELS (4)
99 #define BSCBUS_DUMMY_ADDRESS ((caddr_t)0x0CADD1ED)
100 #define ADDR_TO_OFFSET(a, hdlp) ((caddr_t)(a) - HANDLE_ADDR(hdlp))
101 #define ADDR_TO_VREG(a) ((caddr_t)(a) - BSCBUS_DUMMY_ADDRESS)
102 #define VREG_TO_ADDR(v) (BSCBUS_DUMMY_ADDRESS + (v))
104 #ifdef DEBUG
105 #define BSCBUS_LOGSTATUS
106 #endif /* DEBUG */
108 #ifdef BSCBUS_LOGSTATUS
110 * BSC command logging routines.
111 * Record the data passing to and from the BSC
114 typedef enum {
115 BSC_CMD_BUSY = 1, /* bsc reports busy */
116 BSC_CMD_CLEARING = 2, /* clearing bsc busy */
117 BSC_CMD_CLEARED = 3, /* cleared bsc busy */
118 BSC_CMD_SENDING = 4, /* sending next byte */
119 BSC_CMD_SENT = 5, /* sending last byte */
120 BSC_CMD_PENDING = 6, /* got sent byte ack */
121 BSC_CMD_REPLY = 7, /* got reply byte */
122 BSC_CMD_COMPLETE = 8, /* command complete */
123 BSC_CMD_ERROR_SEQ = 9, /* error status */
124 BSC_CMD_ERROR_STATUS = 10, /* error status */
125 BSC_CMD_ERROR_OFLOW = 11, /* error status */
126 BSC_CMD_ERROR_TOUT = 12, /* error status */
128 BSC_CMD_PROCESS = 13, /* async intr */
129 BSC_CMD_V1INTR = 14, /* v1 intr */
130 BSC_CMD_V1INTRUNCL = 15, /* v1 intr unclaim */
131 BSC_CMD_DOGPAT = 17 /* watchdog pat */
132 } bsc_cmd_stamp_t;
134 typedef struct {
135 hrtime_t bcl_now;
136 int bcl_seq;
137 bsc_cmd_stamp_t bcl_cat;
138 uint8_t bcl_chno;
139 uint8_t bcl_cmdstate;
140 uint8_t bcl_status;
141 uint8_t bcl_data;
142 } bsc_cmd_log_t;
144 uint32_t bscbus_cmd_log_size = 1024;
146 uint32_t bscbus_cmd_log_flags = 0xffffffff;
148 #endif /* BSCBUS_LOGSTATUS */
151 * The following definitions are taken from the Hardware Manual for
152 * the Hitachi H8S/2148 in conjunction with the hardware specification
153 * for the Stiletto blade.
155 * Each instance of the host interface has 3 registers on the H8:
156 * IDRn - Input Data Register - write-only for Solaris.
157 * writes to this can be done via two
158 * addresses - control and data.
159 * The H8 can determine which address was
160 * written by examining the C/D bit in
161 * the status register.
162 * ODRn - Output Data Register - read-only for Solaris.
163 * A read has the side effect of acknowledging
164 * interrupts.
165 * STRn - Status Register - read-only for Solaris.
169 * In terms of host access to this the Input and Output data registers are
170 * mapped at the same address.
172 #define H8_IDRD 0
173 #define H8_IDRC 1
174 #define H8_ODR 0
175 #define H8_STR 1
177 #define H8_STR_OBF 0x01 /* data available in ODR */
178 #define H8_STR_IBF 0x02 /* data for H8 in IDR */
179 #define H8_STR_IDRC 0x08 /* last write to IDR was to IDRC */
180 /* 0=data, 1=command */
181 #define H8_STR_BUSY 0x04 /* H8 busy processing command */
182 #define H8_STR_TOKENPROTOCOL 0x80 /* token-passing protocol */
185 * Packet format ...
187 #define BSCBUS_MASK 0xc0 /* Byte-type bits */
188 #define BSCBUS_PARAM 0x00 /* Parameter byte: 0b0xxxxxxx */
189 #define BSCBUS_LAST 0x80 /* Last byte of packet */
190 #define BSCBUS_CMD 0x80 /* Command byte: 0b10###XWV */
191 #define BSCBUS_STATUS 0xc0 /* Status byte: 0b11###AEV */
193 #define BSCBUS_SEQ 0x38 /* Sequence number bits */
194 #define BSCBUS_SEQ_LSB 0x08 /* Sequence number LSB */
195 #define BSCBUS_CMD_XADDR 0x04 /* Extended (2-byte) addressing */
196 #define BSCBUS_CMD_WRITE 0x02 /* Write command */
197 #define BSCBUS_CMD_WMSB 0x01 /* Set MSB on Write */
198 #define BSCBUS_CMD_READ 0x01 /* Read command */
199 #define BSCBUS_CMD_NOP 0x00 /* NOP command */
201 #define BSCBUS_STATUS_ASYNC 0x04 /* Asynchronous event pending */
202 #define BSCBUS_STATUS_ERR 0x02 /* Error in command processing */
203 #define BSCBUS_STATUS_MSB 0x01 /* MSB of Value read */
205 #define BSCBUS_VREG_LO(x) ((x) & ((1 << 7) - 1))
206 #define BSCBUS_VREG_HI(x) ((x) >> 7)
208 #define BSCBUS_BUFSIZE 8
210 #define BSCBUS_CHANNEL_TO_OFFSET(chno) ((chno) * 2) /* Register offset */
213 * Time periods, in nanoseconds
215 * Note that LOMBUS_ONE_SEC and some other time
216 * periods are defined in <sys/lombus.h>
218 #define BSCBUS_CMD_POLL (LOMBUS_ONE_SEC)
219 #define BSCBUS_CMD_POLLNOINTS (LOMBUS_ONE_SEC/20)
220 #define BSCBUS_HWRESET_POLL (LOMBUS_ONE_SEC/20)
221 #define BSCBUS_HWRESET_TIMEOUT (LOMBUS_ONE_SEC*2)
223 #define BSCBUS_DOG_PAT_POLL_LIMIT (1000)
224 #define BSCBUS_DOG_PAT_POLL (1)
225 #define BSCBUS_PAT_RETRY_LIMIT 5
228 * Local datatypes
230 enum bscbus_cmdstate {
231 BSCBUS_CMDSTATE_IDLE, /* No transaction in progress */
232 BSCBUS_CMDSTATE_BUSY, /* Setting up command */
233 BSCBUS_CMDSTATE_CLEARING, /* Clearing firmware busy status */
234 BSCBUS_CMDSTATE_SENDING, /* Waiting to send data to f/w */
235 BSCBUS_CMDSTATE_PENDING, /* Waiting for ack from f/w */
236 BSCBUS_CMDSTATE_WAITING, /* Waiting for status from f/w */
237 BSCBUS_CMDSTATE_READY, /* Status received/command done */
238 BSCBUS_CMDSTATE_ERROR /* Command failed with error */
241 struct bscbus_channel_state {
242 /* Changes to these are protected by the instance ch_mutex mutex */
243 struct bscbus_state *ssp;
244 uint8_t *ch_regs;
245 ddi_acc_handle_t ch_handle; /* per channel access handle */
246 unsigned int chno;
247 unsigned int map_count; /* Number of mappings to channel */
248 boolean_t map_dog; /* channel is mapped for watchdog */
251 * Flag to indicate that we've incurred a hardware fault on
252 * accesses to the H8; once this is set, we fake all further
253 * accesses in order not to provoke additional bus errors.
255 boolean_t xio_fault;
258 * Data protected by the dog_mutex: the watchdog-patting
259 * protocol data (since the dog can be patted from a high-level
260 * cyclic), and the interrupt-enabled flag.
262 kmutex_t dog_mutex[1];
263 unsigned int pat_retry_count;
264 unsigned int pat_fail_count;
267 * Serial protocol state data, protected by lo_mutex
268 * (which is initialised using <lo_iblk>)
270 kmutex_t lo_mutex[1];
271 ddi_iblock_cookie_t lo_iblk;
272 kcondvar_t lo_cv[1];
273 int unclaimed_count;
275 volatile enum bscbus_cmdstate cmdstate;
276 clock_t deadline;
277 clock_t poll_hz;
278 boolean_t interrupt_failed;
279 uint8_t cmdbuf[BSCBUS_BUFSIZE];
280 uint8_t *cmdp; /* Points to last tx'd in cmdbuf */
281 uint8_t reply[BSCBUS_BUFSIZE];
282 uint8_t async;
283 uint8_t index;
284 uint8_t result;
285 uint8_t sequence;
286 uint32_t error;
289 #define BSCBUS_TX_PENDING(csp) ((csp)->cmdp > (csp)->cmdbuf)
292 * This driver's soft-state structure
295 struct bscbus_state {
297 * Configuration data, set during attach
299 dev_info_t *dip;
300 major_t majornum;
301 int instance;
303 ddi_acc_handle_t h8_handle;
304 uint8_t *h8_regs;
307 * Parameters derived from .conf properties
309 uint32_t debug;
312 * Flag to indicate that we are using per channel
313 * mapping of the register sets and interrupts.
314 * reg set 0 is chan 0
315 * reg set 1 is chan 1 ...
317 * Interrupts are specified in that order but later
318 * channels may not have interrupts.
320 boolean_t per_channel_regs;
323 * channel state data, protected by ch_mutex
324 * channel claim/release requests are protected by this mutex.
326 kmutex_t ch_mutex[1];
327 struct bscbus_channel_state channel[BSCBUS_MAX_CHANNELS];
329 #ifdef BSCBUS_LOGSTATUS
331 * Command logging buffer for recording transactions with the
332 * BSC. This is useful for debugging failed transactions and other
333 * such funnies.
335 bsc_cmd_log_t *cmd_log;
336 uint32_t cmd_log_idx;
337 uint32_t cmd_log_size;
338 uint32_t cmd_log_flags;
339 #endif /* BSCBUS_LOGSTATUS */
343 * The auxiliary structure attached to each child
344 * (the child's parent-private-data points to this).
346 struct bscbus_child_info {
347 lombus_regspec_t *rsp;
348 int nregs;
351 #ifdef BSCBUS_LOGSTATUS
352 void bscbus_cmd_log(struct bscbus_channel_state *, bsc_cmd_stamp_t,
353 uint8_t, uint8_t);
354 #else /* BSCBUS_LOGSTATUS */
355 #define bscbus_cmd_log(state, stamp, status, data)
356 #endif /* BSCBUS_LOGSTATUS */
360 * Local data
363 static void *bscbus_statep;
365 static major_t bscbus_major = NOMAJOR;
367 static ddi_device_acc_attr_t bscbus_dev_acc_attr[1] = {
368 DDI_DEVICE_ATTR_V0,
369 DDI_STRUCTURE_LE_ACC,
370 DDI_STRICTORDER_ACC
375 * General utility routines ...
378 #ifdef DEBUG
379 static void
380 bscbus_trace(struct bscbus_channel_state *csp, char code, const char *caller,
381 const char *fmt, ...)
383 char buf[256];
384 char *p;
385 va_list va;
387 if (csp->ssp->debug & (1 << (code-'@'))) {
388 p = buf;
389 (void) snprintf(p, sizeof (buf) - (p - buf),
390 "%s/%s: ", MYNAME, caller);
391 p += strlen(p);
393 va_start(va, fmt);
394 (void) vsnprintf(p, sizeof (buf) - (p - buf), fmt, va);
395 va_end(va);
397 buf[sizeof (buf) - 1] = '\0';
398 (void) strlog(csp->ssp->majornum, csp->ssp->instance,
399 code, SL_TRACE, buf);
402 #else /* DEBUG */
403 #define bscbus_trace
404 #endif /* DEBUG */
406 static struct bscbus_state *
407 bscbus_getstate(dev_info_t *dip, int instance, const char *caller)
409 struct bscbus_state *ssp = NULL;
410 dev_info_t *sdip = NULL;
411 major_t dmaj = NOMAJOR;
413 if (dip != NULL) {
415 * Use the instance number from the <dip>; also,
416 * check that it really corresponds to this driver
418 instance = ddi_get_instance(dip);
419 dmaj = ddi_driver_major(dip);
420 if (bscbus_major == NOMAJOR && dmaj != NOMAJOR)
421 bscbus_major = dmaj;
422 else if (dmaj != bscbus_major) {
423 cmn_err(CE_WARN,
424 "%s: major number mismatch (%d vs. %d) in %s(),"
425 "probably due to child misconfiguration",
426 MYNAME, bscbus_major, dmaj, caller);
427 instance = -1;
431 if (instance >= 0)
432 ssp = ddi_get_soft_state(bscbus_statep, instance);
433 if (ssp != NULL) {
434 sdip = ssp->dip;
435 if (dip == NULL && sdip == NULL)
436 ssp = NULL;
437 else if (dip != NULL && sdip != NULL && sdip != dip) {
438 cmn_err(CE_WARN,
439 "%s: devinfo mismatch (%p vs. %p) in %s(), "
440 "probably due to child misconfiguration",
441 MYNAME, (void *)dip, (void *)sdip, caller);
442 ssp = NULL;
446 return (ssp);
450 * Lowest-level I/O register read/write
453 static void
454 bscbus_put_reg(struct bscbus_channel_state *csp, uint_t reg, uint8_t val)
456 if (csp->ch_handle != NULL && !csp->xio_fault) {
457 ddi_put8(csp->ch_handle,
458 csp->ch_regs + reg, val);
462 static uint8_t
463 bscbus_get_reg(struct bscbus_channel_state *csp, uint_t reg)
465 uint8_t val;
467 if (csp->ch_handle != NULL && !csp->xio_fault)
468 val = ddi_get8(csp->ch_handle,
469 csp->ch_regs + reg);
470 else
471 val = DUMMY_VALUE;
473 return (val);
476 static void
477 bscbus_check_fault_status(struct bscbus_channel_state *csp)
479 csp->xio_fault =
480 ddi_check_acc_handle(csp->ch_handle) != DDI_SUCCESS;
483 static boolean_t
484 bscbus_faulty(struct bscbus_channel_state *csp)
486 if (!csp->xio_fault)
487 bscbus_check_fault_status(csp);
488 return (csp->xio_fault);
492 * Write data into h8 registers
494 static void
495 bscbus_pat_dog(struct bscbus_channel_state *csp, uint8_t val)
497 uint8_t status;
498 uint32_t doglimit = BSCBUS_DOG_PAT_POLL_LIMIT;
500 bscbus_trace(csp, 'W', "bscbus_pat_dog:", "");
502 bscbus_cmd_log(csp, BSC_CMD_DOGPAT, 0, val);
503 status = bscbus_get_reg(csp, H8_STR);
504 while (status & H8_STR_IBF) {
505 if (csp->pat_retry_count > BSCBUS_PAT_RETRY_LIMIT) {
507 * Previous attempts to contact BSC have failed.
508 * Do not bother waiting for it to eat previous
509 * data.
510 * Pat anyway just in case the BSC is really alive
511 * and the IBF bit is lying.
513 bscbus_put_reg(csp, H8_IDRC, val);
514 bscbus_trace(csp, 'W', "bscbus_pat_dog:",
515 "retry count exceeded");
516 return;
518 if (--doglimit == 0) {
519 /* The BSC is not responding - give up */
520 csp->pat_fail_count++;
521 csp->pat_retry_count++;
522 /* Pat anyway just in case the BSC is really alive */
523 bscbus_put_reg(csp, H8_IDRC, val);
524 bscbus_trace(csp, 'W', "bscbus_pat_dog:",
525 "poll limit exceeded");
526 return;
528 drv_usecwait(BSCBUS_DOG_PAT_POLL);
529 status = bscbus_get_reg(csp, H8_STR);
531 bscbus_put_reg(csp, H8_IDRC, val);
532 csp->pat_retry_count = 0;
536 * State diagrams for how bscbus_process works.
537 * BSCBUS_CMDSTATE_IDLE No transaction in progress
538 * BSCBUS_CMDSTATE_BUSY Setting up command
539 * BSCBUS_CMDSTATE_CLEARING Clearing firmware busy status
540 * BSCBUS_CMDSTATE_SENDING Waiting to send data to f/w
541 * BSCBUS_CMDSTATE_PENDING Waiting for ack from f/w
542 * BSCBUS_CMDSTATE_WAITING Waiting for status from f/w
543 * BSCBUS_CMDSTATE_READY Status received/command done
544 * BSCBUS_CMDSTATE_ERROR Command failed with error
546 * +----------+
547 * | |
548 * | IDLE/BUSY|
549 * | (0/1) | abnormal
550 * +----------+ state
551 * | \ detected
552 * | \------>------+ +----<---+
553 * bsc | | | |
554 * is | V V |
555 * ready| +----------+ |
556 * | | | ^
557 * | | CLEARING | |
558 * | | (2) | |
559 * | +----------+ |
560 * | cleared / | \ | more to clear
561 * | / | \-->--+
562 * | +-------<-------/ V
563 * | | |
564 * V V |timeout
565 * +----------+ timeout |
566 * | |------>---------+--------+
567 * | SENDING | |
568 * | (3) |------<-------+ |
569 * +----------+ | V
570 * sent| \ send ^ack |
571 * last| \ next |received |
572 * | \ +----------+ |
573 * | \ | | |
574 * | \------>| PENDING |-->-+
575 * | | (4) | |
576 * | +----------+ |timeout
577 * | +---<----+ |
578 * | | | |
579 * V V | |
580 * +----------+ | |
581 * | | | |
582 * | WAITING | ^ |
583 * | (5) | | |
584 * +----------+ | |
585 * | | |more | |
586 * | V |required| |
587 * done| | +--->----+ |
588 * | +--->--------------+ +---<---+
589 * | error/timeout | |
590 * V V V
591 * +----------+ +----------+
592 * | | | |
593 * | READY | | ERROR |
594 * | (7) | | (6) |
595 * +----------+ +----------+
596 * | |
597 * V V
598 * | |
599 * +------>---+---<------+
602 * Back to
603 * Idle
606 static void
607 bscbus_process_sending(struct bscbus_channel_state *csp, uint8_t status)
610 * When we get here we actually expect H8_STR_IBF to
611 * be clear but we check just in case of problems.
613 ASSERT(BSCBUS_TX_PENDING(csp));
614 if (!(status & H8_STR_IBF)) {
615 bscbus_put_reg(csp, H8_IDRD, *--csp->cmdp);
616 bscbus_trace(csp, 'P', "bscbus_process_sending",
617 "state %d; val $%x",
618 csp->cmdstate, *csp->cmdp);
619 if (!BSCBUS_TX_PENDING(csp)) {
620 bscbus_cmd_log(csp, BSC_CMD_SENT,
621 status, *csp->cmdp);
622 /* No more pending - move to waiting state */
623 bscbus_trace(csp, 'P', "bscbus_process_sending",
624 "moving to waiting");
625 csp->cmdstate = BSCBUS_CMDSTATE_WAITING;
626 /* Extend deadline because time has moved on */
627 csp->deadline = ddi_get_lbolt() +
628 drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
629 } else {
630 /* Wait for ack of this byte */
631 bscbus_cmd_log(csp, BSC_CMD_SENDING,
632 status, *csp->cmdp);
633 csp->cmdstate = BSCBUS_CMDSTATE_PENDING;
634 bscbus_trace(csp, 'P', "bscbus_process_sending",
635 "moving to pending");
640 static void
641 bscbus_process_clearing(struct bscbus_channel_state *csp,
642 uint8_t status, uint8_t data)
645 * We only enter this state if H8_STR_BUSY was set when
646 * we started the transaction. We just ignore all received
647 * data until we see OBF set AND BUSY cleared.
648 * It is not good enough to see BUSY clear on its own
650 if ((status & H8_STR_OBF) && !(status & H8_STR_BUSY)) {
651 bscbus_cmd_log(csp, BSC_CMD_CLEARED, status, data);
652 csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
653 /* Throw away any data received up until now */
654 bscbus_trace(csp, 'P', "bscbus_process_clearing",
655 "busy cleared");
657 * Send the next byte immediately.
658 * At this stage we should clear the OBF flag because that
659 * data has been used. IBF is still valid so do not clear that.
661 status &= ~(H8_STR_OBF);
662 bscbus_process_sending(csp, status);
663 } else {
664 if (status & H8_STR_OBF) {
665 bscbus_cmd_log(csp, BSC_CMD_CLEARING, status, data);
670 static void
671 bscbus_process_pending(struct bscbus_channel_state *csp, uint8_t status)
673 /* We are waiting for an acknowledgement of a byte */
674 if (status & H8_STR_OBF) {
675 bscbus_cmd_log(csp, BSC_CMD_PENDING,
676 status, *csp->cmdp);
677 bscbus_trace(csp, 'P', "bscbus_process_pending",
678 "moving to sending");
679 csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
681 * Send the next byte immediately.
682 * At this stage we should clear the OBF flag because that
683 * data has been used. IBF is still valid so do not clear that.
685 status &= ~(H8_STR_OBF);
686 bscbus_process_sending(csp, status);
690 static boolean_t
691 bscbus_process_waiting(struct bscbus_channel_state *csp,
692 uint8_t status, uint8_t data)
694 uint8_t rcvd = 0;
695 boolean_t ready = B_FALSE;
696 uint8_t tmp;
698 if (status & H8_STR_OBF) {
699 csp->reply[rcvd = csp->index] = data;
700 if (++rcvd < BSCBUS_BUFSIZE)
701 csp->index = rcvd;
703 bscbus_trace(csp, 'D', "bscbus_process_waiting",
704 "rcvd %d: $%02x $%02x $%02x $%02x $%02x $%02x $%02x $%02x",
705 rcvd,
706 csp->reply[0], csp->reply[1],
707 csp->reply[2], csp->reply[3],
708 csp->reply[4], csp->reply[5],
709 csp->reply[6], csp->reply[7]);
712 if (rcvd == 0) {
714 * No bytes received this time through (though there
715 * might be a partial packet sitting in the buffer).
717 /* EMPTY */
719 } else if (rcvd >= BSCBUS_BUFSIZE) {
721 * Buffer overflow; discard the data & treat as an error
722 * (even if the last byte read did claim to terminate a
723 * packet, it can't be a valid one 'cos it's too long!)
725 bscbus_cmd_log(csp, BSC_CMD_ERROR_OFLOW, status, data);
726 csp->index = 0;
727 csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
728 csp->error = LOMBUS_ERR_OFLOW;
729 ready = B_TRUE;
730 } else if ((data & BSCBUS_LAST) == 0) {
732 * Packet not yet complete; leave the partial packet in
733 * the buffer for later ...
735 bscbus_cmd_log(csp, BSC_CMD_REPLY, status, data);
736 } else if ((data & BSCBUS_MASK) != BSCBUS_STATUS) {
737 /* Invalid "status" byte - maybe an echo of the command? */
738 bscbus_cmd_log(csp, BSC_CMD_ERROR_STATUS, status, data);
740 csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
741 csp->error = LOMBUS_ERR_BADSTATUS;
742 ready = B_TRUE;
743 } else if ((data & BSCBUS_SEQ) != csp->sequence) {
744 /* Wrong sequence number! Flag this as an error */
745 bscbus_cmd_log(csp, BSC_CMD_ERROR_SEQ, status, data);
747 csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
748 csp->error = LOMBUS_ERR_SEQUENCE;
749 ready = B_TRUE;
750 } else {
752 * Finally, we know that's it's a valid reply to our
753 * last command. Update the ASYNC status, derive the
754 * reply parameter (if any), and check the ERROR bit
755 * to find out what the parameter means.
757 * Note that not all the values read/assigned here
758 * are meaningful, but it doesn't matter; the waiting
759 * thread will know which one(s) it should check.
761 bscbus_cmd_log(csp, BSC_CMD_COMPLETE, status, data);
762 csp->async = (data & BSCBUS_STATUS_ASYNC) ? 1 : 0;
764 tmp = ((data & BSCBUS_STATUS_MSB) ? 0x80 : 0) | csp->reply[0];
765 if (data & BSCBUS_STATUS_ERR) {
766 csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
767 csp->error = tmp;
768 } else {
769 csp->cmdstate = BSCBUS_CMDSTATE_READY;
770 csp->result = tmp;
772 ready = B_TRUE;
774 return (ready);
778 * Packet receive handler
780 * This routine should be called from the low-level softint,
781 * or bscbus_cmd() (for polled operation), with the
782 * low-level mutex already held.
784 static void
785 bscbus_process(struct bscbus_channel_state *csp,
786 uint8_t status, uint8_t data)
788 boolean_t ready = B_FALSE;
790 ASSERT(mutex_owned(csp->lo_mutex));
792 if ((status & H8_STR_OBF) || (status & H8_STR_IBF)) {
793 bscbus_trace(csp, 'D', "bscbus_process",
794 "state %d; error $%x",
795 csp->cmdstate, csp->error);
798 switch (csp->cmdstate) {
799 case BSCBUS_CMDSTATE_CLEARING:
800 bscbus_process_clearing(csp, status, data);
801 break;
802 case BSCBUS_CMDSTATE_SENDING:
803 bscbus_process_sending(csp, status);
804 break;
805 case BSCBUS_CMDSTATE_PENDING:
806 bscbus_process_pending(csp, status);
807 break;
808 case BSCBUS_CMDSTATE_WAITING:
809 ready = bscbus_process_waiting(csp, status, data);
810 break;
811 default:
812 /* Nothing to do */
813 break;
817 * Check for timeouts - but only if the command has not yet
818 * completed (ready is true when command completes in this
819 * call to bscbus_process OR cmdstate is READY or ERROR if
820 * this is a spurious call to bscbus_process i.e. a spurious
821 * interrupt)
823 if (!ready &&
824 ((ddi_get_lbolt() - csp->deadline) > 0) &&
825 csp->cmdstate != BSCBUS_CMDSTATE_READY &&
826 csp->cmdstate != BSCBUS_CMDSTATE_ERROR) {
827 bscbus_trace(csp, 'P', "bscbus_process",
828 "timeout previous state %d; error $%x",
829 csp->cmdstate, csp->error);
830 bscbus_cmd_log(csp, BSC_CMD_ERROR_TOUT, status, data);
831 if (csp->cmdstate == BSCBUS_CMDSTATE_CLEARING) {
832 /* Move onto sending because busy might be stuck */
833 csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
834 /* Extend timeout relative to original start time */
835 csp->deadline += drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
836 } else if (csp->cmdstate != BSCBUS_CMDSTATE_IDLE) {
837 csp->cmdstate = BSCBUS_CMDSTATE_ERROR;
838 csp->error = LOMBUS_ERR_TIMEOUT;
840 ready = B_TRUE;
843 if ((status & H8_STR_OBF) || (status & H8_STR_IBF) || ready) {
844 bscbus_trace(csp, 'D', "bscbus_process",
845 "last $%02x; state %d; error $%x; ready %d",
846 data, csp->cmdstate, csp->error, ready);
848 if (ready)
849 cv_broadcast(csp->lo_cv);
852 static uint_t
853 bscbus_hwintr(caddr_t arg)
855 struct bscbus_channel_state *csp = (void *)arg;
857 uint8_t status;
858 uint8_t data = 0xb0 /* Dummy value */;
860 mutex_enter(csp->lo_mutex);
862 * Read the registers to ensure that the interrupt is cleared.
863 * Status must be read first because reading data changes the
864 * status.
865 * We always read the data because that clears the interrupt down.
866 * This is horrible hardware semantics but we have to do it!
868 status = bscbus_get_reg(csp, H8_STR);
869 data = bscbus_get_reg(csp, H8_ODR);
870 if (!(status & H8_STR_OBF)) {
871 bscbus_cmd_log(csp, BSC_CMD_V1INTRUNCL, status, data);
872 csp->unclaimed_count++;
873 } else {
874 bscbus_cmd_log(csp, BSC_CMD_V1INTR, status, data);
876 if (status & H8_STR_TOKENPROTOCOL) {
877 bscbus_process(csp, status, data);
878 if (csp->interrupt_failed) {
879 bscbus_trace(csp, 'I', "bscbus_hwintr:",
880 "interrupt fault cleared channel %d", csp->chno);
881 csp->interrupt_failed = B_FALSE;
882 csp->poll_hz = drv_usectohz(BSCBUS_CMD_POLL / 1000);
886 mutex_exit(csp->lo_mutex);
887 return (DDI_INTR_CLAIMED);
890 void
891 bscbus_poll(struct bscbus_channel_state *csp)
894 * This routine is only called if we timeout in userland
895 * waiting for an interrupt. This generally means that we have
896 * lost interrupt capabilities or that something has gone
897 * wrong. In this case we are allowed to access the hardware
898 * and read the data register if necessary.
899 * If interrupts return then recovery actions should mend us!
901 uint8_t status;
902 uint8_t data = 0xfa; /* Dummy value */
904 ASSERT(mutex_owned(csp->lo_mutex));
906 /* Should look for data to receive */
907 status = bscbus_get_reg(csp, H8_STR);
908 if (status & H8_STR_OBF) {
909 /* There is data available */
910 data = bscbus_get_reg(csp, H8_ODR);
911 bscbus_cmd_log(csp, BSC_CMD_PROCESS, status, data);
913 bscbus_process(csp, status, data);
917 * Serial protocol
919 * This routine builds a command and sets it in progress.
921 static uint8_t
922 bscbus_cmd(HANDLE_TYPE *hdlp, ptrdiff_t vreg, uint_t val, uint_t cmd)
924 struct bscbus_channel_state *csp;
925 clock_t start;
926 uint8_t status;
929 * First of all, wait for the interface to be available.
931 * NOTE: we blow through all the mutex/cv/state checking and
932 * preempt any command in progress if the system is panicking!
934 csp = HANDLE_PRIVATE(hdlp);
935 mutex_enter(csp->lo_mutex);
936 while (csp->cmdstate != BSCBUS_CMDSTATE_IDLE && !ddi_in_panic())
937 cv_wait(csp->lo_cv, csp->lo_mutex);
939 csp->cmdstate = BSCBUS_CMDSTATE_BUSY;
940 csp->sequence = (csp->sequence + BSCBUS_SEQ_LSB) & BSCBUS_SEQ;
943 * We have exclusive ownership, so assemble the command (backwards):
945 * [byte 0] Command: modified by XADDR and/or WMSB bits
946 * [Optional] Parameter: Value to write (low 7 bits)
947 * [Optional] Parameter: Register number (high 7 bits)
948 * [Optional] Parameter: Register number (low 7 bits)
950 csp->cmdp = &csp->cmdbuf[0];
951 *csp->cmdp++ = BSCBUS_CMD | csp->sequence | cmd;
952 switch (cmd) {
953 case BSCBUS_CMD_WRITE:
954 *csp->cmdp++ = val & 0x7f;
955 if (val >= 0x80)
956 csp->cmdbuf[0] |= BSCBUS_CMD_WMSB;
957 /*FALLTHRU*/
958 case BSCBUS_CMD_READ:
959 if (BSCBUS_VREG_HI(vreg) != 0) {
960 *csp->cmdp++ = BSCBUS_VREG_HI(vreg);
961 csp->cmdbuf[0] |= BSCBUS_CMD_XADDR;
963 *csp->cmdp++ = BSCBUS_VREG_LO(vreg);
964 /*FALLTHRU*/
965 case BSCBUS_CMD_NOP:
966 break;
970 * Check and update the H8 h/w fault status before accessing
971 * the chip registers. If there's a (new or previous) fault,
972 * we'll run through the protocol but won't really touch the
973 * hardware and all commands will timeout. If a previously
974 * discovered fault has now gone away (!), then we can (try to)
975 * proceed with the new command (probably a probe).
977 bscbus_check_fault_status(csp);
980 * Prepare for the command (to be processed by the interrupt
981 * handler and/or polling loop below), and wait for a response
982 * or timeout.
984 start = ddi_get_lbolt();
985 csp->deadline = start + drv_usectohz(LOMBUS_CMD_TIMEOUT/1000);
986 csp->error = 0;
987 csp->index = 0;
988 csp->result = DUMMY_VALUE;
990 status = bscbus_get_reg(csp, H8_STR);
991 if (status & H8_STR_BUSY) {
992 bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0xfd);
994 * Must ensure that the busy state has cleared before
995 * sending the command
997 csp->cmdstate = BSCBUS_CMDSTATE_CLEARING;
998 bscbus_trace(csp, 'P', "bscbus_cmd",
999 "h8 reporting status (%x) busy - clearing", status);
1000 } else {
1001 /* It is clear to send the command immediately */
1002 csp->cmdstate = BSCBUS_CMDSTATE_SENDING;
1003 bscbus_trace(csp, 'P', "bscbus_cmd",
1004 "sending first byte of command, status %x", status);
1005 bscbus_poll(csp);
1008 csp->poll_hz = drv_usectohz(
1009 (csp->interrupt_failed ?
1010 BSCBUS_CMD_POLLNOINTS : BSCBUS_CMD_POLL) / 1000);
1012 while ((csp->cmdstate != BSCBUS_CMDSTATE_READY) &&
1013 (csp->cmdstate != BSCBUS_CMDSTATE_ERROR)) {
1014 ASSERT(csp->cmdstate != BSCBUS_CMDSTATE_IDLE);
1016 if ((cv_reltimedwait(csp->lo_cv, csp->lo_mutex,
1017 csp->poll_hz, TR_CLOCK_TICK) == -1) &&
1018 csp->cmdstate != BSCBUS_CMDSTATE_READY &&
1019 csp->cmdstate != BSCBUS_CMDSTATE_ERROR) {
1020 if (!csp->interrupt_failed) {
1021 bscbus_trace(csp, 'I', "bscbus_cmd:",
1022 "interrupt_failed channel %d", csp->chno);
1023 csp->interrupt_failed = B_TRUE;
1024 csp->poll_hz = drv_usectohz(
1025 BSCBUS_CMD_POLLNOINTS / 1000);
1027 bscbus_poll(csp);
1032 * The return value may not be meaningful but retrieve it anyway
1034 val = csp->result;
1035 if (bscbus_faulty(csp)) {
1036 val = DUMMY_VALUE;
1037 HANDLE_FAULT(hdlp) = LOMBUS_ERR_SIOHW;
1038 } else if (csp->cmdstate != BSCBUS_CMDSTATE_READY) {
1040 * Some problem here ... transfer the error code from
1041 * the per-instance state to the per-handle fault flag.
1042 * The error code shouldn't be zero!
1044 if (csp->error != 0)
1045 HANDLE_FAULT(hdlp) = csp->error;
1046 else
1047 HANDLE_FAULT(hdlp) = LOMBUS_ERR_BADERRCODE;
1051 * All done now!
1053 csp->index = 0;
1054 csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
1055 cv_broadcast(csp->lo_cv);
1056 mutex_exit(csp->lo_mutex);
1058 return (val);
1062 * Space 0 - LOM virtual register access
1063 * Only 8-bit accesses are supported.
1065 static uint8_t
1066 bscbus_vreg_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1068 ptrdiff_t offset;
1071 * Check the offset that the caller has added to the base address
1072 * against the length of the mapping originally requested.
1074 offset = ADDR_TO_OFFSET(addr, hdlp);
1075 if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1077 * Invalid access - flag a fault and return a dummy value
1079 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1080 return (DUMMY_VALUE);
1084 * Derive the virtual register number and run the command
1086 return (bscbus_cmd(hdlp, ADDR_TO_VREG(addr), 0, BSCBUS_CMD_READ));
1089 static void
1090 bscbus_vreg_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1092 ptrdiff_t offset;
1095 * Check the offset that the caller has added to the base address
1096 * against the length of the mapping originally requested.
1098 offset = ADDR_TO_OFFSET(addr, hdlp);
1099 if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1101 * Invalid access - flag a fault and return
1103 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1104 return;
1108 * Derive the virtual register number and run the command
1110 (void) bscbus_cmd(hdlp, ADDR_TO_VREG(addr), val, BSCBUS_CMD_WRITE);
1113 static void
1114 bscbus_vreg_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1115 uint8_t *dev_addr, size_t repcount, uint_t flags)
1117 size_t inc;
1119 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1120 for (; repcount--; dev_addr += inc)
1121 *host_addr++ = bscbus_vreg_get8(hdlp, dev_addr);
1124 static void
1125 bscbus_vreg_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1126 uint8_t *dev_addr, size_t repcount, uint_t flags)
1128 size_t inc;
1130 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1131 for (; repcount--; dev_addr += inc)
1132 bscbus_vreg_put8(hdlp, dev_addr, *host_addr++);
1137 * Space 1 - LOM watchdog pat register access
1138 * Only 8-bit accesses are supported.
1140 * Reads have no effect and return 0.
1142 * Multi-byte reads (using ddi_rep_get8(9F)) are a fairly inefficient
1143 * way of zeroing the destination area ;-) and still won't pat the dog.
1145 * Multi-byte writes (using ddi_rep_put8(9F)) will almost certainly
1146 * only count as a single pat, no matter how many bytes the caller
1147 * says to write, as the inter-pat time is VERY long compared with
1148 * the time it will take to read the memory source area.
1151 static uint8_t
1152 bscbus_pat_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1154 ptrdiff_t offset;
1157 * Check the offset that the caller has added to the base address
1158 * against the length of the mapping originally requested.
1160 offset = ADDR_TO_OFFSET(addr, hdlp);
1161 if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1163 * Invalid access - flag a fault and return a dummy value
1165 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1166 return (DUMMY_VALUE);
1169 return (0);
1172 static void
1173 bscbus_pat_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1175 struct bscbus_channel_state *csp;
1176 ptrdiff_t offset;
1179 * Check the offset that the caller has added to the base address
1180 * against the length of the mapping originally requested.
1182 offset = ADDR_TO_OFFSET(addr, hdlp);
1183 if (offset < 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1185 * Invalid access - flag a fault and return
1187 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1188 return;
1191 csp = HANDLE_PRIVATE(hdlp);
1192 mutex_enter(csp->dog_mutex);
1193 bscbus_pat_dog(csp, val);
1194 mutex_exit(csp->dog_mutex);
1197 static void
1198 bscbus_pat_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1199 uint8_t *dev_addr, size_t repcount, uint_t flags)
1201 size_t inc;
1203 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1204 for (; repcount--; dev_addr += inc)
1205 *host_addr++ = bscbus_pat_get8(hdlp, dev_addr);
1208 static void
1209 bscbus_pat_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1210 uint8_t *dev_addr, size_t repcount, uint_t flags)
1212 size_t inc;
1214 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1215 for (; repcount--; dev_addr += inc)
1216 bscbus_pat_put8(hdlp, dev_addr, *host_addr++);
1221 * Space 2 - LOM async event flag register access
1222 * Only 16-bit accesses are supported.
1224 static uint16_t
1225 bscbus_event_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
1227 struct bscbus_channel_state *csp;
1228 ptrdiff_t offset;
1231 * Check the offset that the caller has added to the base address
1232 * against the length of the mapping orignally requested.
1234 offset = ADDR_TO_OFFSET(addr, hdlp);
1235 if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1237 * Invalid access - flag a fault and return a dummy value
1239 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1240 return (DUMMY_VALUE);
1244 * Return the value of the asynchronous-event-pending flag
1245 * as passed back by the LOM at the end of the last command.
1247 csp = HANDLE_PRIVATE(hdlp);
1248 return (csp->async);
1251 static void
1252 bscbus_event_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
1254 ptrdiff_t offset;
1256 _NOTE(ARGUNUSED(val))
1259 * Check the offset that the caller has added to the base address
1260 * against the length of the mapping originally requested.
1262 offset = ADDR_TO_OFFSET(addr, hdlp);
1263 if (offset < 0 || (offset%2) != 0 || offset >= HANDLE_MAPLEN(hdlp)) {
1265 * Invalid access - flag a fault and return
1267 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_NUM;
1268 return;
1272 * The user can't overwrite the asynchronous-event-pending flag!
1274 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_RO;
1277 static void
1278 bscbus_event_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1279 uint16_t *dev_addr, size_t repcount, uint_t flags)
1281 size_t inc;
1283 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1284 for (; repcount--; dev_addr += inc)
1285 *host_addr++ = bscbus_event_get16(hdlp, dev_addr);
1288 static void
1289 bscbus_event_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1290 uint16_t *dev_addr, size_t repcount, uint_t flags)
1292 size_t inc;
1294 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1295 for (; repcount--; dev_addr += inc)
1296 bscbus_event_put16(hdlp, dev_addr, *host_addr++);
1301 * All spaces - access handle fault information
1302 * Only 32-bit accesses are supported.
1304 static uint32_t
1305 bscbus_meta_get32(HANDLE_TYPE *hdlp, uint32_t *addr)
1307 struct bscbus_channel_state *csp;
1308 ptrdiff_t offset;
1311 * Derive the offset that the caller has added to the base
1312 * address originally returned, and use it to determine
1313 * which meta-register is to be accessed ...
1315 offset = ADDR_TO_OFFSET(addr, hdlp);
1316 switch (offset) {
1317 case LOMBUS_FAULT_REG:
1319 * This meta-register provides a code for the most
1320 * recent virtual register access fault, if any.
1322 return (HANDLE_FAULT(hdlp));
1324 case LOMBUS_PROBE_REG:
1326 * Reading this meta-register clears any existing fault
1327 * (at the virtual, not the hardware access layer), then
1328 * runs a NOP command and returns the fault code from that.
1330 HANDLE_FAULT(hdlp) = 0;
1331 (void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
1332 return (HANDLE_FAULT(hdlp));
1334 case LOMBUS_ASYNC_REG:
1336 * Obsolescent - but still supported for backwards
1337 * compatibility. This is an alias for the newer
1338 * LOMBUS_EVENT_REG, but doesn't require a separate
1339 * "reg" entry and ddi_regs_map_setup() call.
1341 * It returns the value of the asynchronous-event-pending
1342 * flag as passed back by the BSC at the end of the last
1343 * completed command.
1345 csp = HANDLE_PRIVATE(hdlp);
1346 return (csp->async);
1348 default:
1350 * Invalid access - flag a fault and return a dummy value
1352 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1353 return (DUMMY_VALUE);
1357 static void
1358 bscbus_meta_put32(HANDLE_TYPE *hdlp, uint32_t *addr, uint32_t val)
1360 ptrdiff_t offset;
1363 * Derive the offset that the caller has added to the base
1364 * address originally returned, and use it to determine
1365 * which meta-register is to be accessed ...
1367 offset = ADDR_TO_OFFSET(addr, hdlp);
1368 switch (offset) {
1369 case LOMBUS_FAULT_REG:
1371 * This meta-register contains a code for the most
1372 * recent virtual register access fault, if any.
1373 * It can be cleared simply by writing 0 to it.
1375 HANDLE_FAULT(hdlp) = val;
1376 return;
1378 case LOMBUS_PROBE_REG:
1380 * Writing this meta-register clears any existing fault
1381 * (at the virtual, not the hardware acess layer), then
1382 * runs a NOP command. The caller can check the fault
1383 * code later if required.
1385 HANDLE_FAULT(hdlp) = 0;
1386 (void) bscbus_cmd(hdlp, 0, 0, BSCBUS_CMD_NOP);
1387 return;
1389 default:
1391 * Invalid access - flag a fault
1393 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1394 return;
1398 static void
1399 bscbus_meta_rep_get32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
1400 uint32_t *dev_addr, size_t repcount, uint_t flags)
1402 size_t inc;
1404 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1405 for (; repcount--; dev_addr += inc)
1406 *host_addr++ = bscbus_meta_get32(hdlp, dev_addr);
1409 static void
1410 bscbus_meta_rep_put32(HANDLE_TYPE *hdlp, uint32_t *host_addr,
1411 uint32_t *dev_addr, size_t repcount, uint_t flags)
1413 size_t inc;
1415 inc = (flags & DDI_DEV_AUTOINCR) ? 1 : 0;
1416 for (; repcount--; dev_addr += inc)
1417 bscbus_meta_put32(hdlp, dev_addr, *host_addr++);
1422 * Finally, some dummy functions for all unsupported access
1423 * space/size/mode combinations ...
1425 static uint8_t
1426 bscbus_no_get8(HANDLE_TYPE *hdlp, uint8_t *addr)
1428 _NOTE(ARGUNUSED(addr))
1431 * Invalid access - flag a fault and return a dummy value
1433 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1434 return (DUMMY_VALUE);
1437 static void
1438 bscbus_no_put8(HANDLE_TYPE *hdlp, uint8_t *addr, uint8_t val)
1440 _NOTE(ARGUNUSED(addr, val))
1443 * Invalid access - flag a fault
1445 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1448 static void
1449 bscbus_no_rep_get8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1450 uint8_t *dev_addr, size_t repcount, uint_t flags)
1452 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1455 * Invalid access - flag a fault
1457 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1460 static void
1461 bscbus_no_rep_put8(HANDLE_TYPE *hdlp, uint8_t *host_addr,
1462 uint8_t *dev_addr, size_t repcount, uint_t flags)
1464 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1467 * Invalid access - flag a fault
1469 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1472 static uint16_t
1473 bscbus_no_get16(HANDLE_TYPE *hdlp, uint16_t *addr)
1475 _NOTE(ARGUNUSED(addr))
1478 * Invalid access - flag a fault and return a dummy value
1480 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1481 return (DUMMY_VALUE);
1484 static void
1485 bscbus_no_put16(HANDLE_TYPE *hdlp, uint16_t *addr, uint16_t val)
1487 _NOTE(ARGUNUSED(addr, val))
1490 * Invalid access - flag a fault
1492 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1495 static void
1496 bscbus_no_rep_get16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1497 uint16_t *dev_addr, size_t repcount, uint_t flags)
1499 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1502 * Invalid access - flag a fault
1504 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1507 static void
1508 bscbus_no_rep_put16(HANDLE_TYPE *hdlp, uint16_t *host_addr,
1509 uint16_t *dev_addr, size_t repcount, uint_t flags)
1511 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1514 * Invalid access - flag a fault
1516 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1519 static uint64_t
1520 bscbus_no_get64(HANDLE_TYPE *hdlp, uint64_t *addr)
1522 _NOTE(ARGUNUSED(addr))
1525 * Invalid access - flag a fault and return a dummy value
1527 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1528 return (DUMMY_VALUE);
1531 static void
1532 bscbus_no_put64(HANDLE_TYPE *hdlp, uint64_t *addr, uint64_t val)
1534 _NOTE(ARGUNUSED(addr, val))
1537 * Invalid access - flag a fault
1539 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1542 static void
1543 bscbus_no_rep_get64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
1544 uint64_t *dev_addr, size_t repcount, uint_t flags)
1546 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1549 * Invalid access - flag a fault
1551 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1554 static void
1555 bscbus_no_rep_put64(HANDLE_TYPE *hdlp, uint64_t *host_addr,
1556 uint64_t *dev_addr, size_t repcount, uint_t flags)
1558 _NOTE(ARGUNUSED(host_addr, dev_addr, repcount, flags))
1561 * Invalid access - flag a fault
1563 HANDLE_FAULT(hdlp) = LOMBUS_ERR_REG_SIZE;
1566 static int
1567 bscbus_acc_fault_check(HANDLE_TYPE *hdlp)
1569 return (HANDLE_FAULT(hdlp) != 0);
1573 * Hardware setup - ensure that there are no pending transactions and
1574 * hence no pending interrupts. We do this be ensuring that the BSC is
1575 * not reporting a busy condition and that it does not have any data
1576 * pending in its output buffer.
1577 * This is important because if we have pending interrupts at attach
1578 * time Solaris will hang due to bugs in ddi_get_iblock_cookie.
1580 static void
1581 bscbus_hw_reset(struct bscbus_channel_state *csp)
1583 int64_t timeout;
1584 uint8_t status;
1586 if (csp->map_count == 0) {
1587 /* No-one using this instance - no need to reset hardware */
1588 return;
1591 bscbus_trace(csp, 'R', "bscbus_hw_reset",
1592 "resetting channel %d", csp->chno);
1594 status = bscbus_get_reg(csp, H8_STR);
1595 if (status & H8_STR_BUSY) {
1597 * Give the h8 time to complete a reply.
1598 * In practice we should never worry about this
1599 * because whenever we get here it will have been
1600 * long enough for the h8 to complete a reply
1602 bscbus_cmd_log(csp, BSC_CMD_BUSY, status, 0);
1603 bscbus_trace(csp, 'R', "bscbus_hw_reset",
1604 "h8 reporting status (%x) busy - waiting", status);
1605 if (ddi_in_panic()) {
1606 drv_usecwait(BSCBUS_HWRESET_POLL/1000);
1607 } else {
1608 delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
1611 /* Reply should be completed by now. Try to clear busy status */
1612 status = bscbus_get_reg(csp, H8_STR);
1613 if (status & (H8_STR_BUSY | H8_STR_OBF)) {
1614 bscbus_trace(csp, 'R', "bscbus_hw_reset",
1615 "clearing busy status for channel %d", csp->chno);
1617 for (timeout = BSCBUS_HWRESET_TIMEOUT;
1618 (timeout > 0);
1619 timeout -= BSCBUS_HWRESET_POLL) {
1620 if (status & H8_STR_OBF) {
1621 (void) bscbus_get_reg(csp, H8_ODR);
1622 if (!(status & H8_STR_BUSY)) {
1623 /* We are done */
1624 break;
1627 if (ddi_in_panic()) {
1628 drv_usecwait(BSCBUS_HWRESET_POLL/1000);
1629 } else {
1630 delay(drv_usectohz(BSCBUS_HWRESET_POLL/1000));
1632 status = bscbus_get_reg(csp, H8_STR);
1634 if (timeout <= 0) {
1635 cmn_err(CE_WARN, "bscbus_hw_reset: timed out "
1636 "clearing busy status");
1640 * We read ODR just in case there is a pending interrupt with
1641 * no data. This is potentially dangerous because we could get
1642 * out of sync due to race conditions BUT at this point the
1643 * channel should be idle so it is safe.
1645 (void) bscbus_get_reg(csp, H8_ODR);
1649 * Higher-level setup & teardown
1652 static void
1653 bscbus_offline(struct bscbus_state *ssp)
1655 if (ssp->h8_handle != NULL)
1656 ddi_regs_map_free(&ssp->h8_handle);
1657 ssp->h8_handle = NULL;
1658 ssp->h8_regs = NULL;
1661 static int
1662 bscbus_online(struct bscbus_state *ssp)
1664 ddi_acc_handle_t h;
1665 caddr_t p;
1666 int nregs;
1667 int err;
1669 ssp->h8_handle = NULL;
1670 ssp->h8_regs = NULL;
1671 ssp->per_channel_regs = B_FALSE;
1673 if (ddi_dev_nregs(ssp->dip, &nregs) != DDI_SUCCESS)
1674 nregs = 0;
1676 switch (nregs) {
1677 case 1:
1679 * regset 0 represents the H8 interface registers
1681 err = ddi_regs_map_setup(ssp->dip, 0, &p, 0, 0,
1682 bscbus_dev_acc_attr, &h);
1683 if (err != DDI_SUCCESS)
1684 return (EIO);
1686 ssp->h8_handle = h;
1687 ssp->h8_regs = (void *)p;
1688 break;
1690 case 0:
1692 * If no registers are defined, succeed vacuously;
1693 * commands will be accepted, but we fake the accesses.
1695 break;
1697 default:
1699 * Remember that we are using the new register scheme.
1700 * reg set 0 is chan 0
1701 * reg set 1 is chan 1 ...
1702 * Interrupts are specified in that order but later
1703 * channels may not have interrupts.
1704 * We map the regs later on a per channel basis.
1706 ssp->per_channel_regs = B_TRUE;
1707 break;
1709 return (0);
1712 static int
1713 bscbus_claim_channel(struct bscbus_channel_state *csp, boolean_t map_dog)
1715 int err;
1717 mutex_enter(csp->ssp->ch_mutex);
1718 csp->map_count++;
1719 bscbus_trace(csp, 'C', "bscbus_claim_channel",
1720 "claim channel for channel %d, count %d",
1721 csp->chno, csp->map_count);
1723 if (csp->map_count == 1) {
1724 /* No-one is using this channel - initialise it */
1725 bscbus_trace(csp, 'C', "bscbus_claim_channel",
1726 "initialise channel %d, count %d",
1727 csp->chno, csp->map_count);
1729 mutex_init(csp->dog_mutex, NULL, MUTEX_DRIVER,
1730 (void *)(uintptr_t)__ipltospl(SPL7 - 1));
1731 csp->map_dog = map_dog;
1732 csp->interrupt_failed = B_FALSE;
1733 csp->cmdstate = BSCBUS_CMDSTATE_IDLE;
1734 csp->pat_retry_count = 0;
1735 csp->pat_fail_count = 0;
1737 /* Map appropriate register set for this channel */
1738 if (csp->ssp->per_channel_regs == B_TRUE) {
1739 ddi_acc_handle_t h;
1740 caddr_t p;
1742 err = ddi_regs_map_setup(csp->ssp->dip, csp->chno,
1743 &p, 0, 0, bscbus_dev_acc_attr, &h);
1745 if (err != DDI_SUCCESS) {
1746 goto failed1;
1749 csp->ch_handle = h;
1750 csp->ch_regs = (void *)p;
1752 bscbus_trace(csp, 'C', "bscbus_claim_channel",
1753 "mapped chno=%d ch_handle=%d ch_regs=%p",
1754 csp->chno, h, p);
1755 } else {
1757 * if using the old reg property scheme use the
1758 * common mapping.
1760 csp->ch_handle = csp->ssp->h8_handle;
1761 csp->ch_regs =
1762 csp->ssp->h8_regs +
1763 BSCBUS_CHANNEL_TO_OFFSET(csp->chno);
1766 /* Ensure no interrupts pending prior to getting iblk cookie */
1767 bscbus_hw_reset(csp);
1769 if (csp->map_dog == 1) {
1771 * we don't want lo_mutex to be initialised
1772 * with an iblock cookie if we are the wdog,
1773 * because we don't use interrupts.
1775 mutex_init(csp->lo_mutex, NULL,
1776 MUTEX_DRIVER, NULL);
1777 cv_init(csp->lo_cv, NULL,
1778 CV_DRIVER, NULL);
1779 csp->unclaimed_count = 0;
1780 } else {
1781 int ninterrupts;
1784 * check that there is an interrupt for this
1785 * this channel. If we fail to setup interrupts we
1786 * must unmap the registers and fail.
1788 err = ddi_dev_nintrs(csp->ssp->dip, &ninterrupts);
1790 if (err != DDI_SUCCESS) {
1791 ninterrupts = 0;
1794 if (ninterrupts <= csp->chno) {
1795 cmn_err(CE_WARN,
1796 "no interrupt available for "
1797 "bscbus channel %d", csp->chno);
1798 goto failed2;
1801 if (ddi_intr_hilevel(csp->ssp->dip, csp->chno) != 0) {
1802 cmn_err(CE_WARN,
1803 "bscbus interrupts are high "
1804 "level - channel not usable.");
1805 goto failed2;
1806 } else {
1807 err = ddi_get_iblock_cookie(csp->ssp->dip,
1808 csp->chno, &csp->lo_iblk);
1809 if (err != DDI_SUCCESS) {
1810 goto failed2;
1813 mutex_init(csp->lo_mutex, NULL,
1814 MUTEX_DRIVER, csp->lo_iblk);
1815 cv_init(csp->lo_cv, NULL,
1816 CV_DRIVER, NULL);
1817 csp->unclaimed_count = 0;
1819 err = ddi_add_intr(csp->ssp->dip, csp->chno,
1820 &csp->lo_iblk, NULL,
1821 bscbus_hwintr, (caddr_t)csp);
1822 if (err != DDI_SUCCESS) {
1823 cv_destroy(csp->lo_cv);
1824 mutex_destroy(csp->lo_mutex);
1825 goto failed2;
1830 * The channel is now live and may
1831 * receive interrupts
1833 } else if (csp->map_dog != map_dog) {
1834 bscbus_trace(csp, 'C', "bscbus_claim_channel",
1835 "request conflicts with previous mapping. old %x, new %x.",
1836 csp->map_dog, map_dog);
1837 goto failed1;
1839 mutex_exit(csp->ssp->ch_mutex);
1840 return (1);
1842 failed2:
1843 /* unmap regs for failed channel */
1844 if (csp->ssp->per_channel_regs == B_TRUE) {
1845 ddi_regs_map_free(&csp->ch_handle);
1847 csp->ch_handle = NULL;
1848 csp->ch_regs = NULL;
1849 failed1:
1850 csp->map_count--;
1851 mutex_exit(csp->ssp->ch_mutex);
1852 return (0);
1855 static void
1856 bscbus_release_channel(struct bscbus_channel_state *csp)
1858 mutex_enter(csp->ssp->ch_mutex);
1859 if (csp->map_count == 1) {
1860 /* No-one is now using this channel - shutdown channel */
1861 bscbus_trace(csp, 'C', "bscbus_release_channel",
1862 "shutdown channel %d, count %d",
1863 csp->chno, csp->map_count);
1865 if (csp->map_dog == 0) {
1866 ASSERT(!ddi_intr_hilevel(csp->ssp->dip, csp->chno));
1867 ddi_remove_intr(csp->ssp->dip, csp->chno, csp->lo_iblk);
1869 cv_destroy(csp->lo_cv);
1870 mutex_destroy(csp->lo_mutex);
1871 mutex_destroy(csp->dog_mutex);
1872 bscbus_hw_reset(csp);
1874 /* unmap registers if using the new register scheme */
1875 if (csp->ssp->per_channel_regs == B_TRUE) {
1876 ddi_regs_map_free(&csp->ch_handle);
1878 csp->ch_handle = NULL;
1879 csp->ch_regs = NULL;
1881 csp->map_count--;
1882 bscbus_trace(csp, 'C', "bscbus_release_channel",
1883 "release channel %d, count %d",
1884 csp->chno, csp->map_count);
1885 mutex_exit(csp->ssp->ch_mutex);
1890 * Nexus routines
1893 #if defined(NDI_ACC_HDL_V2)
1895 static const ndi_acc_fns_t bscbus_vreg_acc_fns = {
1896 NDI_ACC_FNS_CURRENT,
1897 NDI_ACC_FNS_V1,
1899 bscbus_vreg_get8,
1900 bscbus_vreg_put8,
1901 bscbus_vreg_rep_get8,
1902 bscbus_vreg_rep_put8,
1904 bscbus_no_get16,
1905 bscbus_no_put16,
1906 bscbus_no_rep_get16,
1907 bscbus_no_rep_put16,
1909 bscbus_meta_get32,
1910 bscbus_meta_put32,
1911 bscbus_meta_rep_get32,
1912 bscbus_meta_rep_put32,
1914 bscbus_no_get64,
1915 bscbus_no_put64,
1916 bscbus_no_rep_get64,
1917 bscbus_no_rep_put64,
1919 bscbus_acc_fault_check
1922 static const ndi_acc_fns_t bscbus_pat_acc_fns = {
1923 NDI_ACC_FNS_CURRENT,
1924 NDI_ACC_FNS_V1,
1926 bscbus_pat_get8,
1927 bscbus_pat_put8,
1928 bscbus_pat_rep_get8,
1929 bscbus_pat_rep_put8,
1931 bscbus_no_get16,
1932 bscbus_no_put16,
1933 bscbus_no_rep_get16,
1934 bscbus_no_rep_put16,
1936 bscbus_meta_get32,
1937 bscbus_meta_put32,
1938 bscbus_meta_rep_get32,
1939 bscbus_meta_rep_put32,
1941 bscbus_no_get64,
1942 bscbus_no_put64,
1943 bscbus_no_rep_get64,
1944 bscbus_no_rep_put64,
1946 bscbus_acc_fault_check
1949 static const ndi_acc_fns_t bscbus_event_acc_fns = {
1950 NDI_ACC_FNS_CURRENT,
1951 NDI_ACC_FNS_V1,
1953 bscbus_no_get8,
1954 bscbus_no_put8,
1955 bscbus_no_rep_get8,
1956 bscbus_no_rep_put8,
1958 bscbus_event_get16,
1959 bscbus_event_put16,
1960 bscbus_event_rep_get16,
1961 bscbus_event_rep_put16,
1963 bscbus_meta_get32,
1964 bscbus_meta_put32,
1965 bscbus_meta_rep_get32,
1966 bscbus_meta_rep_put32,
1968 bscbus_no_get64,
1969 bscbus_no_put64,
1970 bscbus_no_rep_get64,
1971 bscbus_no_rep_put64,
1973 bscbus_acc_fault_check
1976 static int
1977 bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
1978 int space, caddr_t vaddr, off_t len,
1979 ndi_acc_handle_t *hdlp, caddr_t *addrp)
1981 switch (op) {
1982 default:
1983 return (DDI_ME_UNIMPLEMENTED);
1985 case DDI_MO_MAP_LOCKED:
1986 if (bscbus_claim_channel(csp,
1987 (space == LOMBUS_PAT_SPACE)) == 0) {
1988 return (DDI_ME_GENERIC);
1991 switch (space) {
1992 default:
1993 return (DDI_ME_REGSPEC_RANGE);
1995 case LOMBUS_VREG_SPACE:
1996 ndi_set_acc_fns(hdlp, &bscbus_vreg_acc_fns);
1997 break;
1999 case LOMBUS_PAT_SPACE:
2000 ndi_set_acc_fns(hdlp, &bscbus_pat_acc_fns);
2001 break;
2003 case LOMBUS_EVENT_SPACE:
2004 ndi_set_acc_fns(hdlp, &bscbus_event_acc_fns);
2005 break;
2007 hdlp->ah_addr = *addrp = vaddr;
2008 hdlp->ah_len = len;
2009 hdlp->ah_bus_private = csp;
2010 return (DDI_SUCCESS);
2012 case DDI_MO_UNMAP:
2013 *addrp = NULL;
2014 hdlp->ah_bus_private = NULL;
2015 bscbus_release_channel(csp);
2016 return (DDI_SUCCESS);
2020 #else
2022 static int
2023 bscbus_map_handle(struct bscbus_channel_state *csp, ddi_map_op_t op,
2024 int space, caddr_t vaddr, off_t len,
2025 ddi_acc_hdl_t *hdlp, caddr_t *addrp)
2027 ddi_acc_impl_t *aip = hdlp->ah_platform_private;
2029 switch (op) {
2030 default:
2031 return (DDI_ME_UNIMPLEMENTED);
2033 case DDI_MO_MAP_LOCKED:
2034 if (bscbus_claim_channel(csp,
2035 (space == LOMBUS_PAT_SPACE)) == 0) {
2036 return (DDI_ME_GENERIC);
2039 switch (space) {
2040 default:
2041 return (DDI_ME_REGSPEC_RANGE);
2043 case LOMBUS_VREG_SPACE:
2044 aip->ahi_get8 = bscbus_vreg_get8;
2045 aip->ahi_put8 = bscbus_vreg_put8;
2046 aip->ahi_rep_get8 = bscbus_vreg_rep_get8;
2047 aip->ahi_rep_put8 = bscbus_vreg_rep_put8;
2049 aip->ahi_get16 = bscbus_no_get16;
2050 aip->ahi_put16 = bscbus_no_put16;
2051 aip->ahi_rep_get16 = bscbus_no_rep_get16;
2052 aip->ahi_rep_put16 = bscbus_no_rep_put16;
2054 aip->ahi_get32 = bscbus_meta_get32;
2055 aip->ahi_put32 = bscbus_meta_put32;
2056 aip->ahi_rep_get32 = bscbus_meta_rep_get32;
2057 aip->ahi_rep_put32 = bscbus_meta_rep_put32;
2059 aip->ahi_get64 = bscbus_no_get64;
2060 aip->ahi_put64 = bscbus_no_put64;
2061 aip->ahi_rep_get64 = bscbus_no_rep_get64;
2062 aip->ahi_rep_put64 = bscbus_no_rep_put64;
2064 aip->ahi_fault_check = bscbus_acc_fault_check;
2065 break;
2067 case LOMBUS_PAT_SPACE:
2068 aip->ahi_get8 = bscbus_pat_get8;
2069 aip->ahi_put8 = bscbus_pat_put8;
2070 aip->ahi_rep_get8 = bscbus_pat_rep_get8;
2071 aip->ahi_rep_put8 = bscbus_pat_rep_put8;
2073 aip->ahi_get16 = bscbus_no_get16;
2074 aip->ahi_put16 = bscbus_no_put16;
2075 aip->ahi_rep_get16 = bscbus_no_rep_get16;
2076 aip->ahi_rep_put16 = bscbus_no_rep_put16;
2078 aip->ahi_get32 = bscbus_meta_get32;
2079 aip->ahi_put32 = bscbus_meta_put32;
2080 aip->ahi_rep_get32 = bscbus_meta_rep_get32;
2081 aip->ahi_rep_put32 = bscbus_meta_rep_put32;
2083 aip->ahi_get64 = bscbus_no_get64;
2084 aip->ahi_put64 = bscbus_no_put64;
2085 aip->ahi_rep_get64 = bscbus_no_rep_get64;
2086 aip->ahi_rep_put64 = bscbus_no_rep_put64;
2088 aip->ahi_fault_check = bscbus_acc_fault_check;
2089 break;
2091 case LOMBUS_EVENT_SPACE:
2092 aip->ahi_get8 = bscbus_no_get8;
2093 aip->ahi_put8 = bscbus_no_put8;
2094 aip->ahi_rep_get8 = bscbus_no_rep_get8;
2095 aip->ahi_rep_put8 = bscbus_no_rep_put8;
2097 aip->ahi_get16 = bscbus_event_get16;
2098 aip->ahi_put16 = bscbus_event_put16;
2099 aip->ahi_rep_get16 = bscbus_event_rep_get16;
2100 aip->ahi_rep_put16 = bscbus_event_rep_put16;
2102 aip->ahi_get32 = bscbus_meta_get32;
2103 aip->ahi_put32 = bscbus_meta_put32;
2104 aip->ahi_rep_get32 = bscbus_meta_rep_get32;
2105 aip->ahi_rep_put32 = bscbus_meta_rep_put32;
2107 aip->ahi_get64 = bscbus_no_get64;
2108 aip->ahi_put64 = bscbus_no_put64;
2109 aip->ahi_rep_get64 = bscbus_no_rep_get64;
2110 aip->ahi_rep_put64 = bscbus_no_rep_put64;
2112 aip->ahi_fault_check = bscbus_acc_fault_check;
2113 break;
2115 hdlp->ah_addr = *addrp = vaddr;
2116 hdlp->ah_len = len;
2117 hdlp->ah_bus_private = csp;
2118 return (DDI_SUCCESS);
2120 case DDI_MO_UNMAP:
2121 *addrp = NULL;
2122 hdlp->ah_bus_private = NULL;
2123 bscbus_release_channel(csp);
2124 return (DDI_SUCCESS);
2128 #endif /* NDI_ACC_HDL_V2 */
2130 static int
2131 bscbus_map(dev_info_t *dip, dev_info_t *rdip, ddi_map_req_t *mp,
2132 off_t off, off_t len, caddr_t *addrp)
2134 struct bscbus_child_info *lcip;
2135 struct bscbus_state *ssp;
2136 lombus_regspec_t *rsp;
2138 if ((ssp = bscbus_getstate(dip, -1, "bscbus_map")) == NULL)
2139 return (DDI_FAILURE); /* this "can't happen" */
2142 * Validate mapping request ...
2145 if (mp->map_flags != DDI_MF_KERNEL_MAPPING)
2146 return (DDI_ME_UNSUPPORTED);
2147 if (mp->map_handlep == NULL)
2148 return (DDI_ME_UNSUPPORTED);
2149 if (mp->map_type != DDI_MT_RNUMBER)
2150 return (DDI_ME_UNIMPLEMENTED);
2151 if ((lcip = ddi_get_parent_data(rdip)) == NULL)
2152 return (DDI_ME_INVAL);
2153 if ((rsp = lcip->rsp) == NULL)
2154 return (DDI_ME_INVAL);
2155 if (mp->map_obj.rnumber >= lcip->nregs)
2156 return (DDI_ME_RNUMBER_RANGE);
2157 rsp += mp->map_obj.rnumber;
2158 if (off < 0 || off >= rsp->lombus_size)
2159 return (DDI_ME_INVAL);
2160 if (len == 0)
2161 len = rsp->lombus_size-off;
2162 if (len < 0)
2163 return (DDI_ME_INVAL);
2164 if (off+len < 0 || off+len > rsp->lombus_size)
2165 return (DDI_ME_INVAL);
2167 return (bscbus_map_handle(
2168 &ssp->channel[LOMBUS_SPACE_TO_CHANNEL(rsp->lombus_space)],
2169 mp->map_op, LOMBUS_SPACE_TO_REGSET(rsp->lombus_space),
2170 VREG_TO_ADDR(rsp->lombus_base+off), len, mp->map_handlep, addrp));
2174 static int
2175 bscbus_ctlops(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op,
2176 void *arg, void *result)
2178 struct bscbus_child_info *lcip;
2179 lombus_regspec_t *rsp;
2180 dev_info_t *cdip;
2181 char addr[32];
2182 uint_t nregs;
2183 uint_t rnum;
2184 int *regs;
2185 int limit;
2186 int err;
2187 int i;
2189 if (bscbus_getstate(dip, -1, "bscbus_ctlops") == NULL)
2190 return (DDI_FAILURE); /* this "can't happen" */
2192 switch (op) {
2193 default:
2194 break;
2196 case DDI_CTLOPS_INITCHILD:
2198 * First, look up and validate the "reg" property.
2200 * It must be a non-empty integer array containing a set
2201 * of triples. Once we've verified that, we can treat it
2202 * as an array of type lombus_regspec_t[], which defines
2203 * the meaning of the elements of each triple:
2204 * + the first element of each triple must be a valid space
2205 * + the second and third elements (base, size) of each
2206 * triple must define a valid subrange of that space
2207 * If it passes all the tests, we save it away for future
2208 * reference in the child's parent-private-data field.
2210 cdip = arg;
2211 err = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
2212 DDI_PROP_DONTPASS, "reg", &regs, &nregs);
2213 if (err != DDI_PROP_SUCCESS)
2214 return (DDI_FAILURE);
2216 err = (nregs <= 0 || (nregs % LOMBUS_REGSPEC_SIZE) != 0);
2217 nregs /= LOMBUS_REGSPEC_SIZE;
2218 rsp = (lombus_regspec_t *)regs;
2219 for (i = 0; i < nregs && !err; ++i) {
2220 switch (LOMBUS_SPACE_TO_REGSET(rsp[i].lombus_space)) {
2221 default:
2222 limit = 0;
2223 err = 1;
2224 cmn_err(CE_WARN,
2225 "child(%p): unknown reg space %d",
2226 (void *)cdip, rsp[i].lombus_space);
2227 break;
2229 case LOMBUS_VREG_SPACE:
2230 limit = LOMBUS_MAX_REG+1;
2231 break;
2233 case LOMBUS_PAT_SPACE:
2234 limit = LOMBUS_PAT_REG+1;
2235 break;
2237 case LOMBUS_EVENT_SPACE:
2238 limit = LOMBUS_EVENT_REG+1;
2239 break;
2242 err |= (rsp[i].lombus_base < 0);
2243 err |= (rsp[i].lombus_base >= limit);
2245 if (rsp[i].lombus_size == 0)
2246 rsp[i].lombus_size = limit-rsp[i].lombus_base;
2248 err |= (rsp[i].lombus_size < 0);
2249 err |= (rsp[i].lombus_base+rsp[i].lombus_size < 0);
2250 err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
2252 err |= (rsp[i].lombus_base+rsp[i].lombus_size > limit);
2256 if (err) {
2257 ddi_prop_free(regs);
2258 return (DDI_FAILURE);
2261 lcip = kmem_zalloc(sizeof (*lcip), KM_SLEEP);
2262 lcip->nregs = nregs;
2263 lcip->rsp = rsp;
2264 ddi_set_parent_data(cdip, lcip);
2266 (void) snprintf(addr, sizeof (addr),
2267 "%x,%x", rsp[0].lombus_space, rsp[0].lombus_base);
2268 ddi_set_name_addr(cdip, addr);
2270 return (DDI_SUCCESS);
2272 case DDI_CTLOPS_UNINITCHILD:
2273 cdip = arg;
2274 ddi_set_name_addr(cdip, NULL);
2275 lcip = ddi_get_parent_data(cdip);
2276 ddi_set_parent_data(cdip, NULL);
2277 ddi_prop_free(lcip->rsp);
2278 kmem_free(lcip, sizeof (*lcip));
2279 return (DDI_SUCCESS);
2281 case DDI_CTLOPS_REPORTDEV:
2282 if (rdip == NULL)
2283 return (DDI_FAILURE);
2285 cmn_err(CE_CONT, "?BSC device: %s@%s, %s#%d\n",
2286 ddi_node_name(rdip), ddi_get_name_addr(rdip),
2287 ddi_driver_name(dip), ddi_get_instance(dip));
2289 return (DDI_SUCCESS);
2291 case DDI_CTLOPS_REGSIZE:
2292 if ((lcip = ddi_get_parent_data(rdip)) == NULL)
2293 return (DDI_FAILURE);
2294 if ((rnum = *(uint_t *)arg) >= lcip->nregs)
2295 return (DDI_FAILURE);
2296 *(off_t *)result = lcip->rsp[rnum].lombus_size;
2297 return (DDI_SUCCESS);
2299 case DDI_CTLOPS_NREGS:
2300 if ((lcip = ddi_get_parent_data(rdip)) == NULL)
2301 return (DDI_FAILURE);
2302 *(int *)result = lcip->nregs;
2303 return (DDI_SUCCESS);
2306 return (ddi_ctlops(dip, rdip, op, arg, result));
2311 * This nexus does not support passing interrupts to leaf drivers, so
2312 * all the intrspec-related operations just fail as cleanly as possible.
2315 /*ARGSUSED*/
2316 static int
2317 bscbus_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op,
2318 ddi_intr_handle_impl_t *hdlp, void *result)
2320 _NOTE(ARGUNUSED(dip, rdip, op, hdlp, result))
2321 return (DDI_FAILURE);
2325 * Clean up on detach or failure of attach
2327 static int
2328 bscbus_unattach(struct bscbus_state *ssp, int instance)
2330 int chno;
2332 if (ssp != NULL) {
2333 for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
2334 ASSERT(ssp->channel[chno].map_count == 0);
2336 bscbus_offline(ssp);
2337 ddi_set_driver_private(ssp->dip, NULL);
2338 mutex_destroy(ssp->ch_mutex);
2340 #ifdef BSCBUS_LOGSTATUS
2341 if (ssp->cmd_log_size != 0) {
2342 kmem_free(ssp->cmd_log,
2343 ssp->cmd_log_size * sizeof (bsc_cmd_log_t));
2345 #endif /* BSCBUS_LOGSTATUS */
2348 ddi_soft_state_free(bscbus_statep, instance);
2349 return (DDI_FAILURE);
2353 * Autoconfiguration routines
2356 static int
2357 bscbus_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2359 struct bscbus_state *ssp = NULL;
2360 int chno;
2361 int instance;
2362 int err;
2364 switch (cmd) {
2365 default:
2366 return (DDI_FAILURE);
2368 case DDI_ATTACH:
2369 break;
2373 * Allocate the soft-state structure
2375 instance = ddi_get_instance(dip);
2376 if (ddi_soft_state_zalloc(bscbus_statep, instance) != DDI_SUCCESS)
2377 return (DDI_FAILURE);
2378 if ((ssp = bscbus_getstate(dip, instance, "bscbus_attach")) == NULL)
2379 return (bscbus_unattach(ssp, instance));
2380 ddi_set_driver_private(dip, ssp);
2383 * Initialise devinfo-related fields
2385 ssp->dip = dip;
2386 ssp->majornum = ddi_driver_major(dip);
2387 ssp->instance = instance;
2390 * Set various options from .conf properties
2392 ssp->debug = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
2393 DDI_PROP_DONTPASS, "debug", 0);
2395 mutex_init(ssp->ch_mutex, NULL, MUTEX_DRIVER, NULL);
2397 #ifdef BSCBUS_LOGSTATUS
2398 ssp->cmd_log_size = bscbus_cmd_log_size;
2399 if (ssp->cmd_log_size != 0) {
2400 ssp->cmd_log_idx = 0;
2401 ssp->cmd_log = kmem_zalloc(ssp->cmd_log_size *
2402 sizeof (bsc_cmd_log_t), KM_SLEEP);
2404 #endif /* BSCBUS_LOGSTATUS */
2407 * Online the hardware ...
2409 err = bscbus_online(ssp);
2410 if (err != 0)
2411 return (bscbus_unattach(ssp, instance));
2413 for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
2414 struct bscbus_channel_state *csp = &ssp->channel[chno];
2417 * Initialise state
2418 * The hardware/interrupts are setup at map time to
2419 * avoid claiming hardware that OBP is using
2421 csp->ssp = ssp;
2422 csp->chno = chno;
2423 csp->map_count = 0;
2424 csp->map_dog = B_FALSE;
2428 * All done, report success
2430 ddi_report_dev(dip);
2431 return (DDI_SUCCESS);
2434 static int
2435 bscbus_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2437 struct bscbus_state *ssp;
2438 int instance;
2440 switch (cmd) {
2441 default:
2442 return (DDI_FAILURE);
2444 case DDI_DETACH:
2445 break;
2448 instance = ddi_get_instance(dip);
2449 if ((ssp = bscbus_getstate(dip, instance, "bscbus_detach")) == NULL)
2450 return (DDI_FAILURE); /* this "can't happen" */
2452 (void) bscbus_unattach(ssp, instance);
2453 return (DDI_SUCCESS);
2456 static int
2457 bscbus_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
2459 struct bscbus_state *ssp;
2460 int chno;
2462 _NOTE(ARGUNUSED(cmd))
2464 if ((ssp = bscbus_getstate(dip, -1, "bscbus_reset")) == NULL)
2465 return (DDI_FAILURE);
2467 for (chno = 0; chno < BSCBUS_MAX_CHANNELS; chno++) {
2468 bscbus_hw_reset(&ssp->channel[chno]);
2470 return (DDI_SUCCESS);
2475 * System interface structures
2478 static struct cb_ops bscbus_cb_ops =
2480 nodev, /* b/c open */
2481 nodev, /* b/c close */
2482 nodev, /* b strategy */
2483 nodev, /* b print */
2484 nodev, /* b dump */
2485 nodev, /* c read */
2486 nodev, /* c write */
2487 nodev, /* c ioctl */
2488 nodev, /* c devmap */
2489 nodev, /* c mmap */
2490 nodev, /* c segmap */
2491 nochpoll, /* c poll */
2492 ddi_prop_op, /* b/c prop_op */
2493 NULL, /* c streamtab */
2494 D_MP | D_NEW /* b/c flags */
2497 static struct bus_ops bscbus_bus_ops =
2499 BUSO_REV, /* revision */
2500 bscbus_map, /* bus_map */
2501 0, /* get_intrspec */
2502 0, /* add_intrspec */
2503 0, /* remove_intrspec */
2504 i_ddi_map_fault, /* map_fault */
2505 ddi_no_dma_map, /* dma_map */
2506 ddi_no_dma_allochdl, /* allocate DMA handle */
2507 ddi_no_dma_freehdl, /* free DMA handle */
2508 ddi_no_dma_bindhdl, /* bind DMA handle */
2509 ddi_no_dma_unbindhdl, /* unbind DMA handle */
2510 ddi_no_dma_flush, /* flush DMA */
2511 ddi_no_dma_win, /* move DMA window */
2512 ddi_no_dma_mctl, /* generic DMA control */
2513 bscbus_ctlops, /* generic control */
2514 ddi_bus_prop_op, /* prop_op */
2515 ndi_busop_get_eventcookie, /* get_eventcookie */
2516 ndi_busop_add_eventcall, /* add_eventcall */
2517 ndi_busop_remove_eventcall, /* remove_eventcall */
2518 ndi_post_event, /* post_event */
2519 0, /* interrupt control */
2520 0, /* bus_config */
2521 0, /* bus_unconfig */
2522 0, /* bus_fm_init */
2523 0, /* bus_fm_fini */
2524 0, /* bus_fm_access_enter */
2525 0, /* bus_fm_access_exit */
2526 0, /* bus_power */
2527 bscbus_intr_op /* bus_intr_op */
2530 static struct dev_ops bscbus_dev_ops =
2532 DEVO_REV,
2533 0, /* refcount */
2534 ddi_no_info, /* getinfo */
2535 nulldev, /* identify */
2536 nulldev, /* probe */
2537 bscbus_attach, /* attach */
2538 bscbus_detach, /* detach */
2539 bscbus_reset, /* reset */
2540 &bscbus_cb_ops, /* driver operations */
2541 &bscbus_bus_ops, /* bus operations */
2542 NULL, /* power */
2543 ddi_quiesce_not_needed, /* quiesce */
2546 static struct modldrv modldrv =
2548 &mod_driverops,
2549 "bscbus driver",
2550 &bscbus_dev_ops
2553 static struct modlinkage modlinkage =
2555 MODREV_1,
2557 &modldrv,
2558 NULL
2564 * Dynamic loader interface code
2568 _init(void)
2570 int err;
2572 err = ddi_soft_state_init(&bscbus_statep,
2573 sizeof (struct bscbus_state), 0);
2574 if (err == DDI_SUCCESS)
2575 if ((err = mod_install(&modlinkage)) != DDI_SUCCESS) {
2576 ddi_soft_state_fini(&bscbus_statep);
2579 return (err);
2583 _info(struct modinfo *mip)
2585 return (mod_info(&modlinkage, mip));
2589 _fini(void)
2591 int err;
2593 if ((err = mod_remove(&modlinkage)) == DDI_SUCCESS) {
2594 ddi_soft_state_fini(&bscbus_statep);
2595 bscbus_major = NOMAJOR;
2598 return (err);
2601 #ifdef BSCBUS_LOGSTATUS
2602 void bscbus_cmd_log(struct bscbus_channel_state *csp, bsc_cmd_stamp_t cat,
2603 uint8_t status, uint8_t data)
2605 int idx;
2606 bsc_cmd_log_t *logp;
2607 struct bscbus_state *ssp;
2609 if ((csp) == NULL)
2610 return;
2611 if ((ssp = (csp)->ssp) == NULL)
2612 return;
2613 if (ssp->cmd_log_size == 0)
2614 return;
2615 if ((bscbus_cmd_log_flags & (1 << cat)) == 0)
2616 return;
2617 idx = atomic_inc_32_nv(&ssp->cmd_log_idx);
2618 logp = &ssp->cmd_log[idx % ssp->cmd_log_size];
2619 logp->bcl_seq = idx;
2620 logp->bcl_cat = cat;
2621 logp->bcl_now = gethrtime();
2622 logp->bcl_chno = csp->chno;
2623 logp->bcl_cmdstate = csp->cmdstate;
2624 logp->bcl_status = status;
2625 logp->bcl_data = data;
2627 #endif /* BSCBUS_LOGSTATUS */