summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4v/promif
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/src/uts/sun4v/promif
parent0280efdc4e507211851281715883a4b68445f267 (diff)
downloadillumos-joyent-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/src/uts/sun4v/promif')
-rw-r--r--usr/src/uts/sun4v/promif/promif_io.c163
-rw-r--r--usr/src/uts/sun4v/promif/promif_mon.c137
2 files changed, 192 insertions, 108 deletions
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)