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]
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.
37 #include <sys/types.h>
39 #include <sys/debug.h>
40 #include <sys/errno.h>
45 #include <sys/membar.h>
49 #include <sys/modctl.h>
55 #include <sys/strlog.h>
56 #include <sys/atomic.h>
59 #include <sys/sunddi.h>
60 #include <sys/sunndi.h>
62 #include <sys/bscbus.h>
64 #if defined(NDI_ACC_HDL_V2)
67 * Compiling for Solaris 10+ with access handle enhancements
69 #define HANDLE_TYPE ndi_acc_handle_t
70 #define HANDLE_ADDR(hdlp) (hdlp->ah_addr)
71 #define HANDLE_FAULT(hdlp) (hdlp->ah_fault)
72 #define HANDLE_MAPLEN(hdlp) (hdlp->ah_len)
73 #define HANDLE_PRIVATE(hdlp) (hdlp->ah_bus_private)
78 * Compatibility definitions for backport to Solaris 8/9
80 #define HANDLE_TYPE ddi_acc_impl_t
81 #define HANDLE_ADDR(hdlp) (hdlp->ahi_common.ah_addr)
82 #define HANDLE_FAULT(hdlp) (hdlp->ahi_fault)
83 #define HANDLE_MAPLEN(hdlp) (hdlp->ahi_common.ah_len)
84 #define HANDLE_PRIVATE(hdlp) (hdlp->ahi_common.ah_bus_private)
86 #define ddi_driver_major(dip) ddi_name_to_major(ddi_binding_name(dip))
88 #endif /* NDI_ACC_HDL_V2 */
94 #define MYNAME "bscbus"
95 #define NOMAJOR (~(major_t)0)
96 #define DUMMY_VALUE (~(int8_t)0)
98 #define BSCBUS_INST_TO_MINOR(i) (i)
99 #define BSCBUS_MINOR_TO_INST(m) (m)
101 #define BSCBUS_MAX_CHANNELS (4)
103 #define BSCBUS_DUMMY_ADDRESS ((caddr_t)0x0CADD1ED)
104 #define ADDR_TO_OFFSET(a, hdlp) ((caddr_t)(a) - HANDLE_ADDR(hdlp))
105 #define ADDR_TO_VREG(a) ((caddr_t)(a) - BSCBUS_DUMMY_ADDRESS)
106 #define VREG_TO_ADDR(v) (BSCBUS_DUMMY_ADDRESS + (v))
109 #define BSCBUS_LOGSTATUS
112 #ifdef BSCBUS_LOGSTATUS
114 * BSC command logging routines.
115 * Record the data passing to and from the BSC
119 BSC_CMD_BUSY
= 1, /* bsc reports busy */
120 BSC_CMD_CLEARING
= 2, /* clearing bsc busy */
121 BSC_CMD_CLEARED
= 3, /* cleared bsc busy */
122 BSC_CMD_SENDING
= 4, /* sending next byte */
123 BSC_CMD_SENT
= 5, /* sending last byte */
124 BSC_CMD_PENDING
= 6, /* got sent byte ack */
125 BSC_CMD_REPLY
= 7, /* got reply byte */
126 BSC_CMD_COMPLETE
= 8, /* command complete */
127 BSC_CMD_ERROR_SEQ
= 9, /* error status */
128 BSC_CMD_ERROR_STATUS
= 10, /* error status */
129 BSC_CMD_ERROR_OFLOW
= 11, /* error status */
130 BSC_CMD_ERROR_TOUT
= 12, /* error status */
132 BSC_CMD_PROCESS
= 13, /* async intr */
133 BSC_CMD_V1INTR
= 14, /* v1 intr */
134 BSC_CMD_V1INTRUNCL
= 15, /* v1 intr unclaim */
135 BSC_CMD_DOGPAT
= 17 /* watchdog pat */
141 bsc_cmd_stamp_t bcl_cat
;
143 uint8_t bcl_cmdstate
;
148 uint32_t bscbus_cmd_log_size
= 1024;
150 uint32_t bscbus_cmd_log_flags
= 0xffffffff;
152 #endif /* BSCBUS_LOGSTATUS */
155 * The following definitions are taken from the Hardware Manual for
156 * the Hitachi H8S/2148 in conjunction with the hardware specification
157 * for the Stiletto blade.
159 * Each instance of the host interface has 3 registers on the H8:
160 * IDRn - Input Data Register - write-only for Solaris.
161 * writes to this can be done via two
162 * addresses - control and data.
163 * The H8 can determine which address was
164 * written by examining the C/D bit in
165 * the status register.
166 * ODRn - Output Data Register - read-only for Solaris.
167 * A read has the side effect of acknowledging
169 * STRn - Status Register - read-only for Solaris.
173 * In terms of host access to this the Input and Output data registers are
174 * mapped at the same address.
181 #define H8_STR_OBF 0x01 /* data available in ODR */
182 #define H8_STR_IBF 0x02 /* data for H8 in IDR */
183 #define H8_STR_IDRC 0x08 /* last write to IDR was to IDRC */
184 /* 0=data, 1=command */
185 #define H8_STR_BUSY 0x04 /* H8 busy processing command */
186 #define H8_STR_TOKENPROTOCOL 0x80 /* token-passing protocol */
191 #define BSCBUS_MASK 0xc0 /* Byte-type bits */
192 #define BSCBUS_PARAM 0x00 /* Parameter byte: 0b0xxxxxxx */
193 #define BSCBUS_LAST 0x80 /* Last byte of packet */
194 #define BSCBUS_CMD 0x80 /* Command byte: 0b10###XWV */
195 #define BSCBUS_STATUS 0xc0 /* Status byte: 0b11###AEV */
197 #define BSCBUS_SEQ 0x38 /* Sequence number bits */
198 #define BSCBUS_SEQ_LSB 0x08 /* Sequence number LSB */
199 #define BSCBUS_CMD_XADDR 0x04 /* Extended (2-byte) addressing */
200 #define BSCBUS_CMD_WRITE 0x02 /* Write command */
201 #define BSCBUS_CMD_WMSB 0x01 /* Set MSB on Write */
202 #define BSCBUS_CMD_READ 0x01 /* Read command */
203 #define BSCBUS_CMD_NOP 0x00 /* NOP command */
205 #define BSCBUS_STATUS_ASYNC 0x04 /* Asynchronous event pending */
206 #define BSCBUS_STATUS_ERR 0x02 /* Error in command processing */
207 #define BSCBUS_STATUS_MSB 0x01 /* MSB of Value read */
209 #define BSCBUS_VREG_LO(x) ((x) & ((1 << 7) - 1))
210 #define BSCBUS_VREG_HI(x) ((x) >> 7)
212 #define BSCBUS_BUFSIZE 8
214 #define BSCBUS_CHANNEL_TO_OFFSET(chno) ((chno) * 2) /* Register offset */
217 * Time periods, in nanoseconds
219 * Note that LOMBUS_ONE_SEC and some other time
220 * periods are defined in <sys/lombus.h>
222 #define BSCBUS_CMD_POLL (LOMBUS_ONE_SEC)
223 #define BSCBUS_CMD_POLLNOINTS (LOMBUS_ONE_SEC/20)
224 #define BSCBUS_HWRESET_POLL (LOMBUS_ONE_SEC/20)
225 #define BSCBUS_HWRESET_TIMEOUT (LOMBUS_ONE_SEC*2)
227 #define BSCBUS_DOG_PAT_POLL_LIMIT (1000)
228 #define BSCBUS_DOG_PAT_POLL (1)
229 #define BSCBUS_PAT_RETRY_LIMIT 5
234 enum bscbus_cmdstate
{
235 BSCBUS_CMDSTATE_IDLE
, /* No transaction in progress */
236 BSCBUS_CMDSTATE_BUSY
, /* Setting up command */
237 BSCBUS_CMDSTATE_CLEARING
, /* Clearing firmware busy status */
238 BSCBUS_CMDSTATE_SENDING
, /* Waiting to send data to f/w */
239 BSCBUS_CMDSTATE_PENDING
, /* Waiting for ack from f/w */
240 BSCBUS_CMDSTATE_WAITING
, /* Waiting for status from f/w */
241 BSCBUS_CMDSTATE_READY
, /* Status received/command done */
242 BSCBUS_CMDSTATE_ERROR
/* Command failed with error */
245 struct bscbus_channel_state
{
246 /* Changes to these are protected by the instance ch_mutex mutex */
247 struct bscbus_state
*ssp
;
249 ddi_acc_handle_t ch_handle
; /* per channel access handle */
251 unsigned int map_count
; /* Number of mappings to channel */
252 boolean_t map_dog
; /* channel is mapped for watchdog */
255 * Flag to indicate that we've incurred a hardware fault on
256 * accesses to the H8; once this is set, we fake all further
257 * accesses in order not to provoke additional bus errors.
262 * Data protected by the dog_mutex: the watchdog-patting
263 * protocol data (since the dog can be patted from a high-level
264 * cyclic), and the interrupt-enabled flag.
266 kmutex_t dog_mutex
[1];
267 unsigned int pat_retry_count
;
268 unsigned int pat_fail_count
;
271 * Serial protocol state data, protected by lo_mutex
272 * (which is initialised using <lo_iblk>)
274 kmutex_t lo_mutex
[1];
275 ddi_iblock_cookie_t lo_iblk
;
279 volatile enum bscbus_cmdstate cmdstate
;
282 boolean_t interrupt_failed
;
283 uint8_t cmdbuf
[BSCBUS_BUFSIZE
];
284 uint8_t *cmdp
; /* Points to last tx'd in cmdbuf */
285 uint8_t reply
[BSCBUS_BUFSIZE
];
293 #define BSCBUS_TX_PENDING(csp) ((csp)->cmdp > (csp)->cmdbuf)
296 * This driver's soft-state structure
299 struct bscbus_state
{
301 * Configuration data, set during attach
307 ddi_acc_handle_t h8_handle
;
311 * Parameters derived from .conf properties
316 * Flag to indicate that we are using per channel
317 * mapping of the register sets and interrupts.
318 * reg set 0 is chan 0
319 * reg set 1 is chan 1 ...
321 * Interrupts are specified in that order but later
322 * channels may not have interrupts.
324 boolean_t per_channel_regs
;
327 * channel state data, protected by ch_mutex
328 * channel claim/release requests are protected by this mutex.
330 kmutex_t ch_mutex
[1];
331 struct bscbus_channel_state channel
[BSCBUS_MAX_CHANNELS
];
333 #ifdef BSCBUS_LOGSTATUS
335 * Command logging buffer for recording transactions with the
336 * BSC. This is useful for debugging failed transactions and other
339 bsc_cmd_log_t
*cmd_log
;
340 uint32_t cmd_log_idx
;
341 uint32_t cmd_log_size
;
342 uint32_t cmd_log_flags
;
343 #endif /* BSCBUS_LOGSTATUS */
347 * The auxiliary structure attached to each child
348 * (the child's parent-private-data points to this).
350 struct bscbus_child_info
{
351 lombus_regspec_t
*rsp
;
355 #ifdef BSCBUS_LOGSTATUS
356 void bscbus_cmd_log(struct bscbus_channel_state
*, bsc_cmd_stamp_t
,
358 #else /* BSCBUS_LOGSTATUS */
359 #define bscbus_cmd_log(state, stamp, status, data)
360 #endif /* BSCBUS_LOGSTATUS */
367 static void *bscbus_statep
;
369 static major_t bscbus_major
= NOMAJOR
;
371 static ddi_device_acc_attr_t bscbus_dev_acc_attr
[1] = {
373 DDI_STRUCTURE_LE_ACC
,
379 * General utility routines ...
384 bscbus_trace(struct bscbus_channel_state
*csp
, char code
, const char *caller
,
385 const char *fmt
, ...)
391 if (csp
->ssp
->debug
& (1 << (code
-'@'))) {
393 (void) snprintf(p
, sizeof (buf
) - (p
- buf
),
394 "%s/%s: ", MYNAME
, caller
);
398 (void) vsnprintf(p
, sizeof (buf
) - (p
- buf
), fmt
, va
);
401 buf
[sizeof (buf
) - 1] = '\0';
402 (void) strlog(csp
->ssp
->majornum
, csp
->ssp
->instance
,
403 code
, SL_TRACE
, buf
);
410 static struct bscbus_state
*
411 bscbus_getstate(dev_info_t
*dip
, int instance
, const char *caller
)
413 struct bscbus_state
*ssp
= NULL
;
414 dev_info_t
*sdip
= NULL
;
415 major_t dmaj
= NOMAJOR
;
419 * Use the instance number from the <dip>; also,
420 * check that it really corresponds to this driver
422 instance
= ddi_get_instance(dip
);
423 dmaj
= ddi_driver_major(dip
);
424 if (bscbus_major
== NOMAJOR
&& dmaj
!= NOMAJOR
)
426 else if (dmaj
!= bscbus_major
) {
428 "%s: major number mismatch (%d vs. %d) in %s(),"
429 "probably due to child misconfiguration",
430 MYNAME
, bscbus_major
, dmaj
, caller
);
436 ssp
= ddi_get_soft_state(bscbus_statep
, instance
);
439 if (dip
== NULL
&& sdip
== NULL
)
441 else if (dip
!= NULL
&& sdip
!= NULL
&& sdip
!= dip
) {
443 "%s: devinfo mismatch (%p vs. %p) in %s(), "
444 "probably due to child misconfiguration",
445 MYNAME
, (void *)dip
, (void *)sdip
, caller
);
454 * Lowest-level I/O register read/write
458 bscbus_put_reg(struct bscbus_channel_state
*csp
, uint_t reg
, uint8_t val
)
460 if (csp
->ch_handle
!= NULL
&& !csp
->xio_fault
) {
461 ddi_put8(csp
->ch_handle
,
462 csp
->ch_regs
+ reg
, val
);
467 bscbus_get_reg(struct bscbus_channel_state
*csp
, uint_t reg
)
471 if (csp
->ch_handle
!= NULL
&& !csp
->xio_fault
)
472 val
= ddi_get8(csp
->ch_handle
,
481 bscbus_check_fault_status(struct bscbus_channel_state
*csp
)
484 ddi_check_acc_handle(csp
->ch_handle
) != DDI_SUCCESS
;
488 bscbus_faulty(struct bscbus_channel_state
*csp
)
491 bscbus_check_fault_status(csp
);
492 return (csp
->xio_fault
);
496 * Write data into h8 registers
499 bscbus_pat_dog(struct bscbus_channel_state
*csp
, uint8_t val
)
502 uint32_t doglimit
= BSCBUS_DOG_PAT_POLL_LIMIT
;
504 bscbus_trace(csp
, 'W', "bscbus_pat_dog:", "");
506 bscbus_cmd_log(csp
, BSC_CMD_DOGPAT
, 0, val
);
507 status
= bscbus_get_reg(csp
, H8_STR
);
508 while (status
& H8_STR_IBF
) {
509 if (csp
->pat_retry_count
> BSCBUS_PAT_RETRY_LIMIT
) {
511 * Previous attempts to contact BSC have failed.
512 * Do not bother waiting for it to eat previous
514 * Pat anyway just in case the BSC is really alive
515 * and the IBF bit is lying.
517 bscbus_put_reg(csp
, H8_IDRC
, val
);
518 bscbus_trace(csp
, 'W', "bscbus_pat_dog:",
519 "retry count exceeded");
522 if (--doglimit
== 0) {
523 /* The BSC is not responding - give up */
524 csp
->pat_fail_count
++;
525 csp
->pat_retry_count
++;
526 /* Pat anyway just in case the BSC is really alive */
527 bscbus_put_reg(csp
, H8_IDRC
, val
);
528 bscbus_trace(csp
, 'W', "bscbus_pat_dog:",
529 "poll limit exceeded");
532 drv_usecwait(BSCBUS_DOG_PAT_POLL
);
533 status
= bscbus_get_reg(csp
, H8_STR
);
535 bscbus_put_reg(csp
, H8_IDRC
, val
);
536 csp
->pat_retry_count
= 0;
540 * State diagrams for how bscbus_process works.
541 * BSCBUS_CMDSTATE_IDLE No transaction in progress
542 * BSCBUS_CMDSTATE_BUSY Setting up command
543 * BSCBUS_CMDSTATE_CLEARING Clearing firmware busy status
544 * BSCBUS_CMDSTATE_SENDING Waiting to send data to f/w
545 * BSCBUS_CMDSTATE_PENDING Waiting for ack from f/w
546 * BSCBUS_CMDSTATE_WAITING Waiting for status from f/w
547 * BSCBUS_CMDSTATE_READY Status received/command done
548 * BSCBUS_CMDSTATE_ERROR Command failed with error
556 * | \------>------+ +----<---+
559 * ready| +----------+ |
564 * | cleared / | \ | more to clear
566 * | +-------<-------/ V
569 * +----------+ timeout |
570 * | |------>---------+--------+
572 * | (3) |------<-------+ |
574 * sent| \ send ^ack |
575 * last| \ next |received |
578 * | \------>| PENDING |-->-+
580 * | +----------+ |timeout
591 * done| | +--->----+ |
592 * | +--->--------------+ +---<---+
593 * | error/timeout | |
595 * +----------+ +----------+
597 * | READY | | ERROR |
599 * +----------+ +----------+
603 * +------>---+---<------+
611 bscbus_process_sending(struct bscbus_channel_state
*csp
, uint8_t status
)
614 * When we get here we actually expect H8_STR_IBF to
615 * be clear but we check just in case of problems.
617 ASSERT(BSCBUS_TX_PENDING(csp
));
618 if (!(status
& H8_STR_IBF
)) {
619 bscbus_put_reg(csp
, H8_IDRD
, *--csp
->cmdp
);
620 bscbus_trace(csp
, 'P', "bscbus_process_sending",
622 csp
->cmdstate
, *csp
->cmdp
);
623 if (!BSCBUS_TX_PENDING(csp
)) {
624 bscbus_cmd_log(csp
, BSC_CMD_SENT
,
626 /* No more pending - move to waiting state */
627 bscbus_trace(csp
, 'P', "bscbus_process_sending",
628 "moving to waiting");
629 csp
->cmdstate
= BSCBUS_CMDSTATE_WAITING
;
630 /* Extend deadline because time has moved on */
631 csp
->deadline
= ddi_get_lbolt() +
632 drv_usectohz(LOMBUS_CMD_TIMEOUT
/1000);
634 /* Wait for ack of this byte */
635 bscbus_cmd_log(csp
, BSC_CMD_SENDING
,
637 csp
->cmdstate
= BSCBUS_CMDSTATE_PENDING
;
638 bscbus_trace(csp
, 'P', "bscbus_process_sending",
639 "moving to pending");
645 bscbus_process_clearing(struct bscbus_channel_state
*csp
,
646 uint8_t status
, uint8_t data
)
649 * We only enter this state if H8_STR_BUSY was set when
650 * we started the transaction. We just ignore all received
651 * data until we see OBF set AND BUSY cleared.
652 * It is not good enough to see BUSY clear on its own
654 if ((status
& H8_STR_OBF
) && !(status
& H8_STR_BUSY
)) {
655 bscbus_cmd_log(csp
, BSC_CMD_CLEARED
, status
, data
);
656 csp
->cmdstate
= BSCBUS_CMDSTATE_SENDING
;
657 /* Throw away any data received up until now */
658 bscbus_trace(csp
, 'P', "bscbus_process_clearing",
661 * Send the next byte immediately.
662 * At this stage we should clear the OBF flag because that
663 * data has been used. IBF is still valid so do not clear that.
665 status
&= ~(H8_STR_OBF
);
666 bscbus_process_sending(csp
, status
);
668 if (status
& H8_STR_OBF
) {
669 bscbus_cmd_log(csp
, BSC_CMD_CLEARING
, status
, data
);
675 bscbus_process_pending(struct bscbus_channel_state
*csp
, uint8_t status
)
677 /* We are waiting for an acknowledgement of a byte */
678 if (status
& H8_STR_OBF
) {
679 bscbus_cmd_log(csp
, BSC_CMD_PENDING
,
681 bscbus_trace(csp
, 'P', "bscbus_process_pending",
682 "moving to sending");
683 csp
->cmdstate
= BSCBUS_CMDSTATE_SENDING
;
685 * Send the next byte immediately.
686 * At this stage we should clear the OBF flag because that
687 * data has been used. IBF is still valid so do not clear that.
689 status
&= ~(H8_STR_OBF
);
690 bscbus_process_sending(csp
, status
);
695 bscbus_process_waiting(struct bscbus_channel_state
*csp
,
696 uint8_t status
, uint8_t data
)
699 boolean_t ready
= B_FALSE
;
702 if (status
& H8_STR_OBF
) {
703 csp
->reply
[rcvd
= csp
->index
] = data
;
704 if (++rcvd
< BSCBUS_BUFSIZE
)
707 bscbus_trace(csp
, 'D', "bscbus_process_waiting",
708 "rcvd %d: $%02x $%02x $%02x $%02x $%02x $%02x $%02x $%02x",
710 csp
->reply
[0], csp
->reply
[1],
711 csp
->reply
[2], csp
->reply
[3],
712 csp
->reply
[4], csp
->reply
[5],
713 csp
->reply
[6], csp
->reply
[7]);
718 * No bytes received this time through (though there
719 * might be a partial packet sitting in the buffer).
723 } else if (rcvd
>= BSCBUS_BUFSIZE
) {
725 * Buffer overflow; discard the data & treat as an error
726 * (even if the last byte read did claim to terminate a
727 * packet, it can't be a valid one 'cos it's too long!)
729 bscbus_cmd_log(csp
, BSC_CMD_ERROR_OFLOW
, status
, data
);
731 csp
->cmdstate
= BSCBUS_CMDSTATE_ERROR
;
732 csp
->error
= LOMBUS_ERR_OFLOW
;
734 } else if ((data
& BSCBUS_LAST
) == 0) {
736 * Packet not yet complete; leave the partial packet in
737 * the buffer for later ...
739 bscbus_cmd_log(csp
, BSC_CMD_REPLY
, status
, data
);
740 } else if ((data
& BSCBUS_MASK
) != BSCBUS_STATUS
) {
741 /* Invalid "status" byte - maybe an echo of the command? */
742 bscbus_cmd_log(csp
, BSC_CMD_ERROR_STATUS
, status
, data
);
744 csp
->cmdstate
= BSCBUS_CMDSTATE_ERROR
;
745 csp
->error
= LOMBUS_ERR_BADSTATUS
;
747 } else if ((data
& BSCBUS_SEQ
) != csp
->sequence
) {
748 /* Wrong sequence number! Flag this as an error */
749 bscbus_cmd_log(csp
, BSC_CMD_ERROR_SEQ
, status
, data
);
751 csp
->cmdstate
= BSCBUS_CMDSTATE_ERROR
;
752 csp
->error
= LOMBUS_ERR_SEQUENCE
;
756 * Finally, we know that's it's a valid reply to our
757 * last command. Update the ASYNC status, derive the
758 * reply parameter (if any), and check the ERROR bit
759 * to find out what the parameter means.
761 * Note that not all the values read/assigned here
762 * are meaningful, but it doesn't matter; the waiting
763 * thread will know which one(s) it should check.
765 bscbus_cmd_log(csp
, BSC_CMD_COMPLETE
, status
, data
);
766 csp
->async
= (data
& BSCBUS_STATUS_ASYNC
) ? 1 : 0;
768 tmp
= ((data
& BSCBUS_STATUS_MSB
) ? 0x80 : 0) | csp
->reply
[0];
769 if (data
& BSCBUS_STATUS_ERR
) {
770 csp
->cmdstate
= BSCBUS_CMDSTATE_ERROR
;
773 csp
->cmdstate
= BSCBUS_CMDSTATE_READY
;
782 * Packet receive handler
784 * This routine should be called from the low-level softint,
785 * or bscbus_cmd() (for polled operation), with the
786 * low-level mutex already held.
789 bscbus_process(struct bscbus_channel_state
*csp
,
790 uint8_t status
, uint8_t data
)
792 boolean_t ready
= B_FALSE
;
794 ASSERT(mutex_owned(csp
->lo_mutex
));
796 if ((status
& H8_STR_OBF
) || (status
& H8_STR_IBF
)) {
797 bscbus_trace(csp
, 'D', "bscbus_process",
798 "state %d; error $%x",
799 csp
->cmdstate
, csp
->error
);
802 switch (csp
->cmdstate
) {
803 case BSCBUS_CMDSTATE_CLEARING
:
804 bscbus_process_clearing(csp
, status
, data
);
806 case BSCBUS_CMDSTATE_SENDING
:
807 bscbus_process_sending(csp
, status
);
809 case BSCBUS_CMDSTATE_PENDING
:
810 bscbus_process_pending(csp
, status
);
812 case BSCBUS_CMDSTATE_WAITING
:
813 ready
= bscbus_process_waiting(csp
, status
, data
);
821 * Check for timeouts - but only if the command has not yet
822 * completed (ready is true when command completes in this
823 * call to bscbus_process OR cmdstate is READY or ERROR if
824 * this is a spurious call to bscbus_process i.e. a spurious
828 ((ddi_get_lbolt() - csp
->deadline
) > 0) &&
829 csp
->cmdstate
!= BSCBUS_CMDSTATE_READY
&&
830 csp
->cmdstate
!= BSCBUS_CMDSTATE_ERROR
) {
831 bscbus_trace(csp
, 'P', "bscbus_process",
832 "timeout previous state %d; error $%x",
833 csp
->cmdstate
, csp
->error
);
834 bscbus_cmd_log(csp
, BSC_CMD_ERROR_TOUT
, status
, data
);
835 if (csp
->cmdstate
== BSCBUS_CMDSTATE_CLEARING
) {
836 /* Move onto sending because busy might be stuck */
837 csp
->cmdstate
= BSCBUS_CMDSTATE_SENDING
;
838 /* Extend timeout relative to original start time */
839 csp
->deadline
+= drv_usectohz(LOMBUS_CMD_TIMEOUT
/1000);
840 } else if (csp
->cmdstate
!= BSCBUS_CMDSTATE_IDLE
) {
841 csp
->cmdstate
= BSCBUS_CMDSTATE_ERROR
;
842 csp
->error
= LOMBUS_ERR_TIMEOUT
;
847 if ((status
& H8_STR_OBF
) || (status
& H8_STR_IBF
) || ready
) {
848 bscbus_trace(csp
, 'D', "bscbus_process",
849 "last $%02x; state %d; error $%x; ready %d",
850 data
, csp
->cmdstate
, csp
->error
, ready
);
853 cv_broadcast(csp
->lo_cv
);
857 bscbus_hwintr(caddr_t arg
)
859 struct bscbus_channel_state
*csp
= (void *)arg
;
862 uint8_t data
= 0xb0 /* Dummy value */;
864 mutex_enter(csp
->lo_mutex
);
866 * Read the registers to ensure that the interrupt is cleared.
867 * Status must be read first because reading data changes the
869 * We always read the data because that clears the interrupt down.
870 * This is horrible hardware semantics but we have to do it!
872 status
= bscbus_get_reg(csp
, H8_STR
);
873 data
= bscbus_get_reg(csp
, H8_ODR
);
874 if (!(status
& H8_STR_OBF
)) {
875 bscbus_cmd_log(csp
, BSC_CMD_V1INTRUNCL
, status
, data
);
876 csp
->unclaimed_count
++;
878 bscbus_cmd_log(csp
, BSC_CMD_V1INTR
, status
, data
);
880 if (status
& H8_STR_TOKENPROTOCOL
) {
881 bscbus_process(csp
, status
, data
);
882 if (csp
->interrupt_failed
) {
883 bscbus_trace(csp
, 'I', "bscbus_hwintr:",
884 "interrupt fault cleared channel %d", csp
->chno
);
885 csp
->interrupt_failed
= B_FALSE
;
886 csp
->poll_hz
= drv_usectohz(BSCBUS_CMD_POLL
/ 1000);
890 mutex_exit(csp
->lo_mutex
);
891 return (DDI_INTR_CLAIMED
);
895 bscbus_poll(struct bscbus_channel_state
*csp
)
898 * This routine is only called if we timeout in userland
899 * waiting for an interrupt. This generally means that we have
900 * lost interrupt capabilities or that something has gone
901 * wrong. In this case we are allowed to access the hardware
902 * and read the data register if necessary.
903 * If interrupts return then recovery actions should mend us!
906 uint8_t data
= 0xfa; /* Dummy value */
908 ASSERT(mutex_owned(csp
->lo_mutex
));
910 /* Should look for data to receive */
911 status
= bscbus_get_reg(csp
, H8_STR
);
912 if (status
& H8_STR_OBF
) {
913 /* There is data available */
914 data
= bscbus_get_reg(csp
, H8_ODR
);
915 bscbus_cmd_log(csp
, BSC_CMD_PROCESS
, status
, data
);
917 bscbus_process(csp
, status
, data
);
923 * This routine builds a command and sets it in progress.
926 bscbus_cmd(HANDLE_TYPE
*hdlp
, ptrdiff_t vreg
, uint_t val
, uint_t cmd
)
928 struct bscbus_channel_state
*csp
;
933 * First of all, wait for the interface to be available.
935 * NOTE: we blow through all the mutex/cv/state checking and
936 * preempt any command in progress if the system is panicking!
938 csp
= HANDLE_PRIVATE(hdlp
);
939 mutex_enter(csp
->lo_mutex
);
940 while (csp
->cmdstate
!= BSCBUS_CMDSTATE_IDLE
&& !ddi_in_panic())
941 cv_wait(csp
->lo_cv
, csp
->lo_mutex
);
943 csp
->cmdstate
= BSCBUS_CMDSTATE_BUSY
;
944 csp
->sequence
= (csp
->sequence
+ BSCBUS_SEQ_LSB
) & BSCBUS_SEQ
;
947 * We have exclusive ownership, so assemble the command (backwards):
949 * [byte 0] Command: modified by XADDR and/or WMSB bits
950 * [Optional] Parameter: Value to write (low 7 bits)
951 * [Optional] Parameter: Register number (high 7 bits)
952 * [Optional] Parameter: Register number (low 7 bits)
954 csp
->cmdp
= &csp
->cmdbuf
[0];
955 *csp
->cmdp
++ = BSCBUS_CMD
| csp
->sequence
| cmd
;
957 case BSCBUS_CMD_WRITE
:
958 *csp
->cmdp
++ = val
& 0x7f;
960 csp
->cmdbuf
[0] |= BSCBUS_CMD_WMSB
;
962 case BSCBUS_CMD_READ
:
963 if (BSCBUS_VREG_HI(vreg
) != 0) {
964 *csp
->cmdp
++ = BSCBUS_VREG_HI(vreg
);
965 csp
->cmdbuf
[0] |= BSCBUS_CMD_XADDR
;
967 *csp
->cmdp
++ = BSCBUS_VREG_LO(vreg
);
974 * Check and update the H8 h/w fault status before accessing
975 * the chip registers. If there's a (new or previous) fault,
976 * we'll run through the protocol but won't really touch the
977 * hardware and all commands will timeout. If a previously
978 * discovered fault has now gone away (!), then we can (try to)
979 * proceed with the new command (probably a probe).
981 bscbus_check_fault_status(csp
);
984 * Prepare for the command (to be processed by the interrupt
985 * handler and/or polling loop below), and wait for a response
988 start
= ddi_get_lbolt();
989 csp
->deadline
= start
+ drv_usectohz(LOMBUS_CMD_TIMEOUT
/1000);
992 csp
->result
= DUMMY_VALUE
;
994 status
= bscbus_get_reg(csp
, H8_STR
);
995 if (status
& H8_STR_BUSY
) {
996 bscbus_cmd_log(csp
, BSC_CMD_BUSY
, status
, 0xfd);
998 * Must ensure that the busy state has cleared before
999 * sending the command
1001 csp
->cmdstate
= BSCBUS_CMDSTATE_CLEARING
;
1002 bscbus_trace(csp
, 'P', "bscbus_cmd",
1003 "h8 reporting status (%x) busy - clearing", status
);
1005 /* It is clear to send the command immediately */
1006 csp
->cmdstate
= BSCBUS_CMDSTATE_SENDING
;
1007 bscbus_trace(csp
, 'P', "bscbus_cmd",
1008 "sending first byte of command, status %x", status
);
1012 csp
->poll_hz
= drv_usectohz(
1013 (csp
->interrupt_failed
?
1014 BSCBUS_CMD_POLLNOINTS
: BSCBUS_CMD_POLL
) / 1000);
1016 while ((csp
->cmdstate
!= BSCBUS_CMDSTATE_READY
) &&
1017 (csp
->cmdstate
!= BSCBUS_CMDSTATE_ERROR
)) {
1018 ASSERT(csp
->cmdstate
!= BSCBUS_CMDSTATE_IDLE
);
1020 if ((cv_reltimedwait(csp
->lo_cv
, csp
->lo_mutex
,
1021 csp
->poll_hz
, TR_CLOCK_TICK
) == -1) &&
1022 csp
->cmdstate
!= BSCBUS_CMDSTATE_READY
&&
1023 csp
->cmdstate
!= BSCBUS_CMDSTATE_ERROR
) {
1024 if (!csp
->interrupt_failed
) {
1025 bscbus_trace(csp
, 'I', "bscbus_cmd:",
1026 "interrupt_failed channel %d", csp
->chno
);
1027 csp
->interrupt_failed
= B_TRUE
;
1028 csp
->poll_hz
= drv_usectohz(
1029 BSCBUS_CMD_POLLNOINTS
/ 1000);
1036 * The return value may not be meaningful but retrieve it anyway
1039 if (bscbus_faulty(csp
)) {
1041 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_SIOHW
;
1042 } else if (csp
->cmdstate
!= BSCBUS_CMDSTATE_READY
) {
1044 * Some problem here ... transfer the error code from
1045 * the per-instance state to the per-handle fault flag.
1046 * The error code shouldn't be zero!
1048 if (csp
->error
!= 0)
1049 HANDLE_FAULT(hdlp
) = csp
->error
;
1051 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_BADERRCODE
;
1058 csp
->cmdstate
= BSCBUS_CMDSTATE_IDLE
;
1059 cv_broadcast(csp
->lo_cv
);
1060 mutex_exit(csp
->lo_mutex
);
1066 * Space 0 - LOM virtual register access
1067 * Only 8-bit accesses are supported.
1070 bscbus_vreg_get8(HANDLE_TYPE
*hdlp
, uint8_t *addr
)
1075 * Check the offset that the caller has added to the base address
1076 * against the length of the mapping originally requested.
1078 offset
= ADDR_TO_OFFSET(addr
, hdlp
);
1079 if (offset
< 0 || offset
>= HANDLE_MAPLEN(hdlp
)) {
1081 * Invalid access - flag a fault and return a dummy value
1083 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_NUM
;
1084 return (DUMMY_VALUE
);
1088 * Derive the virtual register number and run the command
1090 return (bscbus_cmd(hdlp
, ADDR_TO_VREG(addr
), 0, BSCBUS_CMD_READ
));
1094 bscbus_vreg_put8(HANDLE_TYPE
*hdlp
, uint8_t *addr
, uint8_t val
)
1099 * Check the offset that the caller has added to the base address
1100 * against the length of the mapping originally requested.
1102 offset
= ADDR_TO_OFFSET(addr
, hdlp
);
1103 if (offset
< 0 || offset
>= HANDLE_MAPLEN(hdlp
)) {
1105 * Invalid access - flag a fault and return
1107 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_NUM
;
1112 * Derive the virtual register number and run the command
1114 (void) bscbus_cmd(hdlp
, ADDR_TO_VREG(addr
), val
, BSCBUS_CMD_WRITE
);
1118 bscbus_vreg_rep_get8(HANDLE_TYPE
*hdlp
, uint8_t *host_addr
,
1119 uint8_t *dev_addr
, size_t repcount
, uint_t flags
)
1123 inc
= (flags
& DDI_DEV_AUTOINCR
) ? 1 : 0;
1124 for (; repcount
--; dev_addr
+= inc
)
1125 *host_addr
++ = bscbus_vreg_get8(hdlp
, dev_addr
);
1129 bscbus_vreg_rep_put8(HANDLE_TYPE
*hdlp
, uint8_t *host_addr
,
1130 uint8_t *dev_addr
, size_t repcount
, uint_t flags
)
1134 inc
= (flags
& DDI_DEV_AUTOINCR
) ? 1 : 0;
1135 for (; repcount
--; dev_addr
+= inc
)
1136 bscbus_vreg_put8(hdlp
, dev_addr
, *host_addr
++);
1141 * Space 1 - LOM watchdog pat register access
1142 * Only 8-bit accesses are supported.
1144 * Reads have no effect and return 0.
1146 * Multi-byte reads (using ddi_rep_get8(9F)) are a fairly inefficient
1147 * way of zeroing the destination area ;-) and still won't pat the dog.
1149 * Multi-byte writes (using ddi_rep_put8(9F)) will almost certainly
1150 * only count as a single pat, no matter how many bytes the caller
1151 * says to write, as the inter-pat time is VERY long compared with
1152 * the time it will take to read the memory source area.
1156 bscbus_pat_get8(HANDLE_TYPE
*hdlp
, uint8_t *addr
)
1161 * Check the offset that the caller has added to the base address
1162 * against the length of the mapping originally requested.
1164 offset
= ADDR_TO_OFFSET(addr
, hdlp
);
1165 if (offset
< 0 || offset
>= HANDLE_MAPLEN(hdlp
)) {
1167 * Invalid access - flag a fault and return a dummy value
1169 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_NUM
;
1170 return (DUMMY_VALUE
);
1177 bscbus_pat_put8(HANDLE_TYPE
*hdlp
, uint8_t *addr
, uint8_t val
)
1179 struct bscbus_channel_state
*csp
;
1183 * Check the offset that the caller has added to the base address
1184 * against the length of the mapping originally requested.
1186 offset
= ADDR_TO_OFFSET(addr
, hdlp
);
1187 if (offset
< 0 || offset
>= HANDLE_MAPLEN(hdlp
)) {
1189 * Invalid access - flag a fault and return
1191 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_NUM
;
1195 csp
= HANDLE_PRIVATE(hdlp
);
1196 mutex_enter(csp
->dog_mutex
);
1197 bscbus_pat_dog(csp
, val
);
1198 mutex_exit(csp
->dog_mutex
);
1202 bscbus_pat_rep_get8(HANDLE_TYPE
*hdlp
, uint8_t *host_addr
,
1203 uint8_t *dev_addr
, size_t repcount
, uint_t flags
)
1207 inc
= (flags
& DDI_DEV_AUTOINCR
) ? 1 : 0;
1208 for (; repcount
--; dev_addr
+= inc
)
1209 *host_addr
++ = bscbus_pat_get8(hdlp
, dev_addr
);
1213 bscbus_pat_rep_put8(HANDLE_TYPE
*hdlp
, uint8_t *host_addr
,
1214 uint8_t *dev_addr
, size_t repcount
, uint_t flags
)
1218 inc
= (flags
& DDI_DEV_AUTOINCR
) ? 1 : 0;
1219 for (; repcount
--; dev_addr
+= inc
)
1220 bscbus_pat_put8(hdlp
, dev_addr
, *host_addr
++);
1225 * Space 2 - LOM async event flag register access
1226 * Only 16-bit accesses are supported.
1229 bscbus_event_get16(HANDLE_TYPE
*hdlp
, uint16_t *addr
)
1231 struct bscbus_channel_state
*csp
;
1235 * Check the offset that the caller has added to the base address
1236 * against the length of the mapping orignally requested.
1238 offset
= ADDR_TO_OFFSET(addr
, hdlp
);
1239 if (offset
< 0 || (offset
%2) != 0 || offset
>= HANDLE_MAPLEN(hdlp
)) {
1241 * Invalid access - flag a fault and return a dummy value
1243 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_NUM
;
1244 return (DUMMY_VALUE
);
1248 * Return the value of the asynchronous-event-pending flag
1249 * as passed back by the LOM at the end of the last command.
1251 csp
= HANDLE_PRIVATE(hdlp
);
1252 return (csp
->async
);
1256 bscbus_event_put16(HANDLE_TYPE
*hdlp
, uint16_t *addr
, uint16_t val
)
1260 _NOTE(ARGUNUSED(val
))
1263 * Check the offset that the caller has added to the base address
1264 * against the length of the mapping originally requested.
1266 offset
= ADDR_TO_OFFSET(addr
, hdlp
);
1267 if (offset
< 0 || (offset
%2) != 0 || offset
>= HANDLE_MAPLEN(hdlp
)) {
1269 * Invalid access - flag a fault and return
1271 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_NUM
;
1276 * The user can't overwrite the asynchronous-event-pending flag!
1278 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_RO
;
1282 bscbus_event_rep_get16(HANDLE_TYPE
*hdlp
, uint16_t *host_addr
,
1283 uint16_t *dev_addr
, size_t repcount
, uint_t flags
)
1287 inc
= (flags
& DDI_DEV_AUTOINCR
) ? 1 : 0;
1288 for (; repcount
--; dev_addr
+= inc
)
1289 *host_addr
++ = bscbus_event_get16(hdlp
, dev_addr
);
1293 bscbus_event_rep_put16(HANDLE_TYPE
*hdlp
, uint16_t *host_addr
,
1294 uint16_t *dev_addr
, size_t repcount
, uint_t flags
)
1298 inc
= (flags
& DDI_DEV_AUTOINCR
) ? 1 : 0;
1299 for (; repcount
--; dev_addr
+= inc
)
1300 bscbus_event_put16(hdlp
, dev_addr
, *host_addr
++);
1305 * All spaces - access handle fault information
1306 * Only 32-bit accesses are supported.
1309 bscbus_meta_get32(HANDLE_TYPE
*hdlp
, uint32_t *addr
)
1311 struct bscbus_channel_state
*csp
;
1315 * Derive the offset that the caller has added to the base
1316 * address originally returned, and use it to determine
1317 * which meta-register is to be accessed ...
1319 offset
= ADDR_TO_OFFSET(addr
, hdlp
);
1321 case LOMBUS_FAULT_REG
:
1323 * This meta-register provides a code for the most
1324 * recent virtual register access fault, if any.
1326 return (HANDLE_FAULT(hdlp
));
1328 case LOMBUS_PROBE_REG
:
1330 * Reading this meta-register clears any existing fault
1331 * (at the virtual, not the hardware access layer), then
1332 * runs a NOP command and returns the fault code from that.
1334 HANDLE_FAULT(hdlp
) = 0;
1335 (void) bscbus_cmd(hdlp
, 0, 0, BSCBUS_CMD_NOP
);
1336 return (HANDLE_FAULT(hdlp
));
1338 case LOMBUS_ASYNC_REG
:
1340 * Obsolescent - but still supported for backwards
1341 * compatibility. This is an alias for the newer
1342 * LOMBUS_EVENT_REG, but doesn't require a separate
1343 * "reg" entry and ddi_regs_map_setup() call.
1345 * It returns the value of the asynchronous-event-pending
1346 * flag as passed back by the BSC at the end of the last
1347 * completed command.
1349 csp
= HANDLE_PRIVATE(hdlp
);
1350 return (csp
->async
);
1354 * Invalid access - flag a fault and return a dummy value
1356 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1357 return (DUMMY_VALUE
);
1362 bscbus_meta_put32(HANDLE_TYPE
*hdlp
, uint32_t *addr
, uint32_t val
)
1367 * Derive the offset that the caller has added to the base
1368 * address originally returned, and use it to determine
1369 * which meta-register is to be accessed ...
1371 offset
= ADDR_TO_OFFSET(addr
, hdlp
);
1373 case LOMBUS_FAULT_REG
:
1375 * This meta-register contains a code for the most
1376 * recent virtual register access fault, if any.
1377 * It can be cleared simply by writing 0 to it.
1379 HANDLE_FAULT(hdlp
) = val
;
1382 case LOMBUS_PROBE_REG
:
1384 * Writing this meta-register clears any existing fault
1385 * (at the virtual, not the hardware acess layer), then
1386 * runs a NOP command. The caller can check the fault
1387 * code later if required.
1389 HANDLE_FAULT(hdlp
) = 0;
1390 (void) bscbus_cmd(hdlp
, 0, 0, BSCBUS_CMD_NOP
);
1395 * Invalid access - flag a fault
1397 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1403 bscbus_meta_rep_get32(HANDLE_TYPE
*hdlp
, uint32_t *host_addr
,
1404 uint32_t *dev_addr
, size_t repcount
, uint_t flags
)
1408 inc
= (flags
& DDI_DEV_AUTOINCR
) ? 1 : 0;
1409 for (; repcount
--; dev_addr
+= inc
)
1410 *host_addr
++ = bscbus_meta_get32(hdlp
, dev_addr
);
1414 bscbus_meta_rep_put32(HANDLE_TYPE
*hdlp
, uint32_t *host_addr
,
1415 uint32_t *dev_addr
, size_t repcount
, uint_t flags
)
1419 inc
= (flags
& DDI_DEV_AUTOINCR
) ? 1 : 0;
1420 for (; repcount
--; dev_addr
+= inc
)
1421 bscbus_meta_put32(hdlp
, dev_addr
, *host_addr
++);
1426 * Finally, some dummy functions for all unsupported access
1427 * space/size/mode combinations ...
1430 bscbus_no_get8(HANDLE_TYPE
*hdlp
, uint8_t *addr
)
1432 _NOTE(ARGUNUSED(addr
))
1435 * Invalid access - flag a fault and return a dummy value
1437 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1438 return (DUMMY_VALUE
);
1442 bscbus_no_put8(HANDLE_TYPE
*hdlp
, uint8_t *addr
, uint8_t val
)
1444 _NOTE(ARGUNUSED(addr
, val
))
1447 * Invalid access - flag a fault
1449 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1453 bscbus_no_rep_get8(HANDLE_TYPE
*hdlp
, uint8_t *host_addr
,
1454 uint8_t *dev_addr
, size_t repcount
, uint_t flags
)
1456 _NOTE(ARGUNUSED(host_addr
, dev_addr
, repcount
, flags
))
1459 * Invalid access - flag a fault
1461 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1465 bscbus_no_rep_put8(HANDLE_TYPE
*hdlp
, uint8_t *host_addr
,
1466 uint8_t *dev_addr
, size_t repcount
, uint_t flags
)
1468 _NOTE(ARGUNUSED(host_addr
, dev_addr
, repcount
, flags
))
1471 * Invalid access - flag a fault
1473 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1477 bscbus_no_get16(HANDLE_TYPE
*hdlp
, uint16_t *addr
)
1479 _NOTE(ARGUNUSED(addr
))
1482 * Invalid access - flag a fault and return a dummy value
1484 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1485 return (DUMMY_VALUE
);
1489 bscbus_no_put16(HANDLE_TYPE
*hdlp
, uint16_t *addr
, uint16_t val
)
1491 _NOTE(ARGUNUSED(addr
, val
))
1494 * Invalid access - flag a fault
1496 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1500 bscbus_no_rep_get16(HANDLE_TYPE
*hdlp
, uint16_t *host_addr
,
1501 uint16_t *dev_addr
, size_t repcount
, uint_t flags
)
1503 _NOTE(ARGUNUSED(host_addr
, dev_addr
, repcount
, flags
))
1506 * Invalid access - flag a fault
1508 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1512 bscbus_no_rep_put16(HANDLE_TYPE
*hdlp
, uint16_t *host_addr
,
1513 uint16_t *dev_addr
, size_t repcount
, uint_t flags
)
1515 _NOTE(ARGUNUSED(host_addr
, dev_addr
, repcount
, flags
))
1518 * Invalid access - flag a fault
1520 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1524 bscbus_no_get64(HANDLE_TYPE
*hdlp
, uint64_t *addr
)
1526 _NOTE(ARGUNUSED(addr
))
1529 * Invalid access - flag a fault and return a dummy value
1531 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1532 return (DUMMY_VALUE
);
1536 bscbus_no_put64(HANDLE_TYPE
*hdlp
, uint64_t *addr
, uint64_t val
)
1538 _NOTE(ARGUNUSED(addr
, val
))
1541 * Invalid access - flag a fault
1543 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1547 bscbus_no_rep_get64(HANDLE_TYPE
*hdlp
, uint64_t *host_addr
,
1548 uint64_t *dev_addr
, size_t repcount
, uint_t flags
)
1550 _NOTE(ARGUNUSED(host_addr
, dev_addr
, repcount
, flags
))
1553 * Invalid access - flag a fault
1555 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1559 bscbus_no_rep_put64(HANDLE_TYPE
*hdlp
, uint64_t *host_addr
,
1560 uint64_t *dev_addr
, size_t repcount
, uint_t flags
)
1562 _NOTE(ARGUNUSED(host_addr
, dev_addr
, repcount
, flags
))
1565 * Invalid access - flag a fault
1567 HANDLE_FAULT(hdlp
) = LOMBUS_ERR_REG_SIZE
;
1571 bscbus_acc_fault_check(HANDLE_TYPE
*hdlp
)
1573 return (HANDLE_FAULT(hdlp
) != 0);
1577 * Hardware setup - ensure that there are no pending transactions and
1578 * hence no pending interrupts. We do this be ensuring that the BSC is
1579 * not reporting a busy condition and that it does not have any data
1580 * pending in its output buffer.
1581 * This is important because if we have pending interrupts at attach
1582 * time Solaris will hang due to bugs in ddi_get_iblock_cookie.
1585 bscbus_hw_reset(struct bscbus_channel_state
*csp
)
1590 if (csp
->map_count
== 0) {
1591 /* No-one using this instance - no need to reset hardware */
1595 bscbus_trace(csp
, 'R', "bscbus_hw_reset",
1596 "resetting channel %d", csp
->chno
);
1598 status
= bscbus_get_reg(csp
, H8_STR
);
1599 if (status
& H8_STR_BUSY
) {
1601 * Give the h8 time to complete a reply.
1602 * In practice we should never worry about this
1603 * because whenever we get here it will have been
1604 * long enough for the h8 to complete a reply
1606 bscbus_cmd_log(csp
, BSC_CMD_BUSY
, status
, 0);
1607 bscbus_trace(csp
, 'R', "bscbus_hw_reset",
1608 "h8 reporting status (%x) busy - waiting", status
);
1609 if (ddi_in_panic()) {
1610 drv_usecwait(BSCBUS_HWRESET_POLL
/1000);
1612 delay(drv_usectohz(BSCBUS_HWRESET_POLL
/1000));
1615 /* Reply should be completed by now. Try to clear busy status */
1616 status
= bscbus_get_reg(csp
, H8_STR
);
1617 if (status
& (H8_STR_BUSY
| H8_STR_OBF
)) {
1618 bscbus_trace(csp
, 'R', "bscbus_hw_reset",
1619 "clearing busy status for channel %d", csp
->chno
);
1621 for (timeout
= BSCBUS_HWRESET_TIMEOUT
;
1623 timeout
-= BSCBUS_HWRESET_POLL
) {
1624 if (status
& H8_STR_OBF
) {
1625 (void) bscbus_get_reg(csp
, H8_ODR
);
1626 if (!(status
& H8_STR_BUSY
)) {
1631 if (ddi_in_panic()) {
1632 drv_usecwait(BSCBUS_HWRESET_POLL
/1000);
1634 delay(drv_usectohz(BSCBUS_HWRESET_POLL
/1000));
1636 status
= bscbus_get_reg(csp
, H8_STR
);
1639 cmn_err(CE_WARN
, "bscbus_hw_reset: timed out "
1640 "clearing busy status");
1644 * We read ODR just in case there is a pending interrupt with
1645 * no data. This is potentially dangerous because we could get
1646 * out of sync due to race conditions BUT at this point the
1647 * channel should be idle so it is safe.
1649 (void) bscbus_get_reg(csp
, H8_ODR
);
1653 * Higher-level setup & teardown
1657 bscbus_offline(struct bscbus_state
*ssp
)
1659 if (ssp
->h8_handle
!= NULL
)
1660 ddi_regs_map_free(&ssp
->h8_handle
);
1661 ssp
->h8_handle
= NULL
;
1662 ssp
->h8_regs
= NULL
;
1666 bscbus_online(struct bscbus_state
*ssp
)
1673 ssp
->h8_handle
= NULL
;
1674 ssp
->h8_regs
= (void *)NULL
;
1675 ssp
->per_channel_regs
= B_FALSE
;
1677 if (ddi_dev_nregs(ssp
->dip
, &nregs
) != DDI_SUCCESS
)
1683 * regset 0 represents the H8 interface registers
1685 err
= ddi_regs_map_setup(ssp
->dip
, 0, &p
, 0, 0,
1686 bscbus_dev_acc_attr
, &h
);
1687 if (err
!= DDI_SUCCESS
)
1691 ssp
->h8_regs
= (void *)p
;
1696 * If no registers are defined, succeed vacuously;
1697 * commands will be accepted, but we fake the accesses.
1703 * Remember that we are using the new register scheme.
1704 * reg set 0 is chan 0
1705 * reg set 1 is chan 1 ...
1706 * Interrupts are specified in that order but later
1707 * channels may not have interrupts.
1708 * We map the regs later on a per channel basis.
1710 ssp
->per_channel_regs
= B_TRUE
;
1717 bscbus_claim_channel(struct bscbus_channel_state
*csp
, boolean_t map_dog
)
1721 mutex_enter(csp
->ssp
->ch_mutex
);
1723 bscbus_trace(csp
, 'C', "bscbus_claim_channel",
1724 "claim channel for channel %d, count %d",
1725 csp
->chno
, csp
->map_count
);
1727 if (csp
->map_count
== 1) {
1728 /* No-one is using this channel - initialise it */
1729 bscbus_trace(csp
, 'C', "bscbus_claim_channel",
1730 "initialise channel %d, count %d",
1731 csp
->chno
, csp
->map_count
);
1733 mutex_init(csp
->dog_mutex
, NULL
, MUTEX_DRIVER
,
1734 (void *)(uintptr_t)__ipltospl(SPL7
- 1));
1735 csp
->map_dog
= map_dog
;
1736 csp
->interrupt_failed
= B_FALSE
;
1737 csp
->cmdstate
= BSCBUS_CMDSTATE_IDLE
;
1738 csp
->pat_retry_count
= 0;
1739 csp
->pat_fail_count
= 0;
1741 /* Map appropriate register set for this channel */
1742 if (csp
->ssp
->per_channel_regs
== B_TRUE
) {
1746 err
= ddi_regs_map_setup(csp
->ssp
->dip
, csp
->chno
,
1747 &p
, 0, 0, bscbus_dev_acc_attr
, &h
);
1749 if (err
!= DDI_SUCCESS
) {
1754 csp
->ch_regs
= (void *)p
;
1756 bscbus_trace(csp
, 'C', "bscbus_claim_channel",
1757 "mapped chno=%d ch_handle=%d ch_regs=%p",
1761 * if using the old reg property scheme use the
1764 csp
->ch_handle
= csp
->ssp
->h8_handle
;
1767 BSCBUS_CHANNEL_TO_OFFSET(csp
->chno
);
1770 /* Ensure no interrupts pending prior to getting iblk cookie */
1771 bscbus_hw_reset(csp
);
1773 if (csp
->map_dog
== 1) {
1775 * we don't want lo_mutex to be initialised
1776 * with an iblock cookie if we are the wdog,
1777 * because we don't use interrupts.
1779 mutex_init(csp
->lo_mutex
, NULL
,
1780 MUTEX_DRIVER
, NULL
);
1781 cv_init(csp
->lo_cv
, NULL
,
1783 csp
->unclaimed_count
= 0;
1788 * check that there is an interrupt for this
1789 * this channel. If we fail to setup interrupts we
1790 * must unmap the registers and fail.
1792 err
= ddi_dev_nintrs(csp
->ssp
->dip
, &ninterrupts
);
1794 if (err
!= DDI_SUCCESS
) {
1798 if (ninterrupts
<= csp
->chno
) {
1800 "no interrupt available for "
1801 "bscbus channel %d", csp
->chno
);
1805 if (ddi_intr_hilevel(csp
->ssp
->dip
, csp
->chno
) != 0) {
1807 "bscbus interrupts are high "
1808 "level - channel not usable.");
1811 err
= ddi_get_iblock_cookie(csp
->ssp
->dip
,
1812 csp
->chno
, &csp
->lo_iblk
);
1813 if (err
!= DDI_SUCCESS
) {
1817 mutex_init(csp
->lo_mutex
, NULL
,
1818 MUTEX_DRIVER
, csp
->lo_iblk
);
1819 cv_init(csp
->lo_cv
, NULL
,
1821 csp
->unclaimed_count
= 0;
1823 err
= ddi_add_intr(csp
->ssp
->dip
, csp
->chno
,
1824 &csp
->lo_iblk
, NULL
,
1825 bscbus_hwintr
, (caddr_t
)csp
);
1826 if (err
!= DDI_SUCCESS
) {
1827 cv_destroy(csp
->lo_cv
);
1828 mutex_destroy(csp
->lo_mutex
);
1834 * The channel is now live and may
1835 * receive interrupts
1837 } else if (csp
->map_dog
!= map_dog
) {
1838 bscbus_trace(csp
, 'C', "bscbus_claim_channel",
1839 "request conflicts with previous mapping. old %x, new %x.",
1840 csp
->map_dog
, map_dog
);
1843 mutex_exit(csp
->ssp
->ch_mutex
);
1847 /* unmap regs for failed channel */
1848 if (csp
->ssp
->per_channel_regs
== B_TRUE
) {
1849 ddi_regs_map_free(&csp
->ch_handle
);
1851 csp
->ch_handle
= NULL
;
1852 csp
->ch_regs
= (void *)NULL
;
1855 mutex_exit(csp
->ssp
->ch_mutex
);
1860 bscbus_release_channel(struct bscbus_channel_state
*csp
)
1862 mutex_enter(csp
->ssp
->ch_mutex
);
1863 if (csp
->map_count
== 1) {
1864 /* No-one is now using this channel - shutdown channel */
1865 bscbus_trace(csp
, 'C', "bscbus_release_channel",
1866 "shutdown channel %d, count %d",
1867 csp
->chno
, csp
->map_count
);
1869 if (csp
->map_dog
== 0) {
1870 ASSERT(!ddi_intr_hilevel(csp
->ssp
->dip
, csp
->chno
));
1871 ddi_remove_intr(csp
->ssp
->dip
, csp
->chno
, csp
->lo_iblk
);
1873 cv_destroy(csp
->lo_cv
);
1874 mutex_destroy(csp
->lo_mutex
);
1875 mutex_destroy(csp
->dog_mutex
);
1876 bscbus_hw_reset(csp
);
1878 /* unmap registers if using the new register scheme */
1879 if (csp
->ssp
->per_channel_regs
== B_TRUE
) {
1880 ddi_regs_map_free(&csp
->ch_handle
);
1882 csp
->ch_handle
= NULL
;
1883 csp
->ch_regs
= (void *)NULL
;
1886 bscbus_trace(csp
, 'C', "bscbus_release_channel",
1887 "release channel %d, count %d",
1888 csp
->chno
, csp
->map_count
);
1889 mutex_exit(csp
->ssp
->ch_mutex
);
1897 #if defined(NDI_ACC_HDL_V2)
1899 static const ndi_acc_fns_t bscbus_vreg_acc_fns
= {
1900 NDI_ACC_FNS_CURRENT
,
1905 bscbus_vreg_rep_get8
,
1906 bscbus_vreg_rep_put8
,
1910 bscbus_no_rep_get16
,
1911 bscbus_no_rep_put16
,
1915 bscbus_meta_rep_get32
,
1916 bscbus_meta_rep_put32
,
1920 bscbus_no_rep_get64
,
1921 bscbus_no_rep_put64
,
1923 bscbus_acc_fault_check
1926 static const ndi_acc_fns_t bscbus_pat_acc_fns
= {
1927 NDI_ACC_FNS_CURRENT
,
1932 bscbus_pat_rep_get8
,
1933 bscbus_pat_rep_put8
,
1937 bscbus_no_rep_get16
,
1938 bscbus_no_rep_put16
,
1942 bscbus_meta_rep_get32
,
1943 bscbus_meta_rep_put32
,
1947 bscbus_no_rep_get64
,
1948 bscbus_no_rep_put64
,
1950 bscbus_acc_fault_check
1953 static const ndi_acc_fns_t bscbus_event_acc_fns
= {
1954 NDI_ACC_FNS_CURRENT
,
1964 bscbus_event_rep_get16
,
1965 bscbus_event_rep_put16
,
1969 bscbus_meta_rep_get32
,
1970 bscbus_meta_rep_put32
,
1974 bscbus_no_rep_get64
,
1975 bscbus_no_rep_put64
,
1977 bscbus_acc_fault_check
1981 bscbus_map_handle(struct bscbus_channel_state
*csp
, ddi_map_op_t op
,
1982 int space
, caddr_t vaddr
, off_t len
,
1983 ndi_acc_handle_t
*hdlp
, caddr_t
*addrp
)
1987 return (DDI_ME_UNIMPLEMENTED
);
1989 case DDI_MO_MAP_LOCKED
:
1990 if (bscbus_claim_channel(csp
,
1991 (space
== LOMBUS_PAT_SPACE
)) == 0) {
1992 return (DDI_ME_GENERIC
);
1997 return (DDI_ME_REGSPEC_RANGE
);
1999 case LOMBUS_VREG_SPACE
:
2000 ndi_set_acc_fns(hdlp
, &bscbus_vreg_acc_fns
);
2003 case LOMBUS_PAT_SPACE
:
2004 ndi_set_acc_fns(hdlp
, &bscbus_pat_acc_fns
);
2007 case LOMBUS_EVENT_SPACE
:
2008 ndi_set_acc_fns(hdlp
, &bscbus_event_acc_fns
);
2011 hdlp
->ah_addr
= *addrp
= vaddr
;
2013 hdlp
->ah_bus_private
= csp
;
2014 return (DDI_SUCCESS
);
2018 hdlp
->ah_bus_private
= NULL
;
2019 bscbus_release_channel(csp
);
2020 return (DDI_SUCCESS
);
2027 bscbus_map_handle(struct bscbus_channel_state
*csp
, ddi_map_op_t op
,
2028 int space
, caddr_t vaddr
, off_t len
,
2029 ddi_acc_hdl_t
*hdlp
, caddr_t
*addrp
)
2031 ddi_acc_impl_t
*aip
= hdlp
->ah_platform_private
;
2035 return (DDI_ME_UNIMPLEMENTED
);
2037 case DDI_MO_MAP_LOCKED
:
2038 if (bscbus_claim_channel(csp
,
2039 (space
== LOMBUS_PAT_SPACE
)) == 0) {
2040 return (DDI_ME_GENERIC
);
2045 return (DDI_ME_REGSPEC_RANGE
);
2047 case LOMBUS_VREG_SPACE
:
2048 aip
->ahi_get8
= bscbus_vreg_get8
;
2049 aip
->ahi_put8
= bscbus_vreg_put8
;
2050 aip
->ahi_rep_get8
= bscbus_vreg_rep_get8
;
2051 aip
->ahi_rep_put8
= bscbus_vreg_rep_put8
;
2053 aip
->ahi_get16
= bscbus_no_get16
;
2054 aip
->ahi_put16
= bscbus_no_put16
;
2055 aip
->ahi_rep_get16
= bscbus_no_rep_get16
;
2056 aip
->ahi_rep_put16
= bscbus_no_rep_put16
;
2058 aip
->ahi_get32
= bscbus_meta_get32
;
2059 aip
->ahi_put32
= bscbus_meta_put32
;
2060 aip
->ahi_rep_get32
= bscbus_meta_rep_get32
;
2061 aip
->ahi_rep_put32
= bscbus_meta_rep_put32
;
2063 aip
->ahi_get64
= bscbus_no_get64
;
2064 aip
->ahi_put64
= bscbus_no_put64
;
2065 aip
->ahi_rep_get64
= bscbus_no_rep_get64
;
2066 aip
->ahi_rep_put64
= bscbus_no_rep_put64
;
2068 aip
->ahi_fault_check
= bscbus_acc_fault_check
;
2071 case LOMBUS_PAT_SPACE
:
2072 aip
->ahi_get8
= bscbus_pat_get8
;
2073 aip
->ahi_put8
= bscbus_pat_put8
;
2074 aip
->ahi_rep_get8
= bscbus_pat_rep_get8
;
2075 aip
->ahi_rep_put8
= bscbus_pat_rep_put8
;
2077 aip
->ahi_get16
= bscbus_no_get16
;
2078 aip
->ahi_put16
= bscbus_no_put16
;
2079 aip
->ahi_rep_get16
= bscbus_no_rep_get16
;
2080 aip
->ahi_rep_put16
= bscbus_no_rep_put16
;
2082 aip
->ahi_get32
= bscbus_meta_get32
;
2083 aip
->ahi_put32
= bscbus_meta_put32
;
2084 aip
->ahi_rep_get32
= bscbus_meta_rep_get32
;
2085 aip
->ahi_rep_put32
= bscbus_meta_rep_put32
;
2087 aip
->ahi_get64
= bscbus_no_get64
;
2088 aip
->ahi_put64
= bscbus_no_put64
;
2089 aip
->ahi_rep_get64
= bscbus_no_rep_get64
;
2090 aip
->ahi_rep_put64
= bscbus_no_rep_put64
;
2092 aip
->ahi_fault_check
= bscbus_acc_fault_check
;
2095 case LOMBUS_EVENT_SPACE
:
2096 aip
->ahi_get8
= bscbus_no_get8
;
2097 aip
->ahi_put8
= bscbus_no_put8
;
2098 aip
->ahi_rep_get8
= bscbus_no_rep_get8
;
2099 aip
->ahi_rep_put8
= bscbus_no_rep_put8
;
2101 aip
->ahi_get16
= bscbus_event_get16
;
2102 aip
->ahi_put16
= bscbus_event_put16
;
2103 aip
->ahi_rep_get16
= bscbus_event_rep_get16
;
2104 aip
->ahi_rep_put16
= bscbus_event_rep_put16
;
2106 aip
->ahi_get32
= bscbus_meta_get32
;
2107 aip
->ahi_put32
= bscbus_meta_put32
;
2108 aip
->ahi_rep_get32
= bscbus_meta_rep_get32
;
2109 aip
->ahi_rep_put32
= bscbus_meta_rep_put32
;
2111 aip
->ahi_get64
= bscbus_no_get64
;
2112 aip
->ahi_put64
= bscbus_no_put64
;
2113 aip
->ahi_rep_get64
= bscbus_no_rep_get64
;
2114 aip
->ahi_rep_put64
= bscbus_no_rep_put64
;
2116 aip
->ahi_fault_check
= bscbus_acc_fault_check
;
2119 hdlp
->ah_addr
= *addrp
= vaddr
;
2121 hdlp
->ah_bus_private
= csp
;
2122 return (DDI_SUCCESS
);
2126 hdlp
->ah_bus_private
= NULL
;
2127 bscbus_release_channel(csp
);
2128 return (DDI_SUCCESS
);
2132 #endif /* NDI_ACC_HDL_V2 */
2135 bscbus_map(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_map_req_t
*mp
,
2136 off_t off
, off_t len
, caddr_t
*addrp
)
2138 struct bscbus_child_info
*lcip
;
2139 struct bscbus_state
*ssp
;
2140 lombus_regspec_t
*rsp
;
2142 if ((ssp
= bscbus_getstate(dip
, -1, "bscbus_map")) == NULL
)
2143 return (DDI_FAILURE
); /* this "can't happen" */
2146 * Validate mapping request ...
2149 if (mp
->map_flags
!= DDI_MF_KERNEL_MAPPING
)
2150 return (DDI_ME_UNSUPPORTED
);
2151 if (mp
->map_handlep
== NULL
)
2152 return (DDI_ME_UNSUPPORTED
);
2153 if (mp
->map_type
!= DDI_MT_RNUMBER
)
2154 return (DDI_ME_UNIMPLEMENTED
);
2155 if ((lcip
= ddi_get_parent_data(rdip
)) == NULL
)
2156 return (DDI_ME_INVAL
);
2157 if ((rsp
= lcip
->rsp
) == NULL
)
2158 return (DDI_ME_INVAL
);
2159 if (mp
->map_obj
.rnumber
>= lcip
->nregs
)
2160 return (DDI_ME_RNUMBER_RANGE
);
2161 rsp
+= mp
->map_obj
.rnumber
;
2162 if (off
< 0 || off
>= rsp
->lombus_size
)
2163 return (DDI_ME_INVAL
);
2165 len
= rsp
->lombus_size
-off
;
2167 return (DDI_ME_INVAL
);
2168 if (off
+len
< 0 || off
+len
> rsp
->lombus_size
)
2169 return (DDI_ME_INVAL
);
2171 return (bscbus_map_handle(
2172 &ssp
->channel
[LOMBUS_SPACE_TO_CHANNEL(rsp
->lombus_space
)],
2173 mp
->map_op
, LOMBUS_SPACE_TO_REGSET(rsp
->lombus_space
),
2174 VREG_TO_ADDR(rsp
->lombus_base
+off
), len
, mp
->map_handlep
, addrp
));
2179 bscbus_ctlops(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_ctl_enum_t op
,
2180 void *arg
, void *result
)
2182 struct bscbus_child_info
*lcip
;
2183 lombus_regspec_t
*rsp
;
2193 if (bscbus_getstate(dip
, -1, "bscbus_ctlops") == NULL
)
2194 return (DDI_FAILURE
); /* this "can't happen" */
2200 case DDI_CTLOPS_INITCHILD
:
2202 * First, look up and validate the "reg" property.
2204 * It must be a non-empty integer array containing a set
2205 * of triples. Once we've verified that, we can treat it
2206 * as an array of type lombus_regspec_t[], which defines
2207 * the meaning of the elements of each triple:
2208 * + the first element of each triple must be a valid space
2209 * + the second and third elements (base, size) of each
2210 * triple must define a valid subrange of that space
2211 * If it passes all the tests, we save it away for future
2212 * reference in the child's parent-private-data field.
2215 err
= ddi_prop_lookup_int_array(DDI_DEV_T_ANY
, cdip
,
2216 DDI_PROP_DONTPASS
, "reg", ®s
, &nregs
);
2217 if (err
!= DDI_PROP_SUCCESS
)
2218 return (DDI_FAILURE
);
2220 err
= (nregs
<= 0 || (nregs
% LOMBUS_REGSPEC_SIZE
) != 0);
2221 nregs
/= LOMBUS_REGSPEC_SIZE
;
2222 rsp
= (lombus_regspec_t
*)regs
;
2223 for (i
= 0; i
< nregs
&& !err
; ++i
) {
2224 switch (LOMBUS_SPACE_TO_REGSET(rsp
[i
].lombus_space
)) {
2229 "child(%p): unknown reg space %d",
2230 (void *)cdip
, rsp
[i
].lombus_space
);
2233 case LOMBUS_VREG_SPACE
:
2234 limit
= LOMBUS_MAX_REG
+1;
2237 case LOMBUS_PAT_SPACE
:
2238 limit
= LOMBUS_PAT_REG
+1;
2241 case LOMBUS_EVENT_SPACE
:
2242 limit
= LOMBUS_EVENT_REG
+1;
2246 err
|= (rsp
[i
].lombus_base
< 0);
2247 err
|= (rsp
[i
].lombus_base
>= limit
);
2249 if (rsp
[i
].lombus_size
== 0)
2250 rsp
[i
].lombus_size
= limit
-rsp
[i
].lombus_base
;
2252 err
|= (rsp
[i
].lombus_size
< 0);
2253 err
|= (rsp
[i
].lombus_base
+rsp
[i
].lombus_size
< 0);
2254 err
|= (rsp
[i
].lombus_base
+rsp
[i
].lombus_size
> limit
);
2256 err
|= (rsp
[i
].lombus_base
+rsp
[i
].lombus_size
> limit
);
2261 ddi_prop_free(regs
);
2262 return (DDI_FAILURE
);
2265 lcip
= kmem_zalloc(sizeof (*lcip
), KM_SLEEP
);
2266 lcip
->nregs
= nregs
;
2268 ddi_set_parent_data(cdip
, lcip
);
2270 (void) snprintf(addr
, sizeof (addr
),
2271 "%x,%x", rsp
[0].lombus_space
, rsp
[0].lombus_base
);
2272 ddi_set_name_addr(cdip
, addr
);
2274 return (DDI_SUCCESS
);
2276 case DDI_CTLOPS_UNINITCHILD
:
2278 ddi_set_name_addr(cdip
, NULL
);
2279 lcip
= ddi_get_parent_data(cdip
);
2280 ddi_set_parent_data(cdip
, NULL
);
2281 ddi_prop_free(lcip
->rsp
);
2282 kmem_free(lcip
, sizeof (*lcip
));
2283 return (DDI_SUCCESS
);
2285 case DDI_CTLOPS_REPORTDEV
:
2287 return (DDI_FAILURE
);
2289 cmn_err(CE_CONT
, "?BSC device: %s@%s, %s#%d\n",
2290 ddi_node_name(rdip
), ddi_get_name_addr(rdip
),
2291 ddi_driver_name(dip
), ddi_get_instance(dip
));
2293 return (DDI_SUCCESS
);
2295 case DDI_CTLOPS_REGSIZE
:
2296 if ((lcip
= ddi_get_parent_data(rdip
)) == NULL
)
2297 return (DDI_FAILURE
);
2298 if ((rnum
= *(uint_t
*)arg
) >= lcip
->nregs
)
2299 return (DDI_FAILURE
);
2300 *(off_t
*)result
= lcip
->rsp
[rnum
].lombus_size
;
2301 return (DDI_SUCCESS
);
2303 case DDI_CTLOPS_NREGS
:
2304 if ((lcip
= ddi_get_parent_data(rdip
)) == NULL
)
2305 return (DDI_FAILURE
);
2306 *(int *)result
= lcip
->nregs
;
2307 return (DDI_SUCCESS
);
2310 return (ddi_ctlops(dip
, rdip
, op
, arg
, result
));
2315 * This nexus does not support passing interrupts to leaf drivers, so
2316 * all the intrspec-related operations just fail as cleanly as possible.
2321 bscbus_intr_op(dev_info_t
*dip
, dev_info_t
*rdip
, ddi_intr_op_t op
,
2322 ddi_intr_handle_impl_t
*hdlp
, void *result
)
2324 #if defined(__sparc)
2325 return (i_ddi_intr_ops(dip
, rdip
, op
, hdlp
, result
));
2327 _NOTE(ARGUNUSED(dip
, rdip
, op
, hdlp
, result
))
2328 return (DDI_FAILURE
);
2333 * Clean up on detach or failure of attach
2336 bscbus_unattach(struct bscbus_state
*ssp
, int instance
)
2341 for (chno
= 0; chno
< BSCBUS_MAX_CHANNELS
; chno
++) {
2342 ASSERT(ssp
->channel
[chno
].map_count
== 0);
2344 bscbus_offline(ssp
);
2345 ddi_set_driver_private(ssp
->dip
, NULL
);
2346 mutex_destroy(ssp
->ch_mutex
);
2348 #ifdef BSCBUS_LOGSTATUS
2349 if (ssp
->cmd_log_size
!= 0) {
2350 kmem_free(ssp
->cmd_log
,
2351 ssp
->cmd_log_size
* sizeof (bsc_cmd_log_t
));
2353 #endif /* BSCBUS_LOGSTATUS */
2356 ddi_soft_state_free(bscbus_statep
, instance
);
2357 return (DDI_FAILURE
);
2361 * Autoconfiguration routines
2365 bscbus_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
2367 struct bscbus_state
*ssp
= NULL
;
2374 return (DDI_FAILURE
);
2381 * Allocate the soft-state structure
2383 instance
= ddi_get_instance(dip
);
2384 if (ddi_soft_state_zalloc(bscbus_statep
, instance
) != DDI_SUCCESS
)
2385 return (DDI_FAILURE
);
2386 if ((ssp
= bscbus_getstate(dip
, instance
, "bscbus_attach")) == NULL
)
2387 return (bscbus_unattach(ssp
, instance
));
2388 ddi_set_driver_private(dip
, ssp
);
2391 * Initialise devinfo-related fields
2394 ssp
->majornum
= ddi_driver_major(dip
);
2395 ssp
->instance
= instance
;
2398 * Set various options from .conf properties
2400 ssp
->debug
= ddi_prop_get_int(DDI_DEV_T_ANY
, dip
,
2401 DDI_PROP_DONTPASS
, "debug", 0);
2403 mutex_init(ssp
->ch_mutex
, NULL
, MUTEX_DRIVER
, NULL
);
2405 #ifdef BSCBUS_LOGSTATUS
2406 ssp
->cmd_log_size
= bscbus_cmd_log_size
;
2407 if (ssp
->cmd_log_size
!= 0) {
2408 ssp
->cmd_log_idx
= 0;
2409 ssp
->cmd_log
= kmem_zalloc(ssp
->cmd_log_size
*
2410 sizeof (bsc_cmd_log_t
), KM_SLEEP
);
2412 #endif /* BSCBUS_LOGSTATUS */
2415 * Online the hardware ...
2417 err
= bscbus_online(ssp
);
2419 return (bscbus_unattach(ssp
, instance
));
2421 for (chno
= 0; chno
< BSCBUS_MAX_CHANNELS
; chno
++) {
2422 struct bscbus_channel_state
*csp
= &ssp
->channel
[chno
];
2426 * The hardware/interrupts are setup at map time to
2427 * avoid claiming hardware that OBP is using
2432 csp
->map_dog
= B_FALSE
;
2436 * All done, report success
2438 ddi_report_dev(dip
);
2439 return (DDI_SUCCESS
);
2443 bscbus_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
2445 struct bscbus_state
*ssp
;
2450 return (DDI_FAILURE
);
2456 instance
= ddi_get_instance(dip
);
2457 if ((ssp
= bscbus_getstate(dip
, instance
, "bscbus_detach")) == NULL
)
2458 return (DDI_FAILURE
); /* this "can't happen" */
2460 (void) bscbus_unattach(ssp
, instance
);
2461 return (DDI_SUCCESS
);
2465 bscbus_reset(dev_info_t
*dip
, ddi_reset_cmd_t cmd
)
2467 struct bscbus_state
*ssp
;
2470 _NOTE(ARGUNUSED(cmd
))
2472 if ((ssp
= bscbus_getstate(dip
, -1, "bscbus_reset")) == NULL
)
2473 return (DDI_FAILURE
);
2475 for (chno
= 0; chno
< BSCBUS_MAX_CHANNELS
; chno
++) {
2476 bscbus_hw_reset(&ssp
->channel
[chno
]);
2478 return (DDI_SUCCESS
);
2483 * System interface structures
2486 static struct cb_ops bscbus_cb_ops
=
2488 nodev
, /* b/c open */
2489 nodev
, /* b/c close */
2490 nodev
, /* b strategy */
2491 nodev
, /* b print */
2494 nodev
, /* c write */
2495 nodev
, /* c ioctl */
2496 nodev
, /* c devmap */
2498 nodev
, /* c segmap */
2499 nochpoll
, /* c poll */
2500 ddi_prop_op
, /* b/c prop_op */
2501 NULL
, /* c streamtab */
2502 D_MP
| D_NEW
/* b/c flags */
2505 static struct bus_ops bscbus_bus_ops
=
2507 BUSO_REV
, /* revision */
2508 bscbus_map
, /* bus_map */
2509 0, /* get_intrspec */
2510 0, /* add_intrspec */
2511 0, /* remove_intrspec */
2512 i_ddi_map_fault
, /* map_fault */
2513 ddi_no_dma_map
, /* dma_map */
2514 ddi_no_dma_allochdl
, /* allocate DMA handle */
2515 ddi_no_dma_freehdl
, /* free DMA handle */
2516 ddi_no_dma_bindhdl
, /* bind DMA handle */
2517 ddi_no_dma_unbindhdl
, /* unbind DMA handle */
2518 ddi_no_dma_flush
, /* flush DMA */
2519 ddi_no_dma_win
, /* move DMA window */
2520 ddi_no_dma_mctl
, /* generic DMA control */
2521 bscbus_ctlops
, /* generic control */
2522 ddi_bus_prop_op
, /* prop_op */
2523 ndi_busop_get_eventcookie
, /* get_eventcookie */
2524 ndi_busop_add_eventcall
, /* add_eventcall */
2525 ndi_busop_remove_eventcall
, /* remove_eventcall */
2526 ndi_post_event
, /* post_event */
2527 0, /* interrupt control */
2529 0, /* bus_unconfig */
2530 0, /* bus_fm_init */
2531 0, /* bus_fm_fini */
2532 0, /* bus_fm_access_enter */
2533 0, /* bus_fm_access_exit */
2535 bscbus_intr_op
/* bus_intr_op */
2538 static struct dev_ops bscbus_dev_ops
=
2542 ddi_no_info
, /* getinfo */
2543 nulldev
, /* identify */
2544 nulldev
, /* probe */
2545 bscbus_attach
, /* attach */
2546 bscbus_detach
, /* detach */
2547 bscbus_reset
, /* reset */
2548 &bscbus_cb_ops
, /* driver operations */
2549 &bscbus_bus_ops
, /* bus operations */
2551 ddi_quiesce_not_needed
, /* quiesce */
2554 static struct modldrv modldrv
=
2561 static struct modlinkage modlinkage
=
2572 * Dynamic loader interface code
2580 err
= ddi_soft_state_init(&bscbus_statep
,
2581 sizeof (struct bscbus_state
), 0);
2582 if (err
== DDI_SUCCESS
)
2583 if ((err
= mod_install(&modlinkage
)) != DDI_SUCCESS
) {
2584 ddi_soft_state_fini(&bscbus_statep
);
2591 _info(struct modinfo
*mip
)
2593 return (mod_info(&modlinkage
, mip
));
2601 if ((err
= mod_remove(&modlinkage
)) == DDI_SUCCESS
) {
2602 ddi_soft_state_fini(&bscbus_statep
);
2603 bscbus_major
= NOMAJOR
;
2609 #ifdef BSCBUS_LOGSTATUS
2610 void bscbus_cmd_log(struct bscbus_channel_state
*csp
, bsc_cmd_stamp_t cat
,
2611 uint8_t status
, uint8_t data
)
2614 bsc_cmd_log_t
*logp
;
2615 struct bscbus_state
*ssp
;
2619 if ((ssp
= (csp
)->ssp
) == NULL
)
2621 if (ssp
->cmd_log_size
== 0)
2623 if ((bscbus_cmd_log_flags
& (1 << cat
)) == 0)
2625 idx
= atomic_add_32_nv(&ssp
->cmd_log_idx
, 1);
2626 logp
= &ssp
->cmd_log
[idx
% ssp
->cmd_log_size
];
2627 logp
->bcl_seq
= idx
;
2628 logp
->bcl_cat
= cat
;
2629 logp
->bcl_now
= gethrtime();
2630 logp
->bcl_chno
= csp
->chno
;
2631 logp
->bcl_cmdstate
= csp
->cmdstate
;
2632 logp
->bcl_status
= status
;
2633 logp
->bcl_data
= data
;
2635 #endif /* BSCBUS_LOGSTATUS */