1 1.22 thorpej /* $NetBSD: tcom.c,v 1.22 2021/08/07 16:19:12 thorpej Exp $ */ 2 1.1 christos 3 1.1 christos /*- 4 1.1 christos * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.1 christos * All rights reserved. 6 1.1 christos * 7 1.1 christos * This code is derived from software contributed to The NetBSD Foundation 8 1.1 christos * by Eric S. Hvozda. 9 1.1 christos * 10 1.1 christos * Redistribution and use in source and binary forms, with or without 11 1.1 christos * modification, are permitted provided that the following conditions 12 1.1 christos * are met: 13 1.1 christos * 1. Redistributions of source code must retain the above copyright 14 1.1 christos * notice, this list of conditions and the following disclaimer. 15 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 christos * notice, this list of conditions and the following disclaimer in the 17 1.1 christos * documentation and/or other materials provided with the distribution. 18 1.1 christos * 19 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 christos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 christos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 christos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 christos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 christos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 christos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 christos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 christos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 christos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 christos * POSSIBILITY OF SUCH DAMAGE. 30 1.1 christos */ 31 1.1 christos 32 1.1 christos /* 33 1.1 christos * Copyright (c) 1998 Jukka Marin. All rights reserved. 34 1.1 christos * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 35 1.1 christos * Copyright (c) 1995 Charles Hannum. All rights reserved. 36 1.1 christos * 37 1.1 christos * This code is derived from public-domain software written by 38 1.1 christos * Roland McGrath. 39 1.1 christos * 40 1.1 christos * Redistribution and use in source and binary forms, with or without 41 1.1 christos * modification, are permitted provided that the following conditions 42 1.1 christos * are met: 43 1.1 christos * 1. Redistributions of source code must retain the above copyright 44 1.1 christos * notice, this list of conditions and the following disclaimer. 45 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 46 1.1 christos * notice, this list of conditions and the following disclaimer in the 47 1.1 christos * documentation and/or other materials provided with the distribution. 48 1.1 christos * 3. All advertising materials mentioning features or use of this software 49 1.1 christos * must display the following acknowledgement: 50 1.1 christos * This product includes software developed by Charles Hannum. 51 1.1 christos * 4. The name of the author may not be used to endorse or promote products 52 1.1 christos * derived from this software without specific prior written permission. 53 1.1 christos * 54 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 55 1.1 christos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 56 1.1 christos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 57 1.1 christos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 58 1.1 christos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 59 1.1 christos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 60 1.1 christos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 61 1.1 christos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 62 1.1 christos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 63 1.1 christos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 64 1.1 christos */ 65 1.1 christos 66 1.1 christos /* 67 1.1 christos * NOTE: This driver has been tested in TCOM "UNIX mode" with base address 68 1.1 christos * set to 0x100 or 0x200 and baud rate jumpers to "normal". This code 69 1.1 christos * does NOT know about the 2x and 4x baud rates available on TCOM cards. 70 1.1 christos */ 71 1.2 lukem 72 1.2 lukem #include <sys/cdefs.h> 73 1.22 thorpej __KERNEL_RCSID(0, "$NetBSD: tcom.c,v 1.22 2021/08/07 16:19:12 thorpej Exp $"); 74 1.1 christos 75 1.1 christos #include <sys/param.h> 76 1.1 christos #include <sys/systm.h> 77 1.1 christos #include <sys/device.h> 78 1.1 christos #include <sys/termios.h> 79 1.1 christos 80 1.14 ad #include <sys/bus.h> 81 1.14 ad #include <sys/intr.h> 82 1.1 christos 83 1.1 christos #include <dev/ic/comreg.h> 84 1.1 christos #include <dev/ic/comvar.h> 85 1.1 christos 86 1.1 christos #include <dev/isa/isavar.h> 87 1.1 christos #include <dev/isa/com_multi.h> 88 1.1 christos 89 1.1 christos #define NSLAVES 8 /* TCOM cards have 4 or 8 UARTs */ 90 1.1 christos #define STATUS_OFFSET 0x40 /* offset from board base address */ 91 1.1 christos #define STATUS_SIZE 8 /* 8 bytes reserved for irq status */ 92 1.1 christos 93 1.1 christos struct tcom_softc { 94 1.17 martin device_t sc_dev; 95 1.1 christos void *sc_ih; 96 1.1 christos 97 1.1 christos bus_space_tag_t sc_iot; 98 1.1 christos int sc_iobase; 99 1.1 christos 100 1.1 christos int sc_alive; /* mask of slave units attached */ 101 1.17 martin void *sc_slaves[NSLAVES]; /* com device softc pointers */ 102 1.1 christos bus_space_handle_t sc_slaveioh[NSLAVES]; 103 1.1 christos bus_space_handle_t sc_statusioh; 104 1.1 christos }; 105 1.1 christos 106 1.19 cegger int tcomprobe(device_t, cfdata_t, void *); 107 1.19 cegger void tcomattach(device_t, device_t, void *); 108 1.10 perry int tcomintr(void *); 109 1.1 christos 110 1.17 martin CFATTACH_DECL_NEW(tcom, sizeof(struct tcom_softc), 111 1.6 thorpej tcomprobe, tcomattach, NULL, NULL); 112 1.1 christos 113 1.1 christos int 114 1.19 cegger tcomprobe(device_t parent, cfdata_t self, void *aux) 115 1.1 christos { 116 1.1 christos struct isa_attach_args *ia = aux; 117 1.1 christos bus_space_tag_t iot = ia->ia_iot; 118 1.1 christos bus_space_handle_t ioh; 119 1.3 thorpej int i, iobase, rv = 1; 120 1.1 christos 121 1.1 christos /* 122 1.1 christos * Do the normal com probe for the first UART and assume 123 1.1 christos * its presence, and the ability to map the other UARTS, 124 1.1 christos * means there is a multiport board there. 125 1.1 christos * XXX Needs more robustness. 126 1.1 christos */ 127 1.1 christos 128 1.3 thorpej if (ia->ia_nio < 1) 129 1.3 thorpej return (0); 130 1.3 thorpej if (ia->ia_nirq < 1) 131 1.3 thorpej return (1); 132 1.3 thorpej 133 1.3 thorpej if (ISA_DIRECT_CONFIG(ia)) 134 1.3 thorpej return (0); 135 1.3 thorpej 136 1.1 christos /* Disallow wildcarded i/o address. */ 137 1.9 drochner if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 138 1.3 thorpej return (0); 139 1.9 drochner if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ) 140 1.1 christos return (0); 141 1.1 christos 142 1.1 christos /* if the first port is in use as console, then it. */ 143 1.3 thorpej if (com_is_console(iot, ia->ia_io[0].ir_addr, 0)) 144 1.1 christos goto checkmappings; 145 1.1 christos 146 1.3 thorpej if (bus_space_map(iot, ia->ia_io[0].ir_addr, COM_NPORTS, 0, &ioh)) { 147 1.1 christos rv = 0; 148 1.1 christos goto out; 149 1.1 christos } 150 1.1 christos rv = comprobe1(iot, ioh); 151 1.1 christos bus_space_unmap(iot, ioh, COM_NPORTS); 152 1.1 christos if (rv == 0) 153 1.1 christos goto out; 154 1.1 christos 155 1.1 christos checkmappings: 156 1.3 thorpej for (i = 1, iobase = ia->ia_io[0].ir_addr; i < NSLAVES; i++) { 157 1.1 christos iobase += COM_NPORTS; 158 1.1 christos 159 1.1 christos if (com_is_console(iot, iobase, 0)) 160 1.1 christos continue; 161 1.1 christos 162 1.1 christos if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) { 163 1.1 christos rv = 0; 164 1.1 christos goto out; 165 1.1 christos } 166 1.1 christos bus_space_unmap(iot, ioh, COM_NPORTS); 167 1.1 christos } 168 1.1 christos 169 1.1 christos out: 170 1.3 thorpej if (rv) { 171 1.3 thorpej ia->ia_nio = 1; 172 1.3 thorpej ia->ia_io[0].ir_size = NSLAVES * COM_NPORTS; 173 1.3 thorpej 174 1.3 thorpej ia->ia_nirq = 1; 175 1.3 thorpej 176 1.3 thorpej ia->ia_niomem = 0; 177 1.3 thorpej ia->ia_ndrq = 0; 178 1.3 thorpej } 179 1.1 christos return (rv); 180 1.1 christos } 181 1.1 christos 182 1.1 christos void 183 1.19 cegger tcomattach(device_t parent, device_t self, void *aux) 184 1.1 christos { 185 1.17 martin struct tcom_softc *sc = device_private(self); 186 1.1 christos struct isa_attach_args *ia = aux; 187 1.1 christos struct commulti_attach_args ca; 188 1.1 christos bus_space_tag_t iot = ia->ia_iot; 189 1.1 christos int i, iobase; 190 1.17 martin device_t slave; 191 1.1 christos 192 1.1 christos printf("\n"); 193 1.1 christos 194 1.17 martin sc->sc_dev = self; 195 1.1 christos sc->sc_iot = ia->ia_iot; 196 1.3 thorpej sc->sc_iobase = ia->ia_io[0].ir_addr; 197 1.1 christos 198 1.1 christos for (i = 0; i < NSLAVES; i++) { 199 1.1 christos iobase = sc->sc_iobase + i * COM_NPORTS; 200 1.1 christos if (!com_is_console(iot, iobase, &sc->sc_slaveioh[i]) && 201 1.1 christos bus_space_map(iot, iobase, COM_NPORTS, 0, 202 1.1 christos &sc->sc_slaveioh[i])) { 203 1.20 msaitoh aprint_error_dev(sc->sc_dev, 204 1.20 msaitoh "can't map i/o space for slave %d\n", i); 205 1.1 christos return; 206 1.1 christos } 207 1.1 christos } 208 1.1 christos 209 1.3 thorpej if (bus_space_map(iot, sc->sc_iobase + STATUS_OFFSET, STATUS_SIZE, 0, 210 1.3 thorpej &sc->sc_statusioh)) { 211 1.17 martin aprint_error_dev(sc->sc_dev, "can't map status space\n"); 212 1.1 christos return; 213 1.1 christos } 214 1.1 christos 215 1.1 christos for (i = 0; i < NSLAVES; i++) { 216 1.1 christos ca.ca_slave = i; 217 1.1 christos ca.ca_iot = sc->sc_iot; 218 1.1 christos ca.ca_ioh = sc->sc_slaveioh[i]; 219 1.1 christos ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS; 220 1.1 christos ca.ca_noien = 0; 221 1.1 christos 222 1.22 thorpej slave = config_found(self, &ca, commultiprint, CFARGS_NONE); 223 1.17 martin if (slave != NULL) { 224 1.1 christos sc->sc_alive |= 1 << i; 225 1.17 martin sc->sc_slaves[i] = device_private(slave); 226 1.17 martin } 227 1.1 christos } 228 1.1 christos 229 1.3 thorpej sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq, 230 1.3 thorpej IST_EDGE, IPL_SERIAL, tcomintr, sc); 231 1.1 christos } 232 1.1 christos 233 1.1 christos int 234 1.18 dsl tcomintr(void *arg) 235 1.1 christos { 236 1.1 christos struct tcom_softc *sc = arg; 237 1.1 christos bus_space_tag_t iot = sc->sc_iot; 238 1.1 christos int alive = sc->sc_alive; 239 1.1 christos int bits; 240 1.1 christos 241 1.1 christos bits = ~bus_space_read_1(iot, sc->sc_statusioh, 0) & alive; 242 1.1 christos if (bits == 0) 243 1.1 christos return (0); 244 1.1 christos 245 1.1 christos for (;;) { 246 1.1 christos #define TRY(n) \ 247 1.1 christos if (bits & (1 << (n))) \ 248 1.1 christos comintr(sc->sc_slaves[n]); 249 1.1 christos TRY(0); 250 1.1 christos TRY(1); 251 1.1 christos TRY(2); 252 1.1 christos TRY(3); 253 1.1 christos TRY(4); 254 1.1 christos TRY(5); 255 1.1 christos TRY(6); 256 1.1 christos TRY(7); 257 1.1 christos #undef TRY 258 1.1 christos bits = ~bus_space_read_1(iot, sc->sc_statusioh, 0) & alive; 259 1.1 christos if (bits == 0) 260 1.1 christos return (1); 261 1.1 christos } 262 1.1 christos } 263