Home | History | Annotate | Line # | Download | only in goldfish
gftty.c revision 1.2
      1 /*	$NetBSD: gftty.c,v 1.2 2024/01/02 07:30:29 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2023 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * Support for the Goldfish virtual TTY.
     34  */
     35 
     36 #include <sys/cdefs.h>
     37 __KERNEL_RCSID(0, "$NetBSD: gftty.c,v 1.2 2024/01/02 07:30:29 thorpej Exp $");
     38 
     39 #include <sys/param.h>
     40 #include <sys/systm.h>
     41 #include <sys/bus.h>
     42 #include <sys/device.h>
     43 #include <sys/kmem.h>
     44 
     45 #include <uvm/uvm_extern.h>
     46 
     47 #include <dev/cons.h>
     48 
     49 #include <dev/goldfish/gfttyvar.h>
     50 
     51 /*
     52  * Goldfish TTY registers.
     53  */
     54 #define	GFTTY_PUT_CHAR		0x00	/* 8 bit output value */
     55 #define	GFTTY_BYTES_READY	0x04	/* number of input bytes available */
     56 #define	GFTTY_CMD		0x08	/* command */
     57 #define	GFTTY_DATA_PTR		0x10	/* DMA pointer */
     58 #define	GFTTY_DATA_LEN		0x14	/* DMA length */
     59 #define	GFTTY_DATA_PTR_HIGH	0x18	/* DMA pointer (64-bit) */
     60 #define	GFTTY_VERSION		0x20	/* TTY version */
     61 
     62 #define	CMD_INT_DISABLE		0x00
     63 #define	CMD_INT_ENABLE		0x01
     64 #define	CMD_WRITE_BUFFER	0x02
     65 #define	CMD_READ_BUFFER		0x03
     66 
     67 #define	REG_READ0(c, r)		\
     68 	bus_space_read_4((c)->c_bst, (c)->c_bsh, (r))
     69 #define	REG_WRITE0(c, r, v)	\
     70 	bus_space_write_4((c)->c_bst, (c)->c_bsh, (r), (v))
     71 
     72 #define	REG_READ(sc, r)		REG_READ0((sc)->sc_config, (r))
     73 #define	REG_WRITE(sc, r, v)	REG_WRITE0((sc)->sc_config, (r), (v))
     74 
     75 static int	gftty_cngetc(dev_t);
     76 static void	gftty_cnputc(dev_t, int);
     77 static void	gftty_cnpollc(dev_t, int);
     78 
     79 static struct gftty_config gftty_cnconfig;
     80 static struct cnm_state gftty_cnmagic_state;
     81 static struct consdev gftty_consdev = {
     82 	.cn_getc	=	gftty_cngetc,
     83 	.cn_putc	=	gftty_cnputc,
     84 	.cn_pollc	=	gftty_cnpollc,
     85 	.cn_dev		=	NODEV,
     86 	.cn_pri		=	CN_NORMAL,
     87 };
     88 
     89 /*
     90  * gftty_attach --
     91  *	Attach a Goldfish virual TTY.
     92  */
     93 void
     94 gftty_attach(struct gftty_softc *sc)
     95 {
     96 
     97 	aprint_naive("\n");
     98 	aprint_normal(": Google Goldfish TTY\n");
     99 
    100 	/* If we got here without a config, we're the console. */
    101 	if (sc->sc_config == NULL) {
    102 		KASSERT(gftty_is_console(sc));
    103 		sc->sc_config = &gftty_cnconfig;
    104 		aprint_normal_dev(sc->sc_dev, "console\n");
    105 	}
    106 }
    107 
    108 /*
    109  * gftty_is_console --
    110  *	Returns true if the specified gftty instance is currently
    111  *	the console.
    112  */
    113 bool
    114 gftty_is_console(struct gftty_softc *sc)
    115 {
    116 	if (cn_tab == &gftty_consdev) {
    117 		bool val;
    118 
    119 		if (prop_dictionary_get_bool(device_properties(sc->sc_dev),
    120 					     "is-console", &val)) {
    121 			return val;
    122 		}
    123 	}
    124 	return false;
    125 }
    126 
    127 /*
    128  * gftty_init_config --
    129  *	Initialize a config structure.
    130  */
    131 static void
    132 gftty_init_config(struct gftty_config *c, bus_space_tag_t bst,
    133     bus_space_handle_t bsh)
    134 {
    135 	c->c_bst = bst;
    136 	c->c_bsh = bsh;
    137 	c->c_version = REG_READ0(c, GFTTY_VERSION);
    138 }
    139 
    140 /*
    141  * gftty_alloc_config --
    142  *	Allocate a config structure, initialize it, and assign
    143  *	it to this device.
    144  */
    145 void
    146 gftty_alloc_config(struct gftty_softc *sc, bus_space_tag_t bst,
    147     bus_space_handle_t bsh)
    148 {
    149 	struct gftty_config *c = kmem_zalloc(sizeof(*c), KM_SLEEP);
    150 
    151 	gftty_init_config(c, bst, bsh);
    152 	sc->sc_config = c;
    153 }
    154 
    155 /*
    156  * gftty_set_buffer --
    157  *	Set the buffer address / length for an I/O operation.
    158  */
    159 static void
    160 gftty_set_buffer(struct gftty_config *c, bus_addr_t addr, bus_size_t size)
    161 {
    162 	REG_WRITE0(c, GFTTY_DATA_PTR, BUS_ADDR_LO32(addr));
    163 	if (sizeof(bus_addr_t) == 8) {
    164 		REG_WRITE0(c, GFTTY_DATA_PTR_HIGH, BUS_ADDR_HI32(addr));
    165 	}
    166 	REG_WRITE0(c, GFTTY_DATA_LEN, (uint32_t)size);
    167 }
    168 
    169 /*
    170  * gftty console routines.
    171  */
    172 static int
    173 gftty_cngetc(dev_t dev)
    174 {
    175 	struct gftty_config * const c = &gftty_cnconfig;
    176 
    177 	if (REG_READ0(c, GFTTY_BYTES_READY) == 0) {
    178 		return -1;
    179 	}
    180 
    181 	/*
    182 	 * XXX This is all terrible and should burn to the ground.
    183 	 * XXX This device desperately needs to be improved with
    184 	 * XXX a GET_CHAR register.
    185 	 */
    186 	bus_addr_t addr;
    187 	uint8_t buf[1];
    188 
    189 	if (c->c_version == 0) {
    190 		addr = (bus_addr_t)buf;
    191 	} else {
    192 		addr = vtophys((vaddr_t)buf);
    193 	}
    194 
    195 	gftty_set_buffer(c, addr, sizeof(buf));
    196 	REG_WRITE0(c, GFTTY_CMD, CMD_READ_BUFFER);
    197 
    198 	return buf[0];
    199 }
    200 
    201 static void
    202 gftty_cnputc(dev_t dev, int ch)
    203 {
    204 	REG_WRITE0(&gftty_cnconfig, GFTTY_PUT_CHAR, (unsigned char)ch);
    205 }
    206 
    207 static void
    208 gftty_cnpollc(dev_t dev, int on)
    209 {
    210 	/* XXX */
    211 }
    212 
    213 /*
    214  * gftty_cnattach --
    215  *	Attach a Goldfish virtual TTY console.
    216  */
    217 void
    218 gftty_cnattach(bus_space_tag_t bst, bus_space_handle_t bsh)
    219 {
    220 	gftty_init_config(&gftty_cnconfig, bst, bsh);
    221 
    222 	cn_tab = &gftty_consdev;
    223 	cn_init_magic(&gftty_cnmagic_state);
    224 	cn_set_magic("+++++");
    225 }
    226