#include <sys/sysmacros.h>
#include <sys/async.h>
#include <sys/sunddi.h>
#include <sys/ddi_impldefs.h>
#include <sys/disp.h>
#include <sys/archsystm.h>
#include "px_obj.h"
#ifdef DEBUG
uint64_t px_debug_flags = 0;
static char *px_debug_sym [] = {
"attach",
"detach",
"map",
"nex-ctlops",
"introps",
"intx-add",
"intx-rem",
"intx-intr",
"msiq",
"msiq-intr",
"msg",
"msg-intr",
"msix-add",
"msix-rem",
"msix-intr",
"err",
"dma-alloc",
"dma-free",
"dma-bind",
"dma-unbind",
"chk-dma-mode",
"bypass-dma",
"fast-dvma",
"init_child",
"dma-map",
"dma-win",
"map-win",
"unmap-win",
"dma-ctl",
"dma-sync",
NULL,
NULL,
"ib",
"cb",
"dmc",
"pec",
"ilu",
"tlu",
"lpu",
"mmu",
"open",
"close",
"ioctl",
"pwr",
"lib-cfg",
"lib-intr",
"lib-dma",
"lib-msiq",
"lib-msi",
"lib-msg",
"NULL",
"NULL",
"tools",
"phys_acc",
"hotplug",
"unknown"
};
static int px_dbg_msg_size = 16;
static int px_dbg_qmask = 0xFFFF;
static px_dbg_msg_t *px_dbg_msgq = NULL;
static uint8_t px_dbg_reference = 0;
static kmutex_t px_dbg_mutex;
static uint8_t px_dbg_qtail = 0;
static uint8_t px_dbg_qhead = 0;
static uint_t px_dbg_qsize = 0;
static uint_t px_dbg_failed = 0;
static void px_dbg_print(px_debug_bit_t bit, dev_info_t *dip, char *fmt,
va_list args);
static void px_dbg_queue(px_debug_bit_t bit, dev_info_t *dip, char *fmt,
va_list args);
static uint_t px_dbg_drain(caddr_t arg1, caddr_t arg2);
static void
px_dbg_print(px_debug_bit_t bit, dev_info_t *dip, char *fmt, va_list args)
{
int cont = bit >> DBG_BITS;
if (cont)
goto body;
if (dip)
prom_printf("%s(%d): %s: ", ddi_driver_name(dip),
ddi_get_instance(dip), px_debug_sym[bit]);
else
prom_printf("px: %s: ", px_debug_sym[bit]);
body:
if (args)
prom_vprintf(fmt, args);
else
prom_printf(fmt);
}
static void
px_dbg_queue(px_debug_bit_t bit, dev_info_t *dip, char *fmt, va_list args)
{
int instance = DIP_TO_INST(dip);
px_t *px_p = INST_TO_STATE(instance);
uint8_t q_no;
px_dbg_msg_t *msg_p;
if (atomic_inc_uint_nv(&px_dbg_qsize) >= px_dbg_msg_size) {
px_dbg_failed++;
atomic_dec_uint(&px_dbg_qsize);
return;
}
q_no = ++px_dbg_qtail & px_dbg_qmask;
msg_p = &px_dbg_msgq[q_no];
ASSERT(msg_p->active == B_FALSE);
vsnprintf(msg_p->msg, DBG_MSG_SIZE, fmt, args);
msg_p->bit = bit;
msg_p->dip = dip;
msg_p->active = B_TRUE;
ddi_intr_trigger_softint(px_p->px_dbg_hdl, (caddr_t)NULL);
}
static uint_t
px_dbg_drain(caddr_t arg1, caddr_t arg2) {
uint8_t q_no;
px_dbg_msg_t *msg_p;
uint_t ret = DDI_INTR_UNCLAIMED;
mutex_enter(&px_dbg_mutex);
while (px_dbg_qsize) {
atomic_dec_uint(&px_dbg_qsize);
if (px_dbg_failed) {
cmn_err(CE_WARN, "%d msg(s) were lost",
px_dbg_failed);
px_dbg_failed = 0;
}
q_no = ++px_dbg_qhead & px_dbg_qmask;
msg_p = &px_dbg_msgq[q_no];
if (msg_p->active) {
px_dbg_print(msg_p->bit, msg_p->dip, msg_p->msg, NULL);
msg_p->active = B_FALSE;
}
ret = DDI_INTR_CLAIMED;
}
mutex_exit(&px_dbg_mutex);
return (ret);
}
void
px_dbg(px_debug_bit_t bit, dev_info_t *dip, char *fmt, ...)
{
va_list ap;
bit &= DBG_MASK;
if (bit >= sizeof (px_debug_sym) / sizeof (char *))
return;
if (!(1ull << bit & px_debug_flags))
return;
va_start(ap, fmt);
if (getpil() > LOCK_LEVEL)
px_dbg_queue(bit, dip, fmt, ap);
else
px_dbg_print(bit, dip, fmt, ap);
va_end(ap);
}
#endif
void
px_dbg_attach(dev_info_t *dip, ddi_softint_handle_t *dbg_hdl)
{
#ifdef DEBUG
if (px_dbg_reference++ == 0) {
int size = px_dbg_msg_size;
size = !ISP2(size) ? ((size | ~size) + 1) : size;
px_dbg_msg_size = size;
px_dbg_qmask = size - 1;
px_dbg_msgq = kmem_zalloc(sizeof (px_dbg_msg_t) * size,
KM_SLEEP);
mutex_init(&px_dbg_mutex, NULL, MUTEX_DRIVER, NULL);
}
if (ddi_intr_add_softint(dip, dbg_hdl,
DDI_INTR_SOFTPRI_MAX, px_dbg_drain, NULL) != DDI_SUCCESS) {
DBG(DBG_ATTACH, dip,
"Unable to allocate soft int for DBG printing.\n");
dbg_hdl = NULL;
}
#endif
}
void
px_dbg_detach(dev_info_t *dip, ddi_softint_handle_t *dbg_hdl)
{
#ifdef DEBUG
if (dbg_hdl != NULL)
(void) ddi_intr_remove_softint(*dbg_hdl);
if (--px_dbg_reference == 0) {
if (px_dbg_msgq != NULL)
kmem_free(px_dbg_msgq,
sizeof (px_dbg_msg_t) * px_dbg_msg_size);
mutex_destroy(&px_dbg_mutex);
}
#endif
}