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