summaryrefslogtreecommitdiff
path: root/usr
diff options
context:
space:
mode:
authorjm22469 <none@none>2008-02-05 09:01:19 -0800
committerjm22469 <none@none>2008-02-05 09:01:19 -0800
commit1b83305cfc332b1e19ad6a194b73b2975e6bf79a (patch)
tree8bf803a14d9bbf1f261d97e19a1c18b8102f6973 /usr
parent0280efdc4e507211851281715883a4b68445f267 (diff)
downloadillumos-gate-1b83305cfc332b1e19ad6a194b73b2975e6bf79a.tar.gz
6581309 inconsistent console behavior when not using the virtual console
6635697 qcn driver should support a polled io mode
Diffstat (limited to 'usr')
-rw-r--r--usr/src/uts/common/io/consconfig_dacf.c139
-rw-r--r--usr/src/uts/common/os/main.c3
-rw-r--r--usr/src/uts/common/sys/consconfig_dacf.h6
-rw-r--r--usr/src/uts/sparc/io/consplat.c28
-rw-r--r--usr/src/uts/sun/sys/bootconf.h3
-rw-r--r--usr/src/uts/sun4/os/startup.c10
-rw-r--r--usr/src/uts/sun4v/io/qcn.c116
-rw-r--r--usr/src/uts/sun4v/os/mach_cpu_states.c35
-rw-r--r--usr/src/uts/sun4v/promif/promif_io.c163
-rw-r--r--usr/src/uts/sun4v/promif/promif_mon.c137
-rw-r--r--usr/src/uts/sun4v/sys/promif_impl.h3
-rw-r--r--usr/src/uts/sun4v/sys/qcn.h10
12 files changed, 470 insertions, 183 deletions
diff --git a/usr/src/uts/common/io/consconfig_dacf.c b/usr/src/uts/common/io/consconfig_dacf.c
index 99a43972de..96ed16e8f4 100644
--- a/usr/src/uts/common/io/consconfig_dacf.c
+++ b/usr/src/uts/common/io/consconfig_dacf.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -477,6 +477,51 @@ consconfig_kbd_abort_disable(ldi_handle_t lh)
return (err);
}
+#ifdef _HAVE_TEM_FIRMWARE
+static int
+consconfig_tem_supported(cons_state_t *sp)
+{
+ dev_t dev;
+ dev_info_t *dip;
+ int *int_array;
+ uint_t nint;
+ int rv = 0;
+
+ if ((dev = ddi_pathname_to_dev_t(sp->cons_fb_path)) == NODEV)
+ return (0); /* warning printed later by common code */
+
+ /*
+ * Here we hold the driver and check "tem-support" property.
+ * We're doing this with e_ddi_hold_devi_by_dev and
+ * ddi_prop_lookup_int_array without opening the driver since
+ * some video cards that don't support the kernel terminal
+ * emulator could hang or crash if opened too early during
+ * boot.
+ */
+ if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) {
+ cmn_err(CE_WARN, "consconfig: cannot hold fb dev %s",
+ sp->cons_fb_path);
+ return (0);
+ }
+
+ /*
+ * Check that the tem-support property exists AND that
+ * it is equal to 1.
+ */
+ if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
+ DDI_PROP_DONTPASS, "tem-support", &int_array, &nint) ==
+ DDI_SUCCESS) {
+ if (nint > 0)
+ rv = int_array[0] == 1;
+ ddi_prop_free(int_array);
+ }
+
+ ddi_release_devi(dip);
+
+ return (rv);
+}
+#endif /* _HAVE_TEM_FIRMWARE */
+
/*
* consconfig_get_polledio:
* Query the console with the CONSPOLLEDIO ioctl.
@@ -619,13 +664,11 @@ consconfig_state_init(void)
/* Identify the stdout driver */
sp->cons_stdout_path = plat_stdoutpath();
- if (plat_stdout_is_framebuffer()) {
- sp->cons_fb_path = sp->cons_stdout_path;
- } else {
- sp->cons_fb_path = plat_fbpath();
- }
+ sp->cons_stdout_is_fb = plat_stdout_is_framebuffer();
- if (plat_stdin_is_keyboard() &&
+ sp->cons_stdin_is_kbd = plat_stdin_is_keyboard();
+
+ if (sp->cons_stdin_is_kbd &&
(usb_kb_path != NULL || consconfig_usb_kb_path != NULL)) {
sp->cons_stdin_path = sp->cons_keyboard_path;
} else {
@@ -639,6 +682,39 @@ consconfig_state_init(void)
sp->cons_stdin_path = plat_stdinpath();
}
+ if (sp->cons_stdout_is_fb) {
+ sp->cons_fb_path = sp->cons_stdout_path;
+
+#ifdef _HAVE_TEM_FIRMWARE
+ sp->cons_tem_supported = consconfig_tem_supported(sp);
+
+ /*
+ * Systems which offer a virtual console must use that
+ * as a fallback whenever the fb doesn't support tem.
+ * Such systems cannot render characters to the screen
+ * using OBP.
+ */
+ if (!sp->cons_tem_supported) {
+ char *path;
+
+ if (plat_virtual_console_path(&path) >= 0) {
+ sp->cons_stdin_is_kbd = 0;
+ sp->cons_stdout_is_fb = 0;
+ sp->cons_stdin_path = path;
+ sp->cons_stdout_path = path;
+ sp->cons_fb_path = plat_fbpath();
+
+ cmn_err(CE_WARN,
+ "%s doesn't support terminal emulation "
+ "mode; switching to virtual console.",
+ sp->cons_fb_path);
+ }
+ }
+#endif /* _HAVE_TEM_FIRMWARE */
+ } else {
+ sp->cons_fb_path = plat_fbpath();
+ }
+
sp->cons_li = ldi_ident_from_anon();
/* Save the pointer for retrieval by the dacf functions */
@@ -713,14 +789,8 @@ cons_build_upper_layer(cons_state_t *sp)
ldi_handle_t wc_lh;
struct strioctl strioc;
int rval;
- dev_t wc_dev;
dev_t dev;
-#ifdef _HAVE_TEM_FIRMWARE
- dev_info_t *dip;
- int *int_array;
- uint_t nint;
- boolean_t kfb_mode;
-#endif /* _HAVE_TEM_FIRMWARE */
+ dev_t wc_dev;
/*
* Build the wc->conskbd portion of the keyboard console stream.
@@ -802,7 +872,7 @@ cons_build_upper_layer(cons_state_t *sp)
if (sp->cons_fb_path == NULL) {
#if defined(__x86)
- if (plat_stdout_is_framebuffer())
+ if (sp->cons_stdout_is_fb)
cmn_err(CE_WARN, "consconfig: no screen found");
#endif
return;
@@ -819,33 +889,11 @@ cons_build_upper_layer(cons_state_t *sp)
#ifdef _HAVE_TEM_FIRMWARE
/*
- * Here we hold the driver and check "tem-support" property.
- * We're doing this with e_ddi_hold_devi_by_dev and
- * ddi_prop_lookup_int_array before opening the driver since
- * some video cards that don't support the kernel terminal
- * emulator could hang or crash if opened too early during
- * boot.
- */
- if ((dip = e_ddi_hold_devi_by_dev(dev, 0)) == NULL) {
- cmn_err(CE_WARN, "consconfig: cannot hold fb dev %s",
- sp->cons_fb_path);
- return;
- }
-
- /*
- * Check the existance of the tem-support property AND that
- * it be equal to 1.
+ * If the underlying fb device doesn't support terminal emulation,
+ * we don't want to open the wc device (below) because it depends
+ * on features which aren't available (polled mode io).
*/
- kfb_mode = B_FALSE;
- if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip,
- DDI_PROP_DONTPASS, "tem-support", &int_array, &nint) ==
- DDI_SUCCESS) {
- if (nint > 0)
- kfb_mode = int_array[0] == 1;
- ddi_prop_free(int_array);
- }
- ddi_release_devi(dip);
- if (!kfb_mode)
+ if (!sp->cons_tem_supported)
return;
#endif /* _HAVE_TEM_FIRMWARE */
@@ -920,7 +968,7 @@ consconfig_load_drivers(cons_state_t *sp)
static void
consconfig_init_framebuffer(cons_state_t *sp)
{
- if (!plat_stdout_is_framebuffer())
+ if (!sp->cons_stdout_is_fb)
return;
DPRINTF(DPRINT_L0, "stdout is framebuffer\n");
@@ -1151,14 +1199,15 @@ consconfig_relink_consms(cons_state_t *sp, ldi_handle_t new_lh, int *muxid)
}
static int
-cons_get_input_type(void)
+cons_get_input_type(cons_state_t *sp)
{
int type;
+
/*
* Now that we know what all the devices are, we can figure out
* what kind of console we have.
*/
- if (plat_stdin_is_keyboard()) {
+ if (sp->cons_stdin_is_kbd) {
/* Stdin is from the system keyboard */
type = CONSOLE_LOCAL;
} else if ((stdindev != NODEV) && (stdindev == stdoutdev)) {
@@ -1396,7 +1445,7 @@ dynamic_console_config(void)
* streams if the pathnames are valid.
*/
consconfig_load_drivers(consconfig_sp);
- consconfig_sp->cons_input_type = cons_get_input_type();
+ consconfig_sp->cons_input_type = cons_get_input_type(consconfig_sp);
/*
* This is legacy special case code for the "cool" virtual console
diff --git a/usr/src/uts/common/os/main.c b/usr/src/uts/common/os/main.c
index 7109a49cda..561534f68e 100644
--- a/usr/src/uts/common/os/main.c
+++ b/usr/src/uts/common/os/main.c
@@ -474,9 +474,8 @@ main(void)
* and swap have been set up.
*/
consconfig();
-#if defined(__i386) || defined(__amd64)
release_bootstrap();
-#endif
+
/*
* attach drivers with ddi-forceattach prop
* This must be done after consconfig() to prevent usb key/mouse
diff --git a/usr/src/uts/common/sys/consconfig_dacf.h b/usr/src/uts/common/sys/consconfig_dacf.h
index 99b06288b0..446cd10cdf 100644
--- a/usr/src/uts/common/sys/consconfig_dacf.h
+++ b/usr/src/uts/common/sys/consconfig_dacf.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -75,6 +75,9 @@ typedef struct cons_state {
kmutex_t cons_lock;
cons_prop_t *cons_km_prop;
+ int cons_tem_supported;
+ int cons_stdin_is_kbd;
+ int cons_stdout_is_fb;
} cons_state_t;
/*
@@ -123,6 +126,7 @@ extern char *plat_kbdpath(void);
extern char *plat_mousepath(void);
extern int plat_stdout_is_framebuffer(void);
extern int plat_stdin_is_keyboard(void);
+extern int plat_virtual_console_path(char **);
extern void plat_tem_get_inverses(int *, int *);
extern void plat_tem_get_prom_font_size(int *, int *);
diff --git a/usr/src/uts/sparc/io/consplat.c b/usr/src/uts/sparc/io/consplat.c
index 5c4bf29453..6ca09e0b3a 100644
--- a/usr/src/uts/sparc/io/consplat.c
+++ b/usr/src/uts/sparc/io/consplat.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -243,3 +243,29 @@ plat_tem_get_prom_pos(uint32_t *row, uint32_t *col)
{
prom_get_tem_pos(row, col);
}
+
+/*
+ * Find the path of the virtual console (if available on the
+ * current architecture).
+ *
+ * Returns: -1 if not found, else actual path length.
+ */
+int
+plat_virtual_console_path(char **bufp)
+{
+ pnode_t pnode;
+ int buflen;
+ static char buf[OBP_MAXPATHLEN];
+
+ pnode = prom_finddevice("/virtual-devices/console");
+
+ if (pnode == OBP_BADNODE)
+ return (-1);
+
+ if ((buflen = prom_phandle_to_path(pnode, buf, sizeof (buf))) < 0)
+ return (-1);
+
+ *bufp = buf;
+
+ return (buflen);
+}
diff --git a/usr/src/uts/sun/sys/bootconf.h b/usr/src/uts/sun/sys/bootconf.h
index 814b84ef61..3e93efd063 100644
--- a/usr/src/uts/sun/sys/bootconf.h
+++ b/usr/src/uts/sun/sys/bootconf.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -208,6 +208,7 @@ extern int strplumb(void);
extern int strplumb_load(void);
extern void consconfig(void);
+extern void release_bootstrap(void);
extern int dhcpinit(void);
diff --git a/usr/src/uts/sun4/os/startup.c b/usr/src/uts/sun4/os/startup.c
index d142820fc1..68c5f0b215 100644
--- a/usr/src/uts/sun4/os/startup.c
+++ b/usr/src/uts/sun4/os/startup.c
@@ -2130,9 +2130,6 @@ post_startup(void)
#ifdef PTL1_PANIC_DEBUG
init_ptl1_thread();
#endif /* PTL1_PANIC_DEBUG */
-
- if (&cif_init)
- cif_init();
}
#ifdef PTL1_PANIC_DEBUG
@@ -3138,3 +3135,10 @@ kobj_texthole_free(caddr_t addr, size_t size)
ASSERT(texthole_arena[arena] != NULL);
vmem_free(texthole_arena[arena], addr, size);
}
+
+void
+release_bootstrap(void)
+{
+ if (&cif_init)
+ cif_init();
+}
diff --git a/usr/src/uts/sun4v/io/qcn.c b/usr/src/uts/sun4v/io/qcn.c
index fc995fe154..6d9e45bbc6 100644
--- a/usr/src/uts/sun4v/io/qcn.c
+++ b/usr/src/uts/sun4v/io/qcn.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,6 +51,7 @@
#include <sys/hypervisor_api.h>
#include <sys/hsvc.h>
#include <sys/machsystm.h>
+#include <sys/consdev.h>
/* dev_ops and cb_ops for device driver */
static int qcn_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
@@ -75,6 +76,14 @@ static void qcn_flush(void);
static uint_t qcn_hi_intr(caddr_t arg);
static uint_t qcn_soft_intr(caddr_t arg1, caddr_t arg2);
+/* functions required for polled io */
+static boolean_t qcn_polledio_ischar(cons_polledio_arg_t arg);
+static int qcn_polledio_getchar(cons_polledio_arg_t arg);
+static void qcn_polledio_putchar(cons_polledio_arg_t arg, uchar_t c);
+static void qcn_polledio_enter(cons_polledio_arg_t arg);
+static void qcn_polledio_exit(cons_polledio_arg_t arg);
+
+
static boolean_t abort_charseq_recognize(uchar_t);
static qcn_t *qcn_state;
@@ -414,6 +423,18 @@ qcn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
mutex_init(&qcn_state->qcn_lock, NULL, MUTEX_DRIVER, NULL);
/*
+ * Fill in the polled I/O structure.
+ */
+ qcn_state->qcn_polledio.cons_polledio_version = CONSPOLLEDIO_V1;
+ qcn_state->qcn_polledio.cons_polledio_argument =
+ (cons_polledio_arg_t)qcn_state;
+ qcn_state->qcn_polledio.cons_polledio_putchar = qcn_polledio_putchar;
+ qcn_state->qcn_polledio.cons_polledio_getchar = qcn_polledio_getchar;
+ qcn_state->qcn_polledio.cons_polledio_ischar = qcn_polledio_ischar;
+ qcn_state->qcn_polledio.cons_polledio_enter = qcn_polledio_enter;
+ qcn_state->qcn_polledio.cons_polledio_exit = qcn_polledio_exit;
+
+ /*
* Enable interrupts
*/
if (!qcn_state->qcn_polling) {
@@ -682,20 +703,47 @@ qcn_ioctl(queue_t *q, mblk_t *mp)
#endif
iocp = (struct iocblk *)mp->b_rptr;
+
tty = &(qcn_state->qcn_tty);
if (tty->t_iocpending != NULL) {
freemsg(tty->t_iocpending);
tty->t_iocpending = NULL;
}
- data_size = ttycommon_ioctl(tty, q, mp, &error);
- if (data_size != 0) {
- if (qcn_state->qcn_wbufcid)
- unbufcall(qcn_state->qcn_wbufcid);
- /* call qcn_reioctl() */
- qcn_state->qcn_wbufcid =
- bufcall(data_size, BPRI_HI, qcn_reioctl, qcn_state);
- return;
+
+ /*
+ * Handle the POLLEDIO ioctls now because ttycommon_ioctl
+ * (below) frees up the message block (mp->b_cont) which
+ * contains the pointer used to pass back results.
+ */
+ switch (iocp->ioc_cmd) {
+ case CONSOPENPOLLEDIO:
+ error = miocpullup(mp, sizeof (struct cons_polledio *));
+ if (error != 0)
+ break;
+
+ *(struct cons_polledio **)mp->b_cont->b_rptr =
+ &qcn_state->qcn_polledio;
+
+ mp->b_datap->db_type = M_IOCACK;
+ break;
+
+ case CONSCLOSEPOLLEDIO:
+ mp->b_datap->db_type = M_IOCACK;
+ iocp->ioc_error = 0;
+ iocp->ioc_rval = 0;
+ break;
+
+ default:
+ data_size = ttycommon_ioctl(tty, q, mp, &error);
+ if (data_size != 0) {
+ if (qcn_state->qcn_wbufcid)
+ unbufcall(qcn_state->qcn_wbufcid);
+ /* call qcn_reioctl() */
+ qcn_state->qcn_wbufcid =
+ bufcall(data_size, BPRI_HI, qcn_reioctl, qcn_state);
+ return;
+ }
}
mutex_enter(&qcn_state->qcn_lock);
@@ -1263,3 +1311,53 @@ qcn_wsrv(queue_t *q)
return (0);
}
+
+static boolean_t
+qcn_polledio_ischar(cons_polledio_arg_t arg)
+{
+ qcn_t *state = (qcn_t *)arg;
+
+ if (state->qcn_char_available)
+ return (B_TRUE);
+
+ return (state->qcn_char_available =
+ (hv_cngetchar(&state->qcn_hold_char) == H_EOK));
+}
+
+
+static int
+qcn_polledio_getchar(cons_polledio_arg_t arg)
+{
+ qcn_t *state = (qcn_t *)arg;
+
+ while (!qcn_polledio_ischar(arg))
+ drv_usecwait(10);
+
+ state->qcn_char_available = B_FALSE;
+
+ return ((int)state->qcn_hold_char);
+}
+
+static void
+qcn_polledio_putchar(cons_polledio_arg_t arg, uchar_t c)
+{
+ if (c == '\n')
+ qcn_polledio_putchar(arg, '\r');
+
+ while (hv_cnputchar((uint8_t)c) == H_EWOULDBLOCK)
+ drv_usecwait(10);
+}
+
+static void
+qcn_polledio_enter(cons_polledio_arg_t arg)
+{
+ qcn_t *state = (qcn_t *)arg;
+
+ state->qcn_char_available = B_FALSE;
+}
+
+/* ARGSUSED */
+static void
+qcn_polledio_exit(cons_polledio_arg_t arg)
+{
+}
diff --git a/usr/src/uts/sun4v/os/mach_cpu_states.c b/usr/src/uts/sun4v/os/mach_cpu_states.c
index 120bebb599..cddd003c00 100644
--- a/usr/src/uts/sun4v/os/mach_cpu_states.c
+++ b/usr/src/uts/sun4v/os/mach_cpu_states.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -106,19 +106,21 @@ extern uint64_t get_cpuaddr(uint64_t, uint64_t);
* the next boot.
*/
static void
-store_boot_cmd(char *args)
+store_boot_cmd(char *args, boolean_t add_boot_str)
{
static char cmd_buf[BOOT_CMD_MAX_LEN];
- size_t len;
+ size_t len = 1;
pnode_t node;
- size_t base_len;
+ size_t base_len = 0;
size_t args_len;
size_t args_max;
- (void) strcpy(cmd_buf, BOOT_CMD_BASE);
+ if (add_boot_str) {
+ (void) strcpy(cmd_buf, BOOT_CMD_BASE);
- base_len = strlen(BOOT_CMD_BASE);
- len = base_len + 1;
+ base_len = strlen(BOOT_CMD_BASE);
+ len = base_len + 1;
+ }
if (args != NULL) {
args_len = strlen(args);
@@ -170,8 +172,20 @@ mdboot(int cmd, int fcn, char *bootstr, boolean_t invoke_cb)
switch (fcn) {
case AD_HALT:
+ /*
+ * LDoms: By storing a no-op command
+ * in the 'reboot-command' variable we cause OBP
+ * to ignore the setting of 'auto-boot?' after
+ * it completes the reset. This causes the system
+ * to stop at the ok prompt.
+ */
+ if (domaining_enabled() && invoke_cb)
+ store_boot_cmd("noop", B_FALSE);
+ break;
+
case AD_POWEROFF:
break;
+
default:
if (bootstr == NULL) {
switch (fcn) {
@@ -205,8 +219,7 @@ mdboot(int cmd, int fcn, char *bootstr, boolean_t invoke_cb)
* only if we are not being called from panic.
*/
if (domaining_enabled() && invoke_cb)
- store_boot_cmd(bootstr);
-
+ store_boot_cmd(bootstr, B_TRUE);
}
/*
@@ -307,7 +320,7 @@ panic_idle(void)
membar_stld();
for (;;)
- continue;
+ ;
}
/*
@@ -1045,7 +1058,7 @@ kdi_tickwait(clock_t nticks)
clock_t endtick = gettick() + nticks;
while (gettick() < endtick)
- continue;
+ ;
}
static void
diff --git a/usr/src/uts/sun4v/promif/promif_io.c b/usr/src/uts/sun4v/promif/promif_io.c
index c7a910f877..c9d237da02 100644
--- a/usr/src/uts/sun4v/promif/promif_io.c
+++ b/usr/src/uts/sun4v/promif/promif_io.c
@@ -29,10 +29,64 @@
#include <sys/promif_impl.h>
#include <sys/systm.h>
#include <sys/hypervisor_api.h>
+#include <sys/consdev.h>
#ifndef _KMDB
#include <sys/kmem.h>
#endif
+/*
+ * Definitions for using Polled I/O.
+ *
+ * The usage of Polled I/O is different when we are in kmdb. In that case,
+ * we can not directly invoke the polled I/O functions and we have to use
+ * the kmdb DPI interface. Also we don't need to enter/exit the polled I/O
+ * mode because this is already managed by kmdb when entering/exiting the
+ * debugger.
+ *
+ * When we are not in kmdb then we can directly call the polled I/O functions
+ * but we have to enter the polled I/O mode first. After using polled I/O
+ * functions we have to exit the polled I/O mode. Note that entering/exiting
+ * the polled I/O mode is time consuming so this should be avoided when
+ * possible.
+ */
+#ifdef _KMDB
+extern struct cons_polledio *kmdb_kdi_get_polled_io(void);
+extern uintptr_t kmdb_dpi_call(uintptr_t, uint_t, const uintptr_t *);
+
+#define PROMIF_PIO (kmdb_kdi_get_polled_io())
+
+#define PROMIF_PIO_CALL1(fn, arg) \
+ (kmdb_dpi_call((uintptr_t)fn, 1, (uintptr_t *)&arg))
+
+#define PROMIF_PIO_CALL2(fn, arg1, arg2) \
+ { \
+ uintptr_t args[2]; \
+ args[0] = (uintptr_t)arg1; \
+ args[1] = (uintptr_t)arg2; \
+ (void) (kmdb_dpi_call((uintptr_t)fn, 2, (uintptr_t *)args)); \
+ }
+
+#define PROMIF_PIO_ENTER(pio)
+#define PROMIF_PIO_EXIT(pio)
+
+#else /* _KMDB */
+
+#define PROMIF_PIO (cons_polledio)
+#define PROMIF_PIO_CALL1(fn, arg) (fn(arg))
+#define PROMIF_PIO_CALL2(fn, arg1, arg2) (fn(arg1, arg2))
+
+#define PROMIF_PIO_ENTER(pio) \
+ if (pio->cons_polledio_enter != NULL) { \
+ pio->cons_polledio_enter(pio->cons_polledio_argument); \
+ }
+
+#define PROMIF_PIO_EXIT(pio) \
+ if (pio->cons_polledio_exit != NULL) { \
+ pio->cons_polledio_exit(pio->cons_polledio_argument); \
+ }
+
+#endif /* _KMDB */
+
#define PROM_REG_TO_UNIT_ADDR(r) ((r) & ~(0xful << 28))
static pnode_t instance_to_package(ihandle_t ih);
@@ -44,6 +98,8 @@ static phandle_t pstdout;
static ihandle_t istdin;
static ihandle_t istdout;
+static struct cons_polledio *promif_polledio = NULL;
+
int
promif_instance_to_package(void *p)
{
@@ -60,6 +116,103 @@ promif_instance_to_package(void *p)
return (0);
}
+/* This function is not used but it is convenient for debugging I/O problems */
+static void
+/* LINTED */
+promif_hv_print(char *str)
+{
+ size_t i, len = strlen(str);
+
+ for (i = 0; i < len; i++) {
+ while (hv_cnputchar((uint8_t)str[i]) == H_EWOULDBLOCK)
+ /* try forever */;
+ }
+}
+
+static void
+promif_pio_enter(void)
+{
+ ASSERT(promif_polledio == NULL);
+
+ promif_polledio = PROMIF_PIO;
+ ASSERT(promif_polledio != NULL);
+
+ PROMIF_PIO_ENTER(promif_polledio);
+}
+
+static void
+promif_pio_exit(void)
+{
+ ASSERT(promif_polledio != NULL);
+
+ PROMIF_PIO_EXIT(promif_polledio);
+ promif_polledio = NULL;
+}
+
+static int
+promif_do_read(char *buf, size_t len, boolean_t wait)
+{
+ int rlen;
+ int (*getchar)(cons_polledio_arg_t);
+ boolean_t (*ischar)(cons_polledio_arg_t);
+ cons_polledio_arg_t arg;
+
+ promif_pio_enter();
+
+ if ((ischar = promif_polledio->cons_polledio_ischar) == NULL)
+ return (0);
+ if ((getchar = promif_polledio->cons_polledio_getchar) == NULL)
+ return (0);
+
+ arg = promif_polledio->cons_polledio_argument;
+
+ for (rlen = 0; rlen < len; ) {
+ if (PROMIF_PIO_CALL1(ischar, arg)) {
+ buf[rlen] = PROMIF_PIO_CALL1(getchar, arg);
+ rlen++;
+ continue;
+ }
+
+ if (!wait)
+ break;
+ }
+
+ promif_pio_exit();
+
+ return (rlen);
+}
+
+static int
+promif_do_write(char *buf, size_t len)
+{
+ int rlen;
+ void (*putchar)(cons_polledio_arg_t, uchar_t);
+ cons_polledio_arg_t arg;
+
+ promif_pio_enter();
+
+ if ((putchar = promif_polledio->cons_polledio_putchar) == NULL)
+ return (0);
+
+ arg = promif_polledio->cons_polledio_argument;
+
+ for (rlen = 0; rlen < len; rlen++)
+ PROMIF_PIO_CALL2(putchar, arg, buf[rlen]);
+
+ promif_pio_exit();
+
+ return (rlen);
+}
+
+char
+promif_getchar(void)
+{
+ char c;
+
+ (void) promif_do_read(&c, 1, B_TRUE);
+ return (c);
+}
+
int
promif_write(void *p)
{
@@ -78,10 +231,7 @@ promif_write(void *p)
/* only support stdout (console) */
ASSERT(fd == istdout);
- for (rlen = 0; rlen < len; rlen++) {
- while (hv_cnputchar((uint8_t)buf[rlen]) == H_EWOULDBLOCK)
- /* try forever */;
- }
+ rlen = promif_do_write(buf, len);
/* return the length written */
ci[6] = p1275_size2cell(rlen);
@@ -108,10 +258,7 @@ promif_read(void *p)
/* only support stdin (console) */
ASSERT(fd == istdin);
- for (rlen = 0; rlen < len; rlen++) {
- if (hv_cngetchar((uint8_t *)&buf[rlen]) != H_EOK)
- break;
- }
+ rlen = promif_do_read(buf, len, B_FALSE);
/* return the length read */
ci[6] = p1275_size2cell(rlen);
diff --git a/usr/src/uts/sun4v/promif/promif_mon.c b/usr/src/uts/sun4v/promif/promif_mon.c
index 9b9cda90e6..c13af78e8c 100644
--- a/usr/src/uts/sun4v/promif/promif_mon.c
+++ b/usr/src/uts/sun4v/promif/promif_mon.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -51,36 +51,15 @@ extern int vx_handler(cell_t *argument_array);
#endif
-#define PROMIF_ENTER 0
-#define PROMIF_EXIT 1
-
#define PROMIF_ISPRINT(c) (((c) >= ' ') && ((c) <= '~'))
-static void promif_mon(int mode);
-
-/*ARGSUSED*/
-int
-promif_enter_mon(void *p)
-{
- PIL_DECL(pil);
-
- PIL_SET7(pil);
-
- prom_printf("\n");
-
+static int promif_ask_before_reset =
#ifdef _KMDB
- promif_mon(PROMIF_ENTER);
+ 1;
#else
- idle_other_cpus();
- promif_mon(PROMIF_ENTER);
- resume_other_cpus();
+ 0;
#endif
- PIL_REST(pil);
-
- return (0);
-}
-
/*ARGSUSED*/
int
promif_exit_to_mon(void *p)
@@ -91,53 +70,43 @@ promif_exit_to_mon(void *p)
prom_printf("Program terminated\n");
- promif_mon(PROMIF_EXIT);
+ if (promif_ask_before_reset) {
+ prom_printf("Press any key to reboot.");
+ (void) prom_getchar();
+ }
+
+ (void) hv_mach_sir();
+
+ /* should not return */
+ ASSERT(0);
PIL_REST(pil);
return (0);
}
-static void
-promif_mon(int mode)
+/*ARGSUSED*/
+int
+promif_enter_mon(void *p)
{
char cmd;
- char *prompt;
- boolean_t invalid_option;
-#ifdef _KMDB
- static char *exit_prompt = "r)eboot, h)alt? ";
-#else
- char value[ 8 ]; /* holds "true" or "false" */
- char *boot_msg;
- static char *null_msg = ".\" \"";
- static char *ignore_msg =
- "cr .\" Ignoring auto-boot? setting for this boot.\" cr";
- static char *exit_prompt = "r)eboot, o)k prompt, h)alt? ";
-#endif
- static char *enter_prompt = "c)ontinue, s)ync, r)eboot, h)alt? ";
+ static char *prompt = "c)ontinue, s)ync, r)eset? ";
+ PIL_DECL(pil);
- prompt = (mode == PROMIF_EXIT) ? exit_prompt : enter_prompt;
+ PIL_SET7(pil);
+
+#ifndef _KMDB
+ idle_other_cpus();
+#endif
for (;;) {
prom_printf("%s", prompt);
-
- while (hv_cngetchar((uint8_t *)&cmd) != H_EOK)
- ;
-
+ cmd = promif_getchar();
prom_printf("%c\n", cmd);
- invalid_option = B_FALSE;
-
switch (cmd) {
case 'r':
- /*
- * Ideally, we would store the boot command string
- * as we do in promif_reboot(). However, at this
- * point the kernel is single-threaded and running
- * at a high PIL. This environment precludes
- * setting ldom variables.
- */
prom_printf("Resetting...\n");
(void) hv_mach_sir();
@@ -146,69 +115,37 @@ promif_mon(int mode)
ASSERT(0);
break;
- case 'h':
- (void) hv_mach_exit(0);
- ASSERT(0);
-
- break;
-
-#ifndef _KMDB
- case 'o':
- /*
- * This option gives the user an "ok" prompt after
- * the system reset regardless of the value of
- * auto-boot? We offer this option because halt(1m)
- * doesn't leave the user at the ok prompt (as it
- * does on non-ldoms systems). If auto-boot? is
- * true tell user we are overriding the setting
- * for this boot only.
- */
- if (mode == PROMIF_EXIT) {
- bzero(value, sizeof (value));
- (void) promif_stree_getprop(prom_optionsnode(),
- "auto-boot?", value);
- boot_msg = strcmp(value, "true") ? null_msg :
- ignore_msg;
- (void) promif_ldom_setprop("reboot-command",
- boot_msg, strlen(boot_msg) + 1);
- (void) hv_mach_sir();
- } else {
- invalid_option = B_TRUE;
- }
- break;
-#endif
-
case '\r':
break;
case 's':
- if (mode == PROMIF_ENTER) {
+ {
#ifdef _KMDB
kmdb_dpi_kernpanic(kmdb_dpi_get_master_cpuid());
#else
cell_t arg = p1275_ptr2cell("sync");
+
(void) vx_handler(&arg);
#endif
- } else {
- invalid_option = B_TRUE;
}
+
+ /* should not return */
+ ASSERT(0);
break;
case 'c':
- if (mode == PROMIF_ENTER) {
- return;
- } else {
- invalid_option = B_TRUE;
- }
- break;
+#ifndef _KMDB
+ resume_other_cpus();
+#endif
+ PIL_REST(pil);
+
+ return (0);
default:
- invalid_option = B_TRUE;
+ if (PROMIF_ISPRINT(cmd))
+ prom_printf("invalid option (%c)\n", cmd);
break;
}
-
- if (invalid_option && PROMIF_ISPRINT(cmd))
- prom_printf("invalid option (%c)\n", cmd);
}
_NOTE(NOTREACHED)
diff --git a/usr/src/uts/sun4v/sys/promif_impl.h b/usr/src/uts/sun4v/sys/promif_impl.h
index 2f5602a5b2..338182b9f1 100644
--- a/usr/src/uts/sun4v/sys/promif_impl.h
+++ b/usr/src/uts/sun4v/sys/promif_impl.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -100,6 +100,7 @@ extern caddr_t promif_stree_getroot(void);
*/
extern cif_func_t promif_find_cif_callback(char *opname);
extern int promif_ldom_setprop(char *name, void *value, int valuelen);
+extern char promif_getchar(void);
/*
* Initialization functions
diff --git a/usr/src/uts/sun4v/sys/qcn.h b/usr/src/uts/sun4v/sys/qcn.h
index d211647812..dbdfb32600 100644
--- a/usr/src/uts/sun4v/sys/qcn.h
+++ b/usr/src/uts/sun4v/sys/qcn.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -41,6 +41,7 @@ extern "C" {
#include <sys/tty.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
+#include <sys/consdev.h>
#define RINGBITS 8 /* # of bits in ring ptrs */
#define RINGSIZE (1<<RINGBITS) /* size of ring */
@@ -105,6 +106,13 @@ typedef struct qcn {
char *cons_write_buffer;
uint64_t cons_write_buf_ra;
uint64_t cons_read_buf_ra;
+
+ /*
+ * support for polled io
+ */
+ cons_polledio_t qcn_polledio;
+ boolean_t qcn_char_available;
+ uint8_t qcn_hold_char;
} qcn_t;
/* Constants for qcn_soft_pend */