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/src/uts/sun4v/promif | |
parent | 0280efdc4e507211851281715883a4b68445f267 (diff) | |
download | illumos-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.c | 163 | ||||
-rw-r--r-- | usr/src/uts/sun4v/promif/promif_mon.c | 137 |
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) |