diff options
author | jm22469 <none@none> | 2008-02-05 09:01:19 -0800 |
---|---|---|
committer | jm22469 <none@none> | 2008-02-05 09:01:19 -0800 |
commit | 1b83305cfc332b1e19ad6a194b73b2975e6bf79a (patch) | |
tree | 8bf803a14d9bbf1f261d97e19a1c18b8102f6973 /usr | |
parent | 0280efdc4e507211851281715883a4b68445f267 (diff) | |
download | illumos-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.c | 139 | ||||
-rw-r--r-- | usr/src/uts/common/os/main.c | 3 | ||||
-rw-r--r-- | usr/src/uts/common/sys/consconfig_dacf.h | 6 | ||||
-rw-r--r-- | usr/src/uts/sparc/io/consplat.c | 28 | ||||
-rw-r--r-- | usr/src/uts/sun/sys/bootconf.h | 3 | ||||
-rw-r--r-- | usr/src/uts/sun4/os/startup.c | 10 | ||||
-rw-r--r-- | usr/src/uts/sun4v/io/qcn.c | 116 | ||||
-rw-r--r-- | usr/src/uts/sun4v/os/mach_cpu_states.c | 35 | ||||
-rw-r--r-- | usr/src/uts/sun4v/promif/promif_io.c | 163 | ||||
-rw-r--r-- | usr/src/uts/sun4v/promif/promif_mon.c | 137 | ||||
-rw-r--r-- | usr/src/uts/sun4v/sys/promif_impl.h | 3 | ||||
-rw-r--r-- | usr/src/uts/sun4v/sys/qcn.h | 10 |
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 */ |