Home | History | Annotate | Download | only in promif
      1  1991    heppo /*
      2  1991    heppo  * CDDL HEADER START
      3  1991    heppo  *
      4  1991    heppo  * The contents of this file are subject to the terms of the
      5  1991    heppo  * Common Development and Distribution License (the "License").
      6  1991    heppo  * You may not use this file except in compliance with the License.
      7  1991    heppo  *
      8  1991    heppo  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  1991    heppo  * or http://www.opensolaris.org/os/licensing.
     10  1991    heppo  * See the License for the specific language governing permissions
     11  1991    heppo  * and limitations under the License.
     12  1991    heppo  *
     13  1991    heppo  * When distributing Covered Code, include this CDDL HEADER in each
     14  1991    heppo  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  1991    heppo  * If applicable, add the following below this CDDL HEADER, with the
     16  1991    heppo  * fields enclosed by brackets "[]" replaced with your own identifying
     17  1991    heppo  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  1991    heppo  *
     19  1991    heppo  * CDDL HEADER END
     20  1991    heppo  */
     21  1991    heppo 
     22  1991    heppo /*
     23  5768  jm22469  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     24  1991    heppo  * Use is subject to license terms.
     25  1991    heppo  */
     26  1991    heppo 
     27  1991    heppo #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28  1991    heppo 
     29  1991    heppo #include <sys/promif_impl.h>
     30  1991    heppo #include <sys/systm.h>
     31  1991    heppo #include <sys/hypervisor_api.h>
     32  5974  jm22469 #include <sys/consdev.h>
     33  1991    heppo #ifndef _KMDB
     34  1991    heppo #include <sys/kmem.h>
     35  1991    heppo #endif
     36  5974  jm22469 
     37  5974  jm22469 /*
     38  5974  jm22469  * Definitions for using Polled I/O.
     39  5974  jm22469  *
     40  5974  jm22469  * The usage of Polled I/O is different when we are in kmdb. In that case,
     41  5974  jm22469  * we can not directly invoke the polled I/O functions and we have to use
     42  5974  jm22469  * the kmdb DPI interface. Also we don't need to enter/exit the polled I/O
     43  5974  jm22469  * mode because this is already managed by kmdb when entering/exiting the
     44  5974  jm22469  * debugger.
     45  5974  jm22469  *
     46  5974  jm22469  * When we are not in kmdb then we can directly call the polled I/O functions
     47  5974  jm22469  * but we have to enter the polled I/O mode first. After using polled I/O
     48  5974  jm22469  * functions we have to exit the polled I/O mode. Note that entering/exiting
     49  5974  jm22469  * the polled I/O mode is time consuming so this should be avoided when
     50  5974  jm22469  * possible.
     51  5974  jm22469  */
     52  5974  jm22469 #ifdef _KMDB
     53  5974  jm22469 extern struct cons_polledio *kmdb_kdi_get_polled_io(void);
     54  5974  jm22469 extern uintptr_t kmdb_dpi_call(uintptr_t, uint_t, const uintptr_t *);
     55  5974  jm22469 
     56  5974  jm22469 #define	PROMIF_PIO (kmdb_kdi_get_polled_io())
     57  5974  jm22469 
     58  5974  jm22469 #define	PROMIF_PIO_CALL1(fn, arg)					\
     59  5974  jm22469 	(kmdb_dpi_call((uintptr_t)fn, 1, (uintptr_t *)&arg))
     60  5974  jm22469 
     61  5974  jm22469 #define	PROMIF_PIO_CALL2(fn, arg1, arg2)				\
     62  5974  jm22469 	{								\
     63  5974  jm22469 		uintptr_t args[2];					\
     64  5974  jm22469 		args[0] = (uintptr_t)arg1;				\
     65  5974  jm22469 		args[1] = (uintptr_t)arg2;				\
     66  5974  jm22469 		(void) (kmdb_dpi_call((uintptr_t)fn, 2, (uintptr_t *)args)); \
     67  5974  jm22469 	}
     68  5974  jm22469 
     69  5974  jm22469 #define	PROMIF_PIO_ENTER(pio)
     70  5974  jm22469 #define	PROMIF_PIO_EXIT(pio)
     71  5974  jm22469 
     72  5974  jm22469 #else  /* _KMDB */
     73  5974  jm22469 
     74  5974  jm22469 #define	PROMIF_PIO				(cons_polledio)
     75  5974  jm22469 #define	PROMIF_PIO_CALL1(fn, arg)		(fn(arg))
     76  5974  jm22469 #define	PROMIF_PIO_CALL2(fn, arg1, arg2)	(fn(arg1, arg2))
     77  5974  jm22469 
     78  5974  jm22469 #define	PROMIF_PIO_ENTER(pio)						\
     79  5974  jm22469 	if (pio->cons_polledio_enter != NULL) {				\
     80  5974  jm22469 		pio->cons_polledio_enter(pio->cons_polledio_argument);	\
     81  5974  jm22469 	}
     82  5974  jm22469 
     83  5974  jm22469 #define	PROMIF_PIO_EXIT(pio)						\
     84  5974  jm22469 	if (pio->cons_polledio_exit != NULL) {				\
     85  5974  jm22469 		pio->cons_polledio_exit(pio->cons_polledio_argument);	\
     86  5974  jm22469 	}
     87  5974  jm22469 
     88  5974  jm22469 #endif	/* _KMDB */
     89  1991    heppo 
     90  1991    heppo #define	PROM_REG_TO_UNIT_ADDR(r)	((r) & ~(0xful << 28))
     91  1991    heppo 
     92  1991    heppo static pnode_t instance_to_package(ihandle_t ih);
     93  1991    heppo 
     94  1991    heppo /* cached copies of IO params */
     95  1991    heppo static phandle_t pstdin;
     96  1991    heppo static phandle_t pstdout;
     97  1991    heppo 
     98  1991    heppo static ihandle_t istdin;
     99  1991    heppo static ihandle_t istdout;
    100  5974  jm22469 
    101  5974  jm22469 static struct cons_polledio *promif_polledio = NULL;
    102  1991    heppo 
    103  1991    heppo int
    104  1991    heppo promif_instance_to_package(void *p)
    105  1991    heppo {
    106  1991    heppo 	cell_t		*ci = (cell_t *)p;
    107  1991    heppo 	ihandle_t	ih;
    108  1991    heppo 	phandle_t	ph;
    109  1991    heppo 
    110  1991    heppo 	ih = p1275_cell2ihandle(ci[3]);
    111  1991    heppo 
    112  1991    heppo 	ph = instance_to_package(ih);
    113  1991    heppo 
    114  1991    heppo 	ci[4] = p1275_phandle2cell(ph);
    115  1991    heppo 
    116  1991    heppo 	return (0);
    117  5974  jm22469 }
    118  5974  jm22469 
    119  5974  jm22469 /* This function is not used but it is convenient for debugging I/O problems */
    120  5974  jm22469 static void
    121  5974  jm22469 /* LINTED */
    122  5974  jm22469 promif_hv_print(char *str)
    123  5974  jm22469 {
    124  5974  jm22469 	size_t i, len = strlen(str);
    125  5974  jm22469 
    126  5974  jm22469 	for (i = 0; i < len; i++) {
    127  5974  jm22469 		while (hv_cnputchar((uint8_t)str[i]) == H_EWOULDBLOCK)
    128  5974  jm22469 			/* try forever */;
    129  5974  jm22469 	}
    130  5974  jm22469 }
    131  5974  jm22469 
    132  5974  jm22469 static void
    133  5974  jm22469 promif_pio_enter(void)
    134  5974  jm22469 {
    135  5974  jm22469 	ASSERT(promif_polledio == NULL);
    136  5974  jm22469 
    137  5974  jm22469 	promif_polledio = PROMIF_PIO;
    138  5974  jm22469 	ASSERT(promif_polledio != NULL);
    139  5974  jm22469 
    140  5974  jm22469 	PROMIF_PIO_ENTER(promif_polledio);
    141  5974  jm22469 }
    142  5974  jm22469 
    143  5974  jm22469 static void
    144  5974  jm22469 promif_pio_exit(void)
    145  5974  jm22469 {
    146  5974  jm22469 	ASSERT(promif_polledio != NULL);
    147  5974  jm22469 
    148  5974  jm22469 	PROMIF_PIO_EXIT(promif_polledio);
    149  5974  jm22469 	promif_polledio = NULL;
    150  5974  jm22469 }
    151  5974  jm22469 
    152  5974  jm22469 static int
    153  5974  jm22469 promif_do_read(char *buf, size_t len, boolean_t wait)
    154  5974  jm22469 {
    155  5974  jm22469 	int rlen;
    156  5974  jm22469 	int (*getchar)(cons_polledio_arg_t);
    157  5974  jm22469 	boolean_t (*ischar)(cons_polledio_arg_t);
    158  5974  jm22469 	cons_polledio_arg_t arg;
    159  5974  jm22469 
    160  5974  jm22469 	promif_pio_enter();
    161  5974  jm22469 
    162  5974  jm22469 	if ((ischar = promif_polledio->cons_polledio_ischar) == NULL)
    163  5974  jm22469 		return (0);
    164  5974  jm22469 	if ((getchar = promif_polledio->cons_polledio_getchar) == NULL)
    165  5974  jm22469 		return (0);
    166  5974  jm22469 
    167  5974  jm22469 	arg = promif_polledio->cons_polledio_argument;
    168  5974  jm22469 
    169  5974  jm22469 	for (rlen = 0; rlen < len; ) {
    170  5974  jm22469 		if (PROMIF_PIO_CALL1(ischar, arg)) {
    171  5974  jm22469 			buf[rlen] = PROMIF_PIO_CALL1(getchar, arg);
    172  5974  jm22469 			rlen++;
    173  5974  jm22469 			continue;
    174  5974  jm22469 		}
    175  5974  jm22469 
    176  5974  jm22469 		if (!wait)
    177  5974  jm22469 			break;
    178  5974  jm22469 	}
    179  5974  jm22469 
    180  5974  jm22469 	promif_pio_exit();
    181  5974  jm22469 
    182  5974  jm22469 	return (rlen);
    183  5974  jm22469 }
    184  5974  jm22469 
    185  5974  jm22469 static int
    186  5974  jm22469 promif_do_write(char *buf, size_t len)
    187  5974  jm22469 {
    188  5974  jm22469 	int rlen;
    189  5974  jm22469 	void (*putchar)(cons_polledio_arg_t, uchar_t);
    190  5974  jm22469 	cons_polledio_arg_t arg;
    191  5974  jm22469 
    192  5974  jm22469 	promif_pio_enter();
    193  5974  jm22469 
    194  5974  jm22469 	if ((putchar = promif_polledio->cons_polledio_putchar) == NULL)
    195  5974  jm22469 		return (0);
    196  5974  jm22469 
    197  5974  jm22469 	arg = promif_polledio->cons_polledio_argument;
    198  5974  jm22469 
    199  5974  jm22469 	for (rlen = 0; rlen < len; rlen++)
    200  5974  jm22469 		PROMIF_PIO_CALL2(putchar, arg, buf[rlen]);
    201  5974  jm22469 
    202  5974  jm22469 	promif_pio_exit();
    203  5974  jm22469 
    204  5974  jm22469 	return (rlen);
    205  5974  jm22469 }
    206  5974  jm22469 
    207  5974  jm22469 char
    208  5974  jm22469 promif_getchar(void)
    209  5974  jm22469 {
    210  5974  jm22469 	char c;
    211  5974  jm22469 
    212  5974  jm22469 	(void) promif_do_read(&c, 1, B_TRUE);
    213  5974  jm22469 	return (c);
    214  1991    heppo }
    215  1991    heppo 
    216  1991    heppo int
    217  1991    heppo promif_write(void *p)
    218  1991    heppo {
    219  1991    heppo 	cell_t	*ci = (cell_t *)p;
    220  1991    heppo 	uint_t	fd;
    221  1991    heppo 	char	*buf;
    222  1991    heppo 	size_t	len;
    223  1991    heppo 	size_t	rlen;
    224  1991    heppo 
    225  1991    heppo 	ASSERT(ci[1] == 3);
    226  1991    heppo 
    227  1991    heppo 	fd  = p1275_cell2uint(ci[3]);
    228  1991    heppo 	buf = p1275_cell2ptr(ci[4]);
    229  1991    heppo 	len = p1275_cell2size(ci[5]);
    230  1991    heppo 
    231  1991    heppo 	/* only support stdout (console) */
    232  1991    heppo 	ASSERT(fd == istdout);
    233  1991    heppo 
    234  5974  jm22469 	rlen = promif_do_write(buf, len);
    235  1991    heppo 
    236  1991    heppo 	/* return the length written */
    237  1991    heppo 	ci[6] = p1275_size2cell(rlen);
    238  1991    heppo 
    239  1991    heppo 	return (0);
    240  1991    heppo }
    241  1991    heppo 
    242  1991    heppo int
    243  1991    heppo promif_read(void *p)
    244  1991    heppo {
    245  1991    heppo 	cell_t	*ci = (cell_t *)p;
    246  1991    heppo 	uint_t	fd;
    247  1991    heppo 	char	*buf;
    248  1991    heppo 	size_t	len;
    249  1991    heppo 	size_t	rlen;
    250  1991    heppo 
    251  1991    heppo 	ASSERT(ci[1] == 3);
    252  1991    heppo 
    253  1991    heppo 	/* unpack arguments */
    254  1991    heppo 	fd  = p1275_cell2uint(ci[3]);
    255  1991    heppo 	buf = p1275_cell2ptr(ci[4]);
    256  1991    heppo 	len = p1275_cell2size(ci[5]);
    257  1991    heppo 
    258  1991    heppo 	/* only support stdin (console) */
    259  1991    heppo 	ASSERT(fd == istdin);
    260  1991    heppo 
    261  5974  jm22469 	rlen = promif_do_read(buf, len, B_FALSE);
    262  1991    heppo 
    263  1991    heppo 	/* return the length read */
    264  1991    heppo 	ci[6] = p1275_size2cell(rlen);
    265  1991    heppo 
    266  1991    heppo 	return (0);
    267  1991    heppo }
    268  1991    heppo 
    269  1991    heppo static pnode_t
    270  1991    heppo instance_to_package(ihandle_t ih)
    271  1991    heppo {
    272  1991    heppo 	/* only support stdin and stdout */
    273  1991    heppo 	ASSERT((ih == istdin) || (ih == istdout));
    274  1991    heppo 
    275  1991    heppo 	if (ih == istdin)
    276  1991    heppo 		return (pstdin);
    277  1991    heppo 
    278  1991    heppo 	if (ih == istdout)
    279  1991    heppo 		return (pstdout);
    280  1991    heppo 
    281  1991    heppo 	return (OBP_BADNODE);
    282  1991    heppo }
    283  1991    heppo 
    284  1991    heppo #ifdef _KMDB
    285  1991    heppo 
    286  1991    heppo void
    287  1991    heppo promif_io_init(ihandle_t in, ihandle_t out, phandle_t pin, phandle_t pout)
    288  1991    heppo {
    289  1991    heppo 	istdin = in;
    290  1991    heppo 	istdout = out;
    291  1991    heppo 	pstdin = pin;
    292  1991    heppo 	pstdout = pout;
    293  1991    heppo }
    294  1991    heppo 
    295  1991    heppo #else
    296  1991    heppo 
    297  1991    heppo void
    298  1991    heppo promif_io_init(void)
    299  1991    heppo {
    300  1991    heppo 	/*
    301  1991    heppo 	 * Cache the mapping between the stdin and stdout
    302  1991    heppo 	 * ihandles and their respective phandles.
    303  1991    heppo 	 */
    304  1991    heppo 	pstdin = prom_stdin_node();
    305  1991    heppo 	pstdout = prom_stdout_node();
    306  1991    heppo 
    307  1991    heppo 	istdin = prom_stdin_ihandle();
    308  1991    heppo 	istdout = prom_stdout_ihandle();
    309  1991    heppo }
    310  1991    heppo 
    311  1991    heppo int
    312  1991    heppo promif_instance_to_path(void *p)
    313  1991    heppo {
    314  1991    heppo 	cell_t		*ci = (cell_t *)p;
    315  1991    heppo 	pnode_t		node;
    316  1991    heppo 	ihandle_t	ih;
    317  1991    heppo 	char		*buf;
    318  1991    heppo 	int		rlen;
    319  1991    heppo 	char		*regval;
    320  1991    heppo 	uint_t		*csaddr;
    321  1991    heppo 	char		name[OBP_MAXPROPNAME];
    322  1991    heppo 	char		scratch[OBP_MAXPATHLEN];
    323  1991    heppo 	int		rvlen;
    324  1991    heppo 
    325  1991    heppo 	ih = p1275_cell2ihandle(ci[3]);
    326  1991    heppo 	buf = p1275_cell2ptr(ci[4]);
    327  1991    heppo 
    328  1991    heppo 	ci[6] = p1275_uint2cell(0);
    329  1991    heppo 
    330  1991    heppo 	node = instance_to_package(ih);
    331  1991    heppo 
    332  1991    heppo 	*buf = '\0';
    333  1991    heppo 
    334  1991    heppo 	while (node != prom_rootnode()) {
    335  1991    heppo 		if (prom_getprop(node, OBP_NAME, name) == -1) {
    336  1991    heppo 			prom_printf("instance_to_path: no name property "
    337  1991    heppo 			    "node=0x%x\n", node);
    338  1991    heppo 			return (-1);
    339  1991    heppo 		}
    340  1991    heppo 
    341  1991    heppo 		/* construct the unit address from the 'reg' property */
    342  1991    heppo 		if ((rlen = prom_getproplen(node, OBP_REG)) == -1)
    343  1991    heppo 			return (-1);
    344  1991    heppo 
    345  5502  jm22469 		/*
    346  5502  jm22469 		 * Make sure we don't get dispatched onto a different
    347  5502  jm22469 		 * cpu if we happen to sleep.  See kern_postprom().
    348  5502  jm22469 		 */
    349  5768  jm22469 		thread_affinity_set(curthread, CPU->cpu_id);
    350  1991    heppo 		regval = kmem_zalloc(rlen, KM_SLEEP);
    351  1991    heppo 
    352  1991    heppo 		(void) prom_getprop(node, OBP_REG, regval);
    353  1991    heppo 
    354  1991    heppo 		csaddr = (uint_t *)regval;
    355  1991    heppo 
    356  1991    heppo 		(void) prom_sprintf(scratch, "/%s@%lx%s", name,
    357  1991    heppo 		    PROM_REG_TO_UNIT_ADDR(*csaddr), buf);
    358  1991    heppo 
    359  1991    heppo 		kmem_free(regval, rlen);
    360  5768  jm22469 		thread_affinity_clear(curthread);
    361  1991    heppo 
    362  1991    heppo 		(void) prom_strcpy(buf, scratch);
    363  1991    heppo 
    364  1991    heppo 		node = prom_parentnode(node);
    365  1991    heppo 	}
    366  1991    heppo 
    367  1991    heppo 	rvlen = prom_strlen(buf);
    368  1991    heppo 	ci[6] = p1275_uint2cell(rvlen);
    369  1991    heppo 
    370  1991    heppo 	return (0);
    371  1991    heppo }
    372  1991    heppo 
    373  1991    heppo #endif	/* _KMDB */
    374