1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (C) 2019 Leandro Lupori 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 27 #include <sys/cdefs.h> 28 #include <sys/linker_set.h> 29 #include <sys/param.h> 30 #include <sys/types.h> 31 32 struct thread; 33 34 #include <vm/vm.h> 35 #include <vm/pmap.h> 36 37 #include <dev/ofw/openfirm.h> 38 #include <gdb/gdb.h> 39 40 #include "opal.h" 41 42 static gdb_probe_f uart_opal_dbg_probe; 43 static gdb_init_f uart_opal_dbg_init; 44 static gdb_term_f uart_opal_dbg_term; 45 static gdb_getc_f uart_opal_dbg_getc; 46 static gdb_putc_f uart_opal_dbg_putc; 47 48 GDB_DBGPORT(uart_opal, uart_opal_dbg_probe, 49 uart_opal_dbg_init, uart_opal_dbg_term, 50 uart_opal_dbg_getc, uart_opal_dbg_putc); 51 52 static int64_t termnum; 53 54 static int 55 uart_opal_dbg_probe(void) 56 { 57 char buf[64]; 58 cell_t reg; 59 phandle_t dev; 60 61 if (!getenv_string("hw.uart.dbgport", buf, sizeof(buf))) 62 return (-1); 63 if ((dev = OF_finddevice(buf)) == -1) 64 return (-1); 65 66 if (OF_getprop(dev, "device_type", buf, sizeof(buf)) == -1) 67 return (-1); 68 if (strcmp(buf, "serial") != 0) 69 return (-1); 70 71 if (OF_getprop(dev, "compatible", buf, sizeof(buf)) == -1) 72 return (-1); 73 if (strcmp(buf, "ibm,opal-console-raw") != 0) 74 return (-1); 75 76 reg = ~0U; 77 OF_getencprop(dev, "reg", ®, sizeof(reg)); 78 if (reg == ~0U) 79 return (-1); 80 termnum = reg; 81 82 return (0); 83 } 84 85 static void 86 uart_opal_dbg_init(void) 87 { 88 } 89 90 static void 91 uart_opal_dbg_term(void) 92 { 93 } 94 95 static int 96 uart_opal_dbg_getc(void) 97 { 98 char c; 99 int err; 100 int64_t len; 101 uint64_t lenp, bufp; 102 103 len = 1; 104 if (pmap_bootstrapped) { 105 lenp = vtophys(&len); 106 bufp = vtophys(&c); 107 } else { 108 lenp = (uint64_t)&len; 109 bufp = (uint64_t)&c; 110 } 111 112 err = opal_call(OPAL_CONSOLE_READ, termnum, lenp, bufp); 113 if (err != OPAL_SUCCESS || len != 1) 114 return (-1); 115 116 opal_call(OPAL_POLL_EVENTS, NULL); 117 118 return (c); 119 } 120 121 static void 122 uart_opal_dbg_putc(int c) 123 { 124 char ch; 125 int err; 126 int64_t len; 127 uint64_t lenp, bufp; 128 129 ch = (unsigned char)c; 130 len = 1; 131 if (pmap_bootstrapped) { 132 lenp = vtophys(&len); 133 bufp = vtophys(&ch); 134 } else { 135 lenp = (uint64_t)&len; 136 bufp = (uint64_t)&ch; 137 } 138 139 for (;;) { 140 err = opal_call(OPAL_CONSOLE_WRITE, termnum, lenp, bufp); 141 /* Clear FIFO if needed. */ 142 if (err == OPAL_BUSY_EVENT) 143 opal_call(OPAL_POLL_EVENTS, NULL); 144 else 145 /* break on success or unrecoverable errors */ 146 break; 147 } 148 DELAY(100); 149 } 150