phyp_console.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (C) 2011 by Nathan Whitehorn. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  21. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  22. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  23. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  24. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <sys/cdefs.h>
  27. __FBSDID("$FreeBSD$");
  28. #include <sys/endian.h>
  29. #include <sys/param.h>
  30. #include <sys/kdb.h>
  31. #include <sys/kernel.h>
  32. #include <sys/priv.h>
  33. #include <sys/systm.h>
  34. #include <sys/module.h>
  35. #include <sys/types.h>
  36. #include <sys/conf.h>
  37. #include <sys/cons.h>
  38. #include <sys/tty.h>
  39. #include <machine/bus.h>
  40. #include <dev/ofw/openfirm.h>
  41. #include <dev/ofw/ofw_bus.h>
  42. #include <dev/ofw/ofw_bus_subr.h>
  43. #include <dev/uart/uart.h>
  44. #include <dev/uart/uart_cpu.h>
  45. #include <dev/uart/uart_bus.h>
  46. #include "phyp-hvcall.h"
  47. #include "uart_if.h"
  48. struct uart_phyp_softc {
  49. device_t dev;
  50. phandle_t node;
  51. int vtermid;
  52. struct tty *tp;
  53. struct resource *irqres;
  54. int irqrid;
  55. struct callout callout;
  56. void *sc_icookie;
  57. int polltime;
  58. struct mtx sc_mtx;
  59. int protocol;
  60. union {
  61. uint64_t u64[2];
  62. char str[16];
  63. } phyp_inbuf;
  64. uint64_t inbuflen;
  65. uint8_t outseqno;
  66. };
  67. static struct uart_phyp_softc *console_sc = NULL;
  68. #if defined(KDB)
  69. static int alt_break_state;
  70. #endif
  71. enum {
  72. HVTERM1, HVTERMPROT
  73. };
  74. #define VS_DATA_PACKET_HEADER 0xff
  75. #define VS_CONTROL_PACKET_HEADER 0xfe
  76. #define VSV_SET_MODEM_CTL 0x01
  77. #define VSV_MODEM_CTL_UPDATE 0x02
  78. #define VSV_RENEGOTIATE_CONNECTION 0x03
  79. #define VS_QUERY_PACKET_HEADER 0xfd
  80. #define VSV_SEND_VERSION_NUMBER 0x01
  81. #define VSV_SEND_MODEM_CTL_STATUS 0x02
  82. #define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc
  83. static int uart_phyp_probe(device_t dev);
  84. static int uart_phyp_attach(device_t dev);
  85. static void uart_phyp_intr(void *v);
  86. static device_method_t uart_phyp_methods[] = {
  87. /* Device interface */
  88. DEVMETHOD(device_probe, uart_phyp_probe),
  89. DEVMETHOD(device_attach, uart_phyp_attach),
  90. DEVMETHOD_END
  91. };
  92. static driver_t uart_phyp_driver = {
  93. "uart",
  94. uart_phyp_methods,
  95. sizeof(struct uart_phyp_softc),
  96. };
  97. DRIVER_MODULE(uart_phyp, vdevice, uart_phyp_driver, uart_devclass, 0, 0);
  98. static cn_probe_t uart_phyp_cnprobe;
  99. static cn_init_t uart_phyp_cninit;
  100. static cn_term_t uart_phyp_cnterm;
  101. static cn_getc_t uart_phyp_cngetc;
  102. static cn_putc_t uart_phyp_cnputc;
  103. static cn_grab_t uart_phyp_cngrab;
  104. static cn_ungrab_t uart_phyp_cnungrab;
  105. CONSOLE_DRIVER(uart_phyp);
  106. static void uart_phyp_ttyoutwakeup(struct tty *tp);
  107. static struct ttydevsw uart_phyp_tty_class = {
  108. .tsw_flags = TF_INITLOCK|TF_CALLOUT,
  109. .tsw_outwakeup = uart_phyp_ttyoutwakeup,
  110. };
  111. static int
  112. uart_phyp_probe_node(struct uart_phyp_softc *sc)
  113. {
  114. phandle_t node = sc->node;
  115. uint32_t reg;
  116. char buf[64];
  117. sc->inbuflen = 0;
  118. sc->outseqno = 0;
  119. if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0)
  120. return (ENXIO);
  121. if (strcmp(buf, "vty") != 0)
  122. return (ENXIO);
  123. if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0)
  124. return (ENXIO);
  125. if (strcmp(buf, "serial") != 0)
  126. return (ENXIO);
  127. reg = -1;
  128. OF_getencprop(node, "reg", &reg, sizeof(reg));
  129. if (reg == -1)
  130. return (ENXIO);
  131. sc->vtermid = reg;
  132. sc->node = node;
  133. if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0)
  134. return (ENXIO);
  135. if (strcmp(buf, "hvterm1") == 0) {
  136. sc->protocol = HVTERM1;
  137. return (0);
  138. } else if (strcmp(buf, "hvterm-protocol") == 0) {
  139. sc->protocol = HVTERMPROT;
  140. return (0);
  141. }
  142. return (ENXIO);
  143. }
  144. static int
  145. uart_phyp_probe(device_t dev)
  146. {
  147. const char *name;
  148. struct uart_phyp_softc sc;
  149. int err;
  150. name = ofw_bus_get_name(dev);
  151. if (name == NULL || strcmp(name, "vty") != 0)
  152. return (ENXIO);
  153. sc.node = ofw_bus_get_node(dev);
  154. err = uart_phyp_probe_node(&sc);
  155. if (err != 0)
  156. return (err);
  157. device_set_desc(dev, "POWER Hypervisor Virtual Serial Port");
  158. return (err);
  159. }
  160. static void
  161. uart_phyp_cnprobe(struct consdev *cp)
  162. {
  163. char buf[64];
  164. ihandle_t stdout;
  165. phandle_t input, chosen;
  166. static struct uart_phyp_softc sc;
  167. if ((chosen = OF_finddevice("/chosen")) == -1)
  168. goto fail;
  169. /* Check if OF has an active stdin/stdout */
  170. input = -1;
  171. if (OF_getencprop(chosen, "stdout", &stdout,
  172. sizeof(stdout)) == sizeof(stdout) && stdout != 0)
  173. input = OF_instance_to_package(stdout);
  174. if (input == -1)
  175. goto fail;
  176. if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1)
  177. goto fail;
  178. if (strcmp(buf, "serial") != 0)
  179. goto fail;
  180. sc.node = input;
  181. if (uart_phyp_probe_node(&sc) != 0)
  182. goto fail;
  183. mtx_init(&sc.sc_mtx, "uart_phyp", NULL, MTX_SPIN | MTX_QUIET |
  184. MTX_NOWITNESS);
  185. cp->cn_pri = CN_NORMAL;
  186. console_sc = &sc;
  187. return;
  188. fail:
  189. cp->cn_pri = CN_DEAD;
  190. return;
  191. }
  192. static int
  193. uart_phyp_attach(device_t dev)
  194. {
  195. struct uart_phyp_softc *sc;
  196. int unit;
  197. sc = device_get_softc(dev);
  198. sc->dev = dev;
  199. sc->node = ofw_bus_get_node(dev);
  200. uart_phyp_probe_node(sc);
  201. unit = device_get_unit(dev);
  202. sc->tp = tty_alloc(&uart_phyp_tty_class, sc);
  203. mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL,
  204. MTX_SPIN | MTX_QUIET | MTX_NOWITNESS);
  205. if (console_sc != NULL && console_sc->vtermid == sc->vtermid) {
  206. sc->outseqno = console_sc->outseqno;
  207. console_sc = sc;
  208. sprintf(uart_phyp_consdev.cn_name, "ttyu%r", unit);
  209. tty_init_console(sc->tp, 0);
  210. }
  211. sc->irqrid = 0;
  212. sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid,
  213. RF_ACTIVE | RF_SHAREABLE);
  214. if (sc->irqres != NULL) {
  215. bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE,
  216. NULL, uart_phyp_intr, sc, &sc->sc_icookie);
  217. } else {
  218. callout_init(&sc->callout, 1);
  219. sc->polltime = hz / 20;
  220. if (sc->polltime < 1)
  221. sc->polltime = 1;
  222. callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
  223. }
  224. tty_makedev(sc->tp, NULL, "u%r", unit);
  225. return (0);
  226. }
  227. static void
  228. uart_phyp_cninit(struct consdev *cp)
  229. {
  230. strcpy(cp->cn_name, "phypcons");
  231. }
  232. static void
  233. uart_phyp_cnterm(struct consdev *cp)
  234. {
  235. }
  236. static int
  237. uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
  238. {
  239. int err;
  240. int hdr = 0;
  241. uint64_t i, j;
  242. uart_lock(&sc->sc_mtx);
  243. if (sc->inbuflen == 0) {
  244. err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid,
  245. 0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0],
  246. &sc->phyp_inbuf.u64[1]);
  247. if (err != H_SUCCESS) {
  248. uart_unlock(&sc->sc_mtx);
  249. return (-1);
  250. }
  251. hdr = 1;
  252. }
  253. if (sc->inbuflen == 0) {
  254. uart_unlock(&sc->sc_mtx);
  255. return (0);
  256. }
  257. #if BYTE_ORDER == LITTLE_ENDIAN
  258. sc->phyp_inbuf.u64[0] = be64toh(sc->phyp_inbuf.u64[0]);
  259. sc->phyp_inbuf.u64[1] = be64toh(sc->phyp_inbuf.u64[1]);
  260. #endif
  261. if ((sc->protocol == HVTERMPROT) && (hdr == 1)) {
  262. sc->inbuflen = sc->inbuflen - 4;
  263. /* The VTERM protocol has a 4 byte header, skip it here. */
  264. memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[4],
  265. sc->inbuflen);
  266. }
  267. /*
  268. * Since version 2.11.0, QEMU became bug-compatible with
  269. * PowerVM's vty implementation, by inserting a \0 after
  270. * every \r going to the guest. Guests are expected to
  271. * workaround this issue by removing every \0 immediately
  272. * following a \r.
  273. */
  274. if (hdr == 1) {
  275. for (i = 0, j = 0; i < sc->inbuflen; i++, j++) {
  276. if (i > j)
  277. sc->phyp_inbuf.str[j] = sc->phyp_inbuf.str[i];
  278. if (sc->phyp_inbuf.str[i] == '\r' &&
  279. i < sc->inbuflen - 1 &&
  280. sc->phyp_inbuf.str[i + 1] == '\0')
  281. i++;
  282. }
  283. sc->inbuflen -= i - j;
  284. }
  285. if (bufsize > sc->inbuflen)
  286. bufsize = sc->inbuflen;
  287. memcpy(buffer, sc->phyp_inbuf.str, bufsize);
  288. sc->inbuflen -= bufsize;
  289. if (sc->inbuflen > 0)
  290. memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[bufsize],
  291. sc->inbuflen);
  292. uart_unlock(&sc->sc_mtx);
  293. return (bufsize);
  294. }
  295. static int
  296. uart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
  297. {
  298. uint16_t seqno;
  299. uint64_t len = 0;
  300. int err;
  301. union {
  302. uint64_t u64[2];
  303. char bytes[16];
  304. } cbuf;
  305. uart_lock(&sc->sc_mtx);
  306. switch (sc->protocol) {
  307. case HVTERM1:
  308. if (bufsize > 16)
  309. bufsize = 16;
  310. memcpy(&cbuf, buffer, bufsize);
  311. len = bufsize;
  312. break;
  313. case HVTERMPROT:
  314. if (bufsize > 12)
  315. bufsize = 12;
  316. seqno = sc->outseqno++;
  317. cbuf.bytes[0] = VS_DATA_PACKET_HEADER;
  318. cbuf.bytes[1] = 4 + bufsize; /* total length, max 16 bytes */
  319. cbuf.bytes[2] = (seqno >> 8) & 0xff;
  320. cbuf.bytes[3] = seqno & 0xff;
  321. memcpy(&cbuf.bytes[4], buffer, bufsize);
  322. len = 4 + bufsize;
  323. break;
  324. }
  325. do {
  326. err = phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, htobe64(cbuf.u64[0]),
  327. htobe64(cbuf.u64[1]));
  328. DELAY(100);
  329. } while (err == H_BUSY);
  330. uart_unlock(&sc->sc_mtx);
  331. return (bufsize);
  332. }
  333. static int
  334. uart_phyp_cngetc(struct consdev *cp)
  335. {
  336. unsigned char c;
  337. int retval;
  338. retval = uart_phyp_get(console_sc, &c, 1);
  339. if (retval != 1)
  340. return (-1);
  341. #if defined(KDB)
  342. kdb_alt_break(c, &alt_break_state);
  343. #endif
  344. return (c);
  345. }
  346. static void
  347. uart_phyp_cnputc(struct consdev *cp, int c)
  348. {
  349. unsigned char ch = c;
  350. uart_phyp_put(console_sc, &ch, 1);
  351. }
  352. static void
  353. uart_phyp_cngrab(struct consdev *cp)
  354. {
  355. }
  356. static void
  357. uart_phyp_cnungrab(struct consdev *cp)
  358. {
  359. }
  360. static void
  361. uart_phyp_ttyoutwakeup(struct tty *tp)
  362. {
  363. struct uart_phyp_softc *sc;
  364. char buffer[8];
  365. int len;
  366. sc = tty_softc(tp);
  367. while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0)
  368. uart_phyp_put(sc, buffer, len);
  369. }
  370. static void
  371. uart_phyp_intr(void *v)
  372. {
  373. struct uart_phyp_softc *sc = v;
  374. struct tty *tp = sc->tp;
  375. unsigned char c;
  376. int len;
  377. tty_lock(tp);
  378. while ((len = uart_phyp_get(sc, &c, 1)) > 0)
  379. ttydisc_rint(tp, c, 0);
  380. ttydisc_rint_done(tp);
  381. tty_unlock(tp);
  382. if (sc->irqres == NULL)
  383. callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
  384. }