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