1 1.41 thorpej /* $NetBSD: com_isa.c,v 1.41 2018/12/08 17:46:13 thorpej Exp $ */ 2 1.12 mycroft 3 1.12 mycroft /*- 4 1.12 mycroft * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.12 mycroft * All rights reserved. 6 1.12 mycroft * 7 1.12 mycroft * This code is derived from software contributed to The NetBSD Foundation 8 1.12 mycroft * by Charles M. Hannum. 9 1.12 mycroft * 10 1.12 mycroft * Redistribution and use in source and binary forms, with or without 11 1.12 mycroft * modification, are permitted provided that the following conditions 12 1.12 mycroft * are met: 13 1.12 mycroft * 1. Redistributions of source code must retain the above copyright 14 1.12 mycroft * notice, this list of conditions and the following disclaimer. 15 1.12 mycroft * 2. Redistributions in binary form must reproduce the above copyright 16 1.12 mycroft * notice, this list of conditions and the following disclaimer in the 17 1.12 mycroft * documentation and/or other materials provided with the distribution. 18 1.12 mycroft * 19 1.12 mycroft * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.12 mycroft * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.12 mycroft * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.12 mycroft * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.12 mycroft * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.12 mycroft * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.12 mycroft * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.12 mycroft * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.12 mycroft * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.12 mycroft * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.12 mycroft * POSSIBILITY OF SUCH DAMAGE. 30 1.12 mycroft */ 31 1.1 mycroft 32 1.1 mycroft /*- 33 1.1 mycroft * Copyright (c) 1991 The Regents of the University of California. 34 1.1 mycroft * All rights reserved. 35 1.1 mycroft * 36 1.1 mycroft * Redistribution and use in source and binary forms, with or without 37 1.1 mycroft * modification, are permitted provided that the following conditions 38 1.1 mycroft * are met: 39 1.1 mycroft * 1. Redistributions of source code must retain the above copyright 40 1.1 mycroft * notice, this list of conditions and the following disclaimer. 41 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright 42 1.1 mycroft * notice, this list of conditions and the following disclaimer in the 43 1.1 mycroft * documentation and/or other materials provided with the distribution. 44 1.21 agc * 3. Neither the name of the University nor the names of its contributors 45 1.1 mycroft * may be used to endorse or promote products derived from this software 46 1.1 mycroft * without specific prior written permission. 47 1.1 mycroft * 48 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 49 1.1 mycroft * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 1.1 mycroft * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 1.1 mycroft * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 52 1.1 mycroft * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 1.1 mycroft * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 54 1.1 mycroft * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 55 1.1 mycroft * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 56 1.1 mycroft * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 1.1 mycroft * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 1.1 mycroft * SUCH DAMAGE. 59 1.1 mycroft * 60 1.1 mycroft * @(#)com.c 7.5 (Berkeley) 5/16/91 61 1.1 mycroft */ 62 1.15 lukem 63 1.15 lukem #include <sys/cdefs.h> 64 1.41 thorpej __KERNEL_RCSID(0, "$NetBSD: com_isa.c,v 1.41 2018/12/08 17:46:13 thorpej Exp $"); 65 1.1 mycroft 66 1.1 mycroft #include <sys/param.h> 67 1.1 mycroft #include <sys/systm.h> 68 1.1 mycroft #include <sys/ioctl.h> 69 1.1 mycroft #include <sys/select.h> 70 1.1 mycroft #include <sys/tty.h> 71 1.1 mycroft #include <sys/proc.h> 72 1.1 mycroft #include <sys/file.h> 73 1.1 mycroft #include <sys/uio.h> 74 1.1 mycroft #include <sys/kernel.h> 75 1.1 mycroft #include <sys/syslog.h> 76 1.1 mycroft #include <sys/device.h> 77 1.1 mycroft 78 1.29 ad #include <sys/intr.h> 79 1.29 ad #include <sys/bus.h> 80 1.1 mycroft 81 1.8 thorpej #include <dev/ic/comreg.h> 82 1.8 thorpej #include <dev/ic/comvar.h> 83 1.25 gdamore #ifdef COM_HAYESP 84 1.25 gdamore #include <dev/ic/hayespreg.h> 85 1.25 gdamore #endif 86 1.8 thorpej 87 1.1 mycroft #include <dev/isa/isavar.h> 88 1.1 mycroft 89 1.7 thorpej struct com_isa_softc { 90 1.7 thorpej struct com_softc sc_com; /* real "com" softc */ 91 1.7 thorpej 92 1.7 thorpej /* ISA-specific goo. */ 93 1.32 dyoung isa_chipset_tag_t sc_ic; 94 1.7 thorpej void *sc_ih; /* interrupt handler */ 95 1.32 dyoung int sc_irq; 96 1.7 thorpej }; 97 1.7 thorpej 98 1.39 dyoung static bool com_isa_suspend(device_t, const pmf_qual_t *); 99 1.39 dyoung static bool com_isa_resume(device_t, const pmf_qual_t *); 100 1.32 dyoung 101 1.33 cube int com_isa_probe(device_t, cfdata_t , void *); 102 1.31 dyoung void com_isa_attach(device_t, device_t, void *); 103 1.30 dyoung static int com_isa_detach(device_t, int); 104 1.25 gdamore #ifdef COM_HAYESP 105 1.25 gdamore int com_isa_isHAYESP(bus_space_handle_t, struct com_softc *); 106 1.25 gdamore #endif 107 1.25 gdamore 108 1.1 mycroft 109 1.35 dyoung CFATTACH_DECL3_NEW(com_isa, sizeof(struct com_isa_softc), 110 1.36 dyoung com_isa_probe, com_isa_attach, com_isa_detach, NULL, 111 1.35 dyoung NULL, NULL, DVF_DETACH_SHUTDOWN); 112 1.1 mycroft 113 1.1 mycroft int 114 1.33 cube com_isa_probe(device_t parent, cfdata_t match, void *aux) 115 1.1 mycroft { 116 1.1 mycroft bus_space_tag_t iot; 117 1.1 mycroft bus_space_handle_t ioh; 118 1.1 mycroft int iobase; 119 1.1 mycroft int rv = 1; 120 1.1 mycroft struct isa_attach_args *ia = aux; 121 1.9 thorpej 122 1.17 thorpej if (ia->ia_nio < 1) 123 1.17 thorpej return (0); 124 1.17 thorpej if (ia->ia_nirq < 1) 125 1.17 thorpej return (0); 126 1.17 thorpej 127 1.17 thorpej if (ISA_DIRECT_CONFIG(ia)) 128 1.17 thorpej return (0); 129 1.17 thorpej 130 1.9 thorpej /* Disallow wildcarded i/o address. */ 131 1.22 drochner if (ia->ia_io[0].ir_addr == ISA_UNKNOWN_PORT) 132 1.17 thorpej return (0); 133 1.17 thorpej 134 1.17 thorpej /* Don't allow wildcarded IRQ. */ 135 1.22 drochner if (ia->ia_irq[0].ir_irq == ISA_UNKNOWN_IRQ) 136 1.9 thorpej return (0); 137 1.1 mycroft 138 1.1 mycroft iot = ia->ia_iot; 139 1.17 thorpej iobase = ia->ia_io[0].ir_addr; 140 1.1 mycroft 141 1.1 mycroft /* if it's in use as console, it's there. */ 142 1.5 drochner if (!com_is_console(iot, iobase, 0)) { 143 1.1 mycroft if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) { 144 1.1 mycroft return 0; 145 1.1 mycroft } 146 1.13 is rv = comprobe1(iot, ioh); 147 1.1 mycroft bus_space_unmap(iot, ioh, COM_NPORTS); 148 1.1 mycroft } 149 1.1 mycroft 150 1.1 mycroft if (rv) { 151 1.17 thorpej ia->ia_nio = 1; 152 1.17 thorpej ia->ia_io[0].ir_size = COM_NPORTS; 153 1.17 thorpej 154 1.17 thorpej ia->ia_nirq = 1; 155 1.17 thorpej 156 1.17 thorpej ia->ia_niomem = 0; 157 1.17 thorpej ia->ia_ndrq = 0; 158 1.1 mycroft } 159 1.1 mycroft return (rv); 160 1.1 mycroft } 161 1.1 mycroft 162 1.1 mycroft void 163 1.31 dyoung com_isa_attach(device_t parent, device_t self, void *aux) 164 1.1 mycroft { 165 1.31 dyoung struct com_isa_softc *isc = device_private(self); 166 1.7 thorpej struct com_softc *sc = &isc->sc_com; 167 1.1 mycroft int iobase, irq; 168 1.1 mycroft bus_space_tag_t iot; 169 1.25 gdamore bus_space_handle_t ioh; 170 1.1 mycroft struct isa_attach_args *ia = aux; 171 1.25 gdamore #ifdef COM_HAYESP 172 1.25 gdamore int hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 }; 173 1.25 gdamore int *hayespp; 174 1.25 gdamore #endif 175 1.1 mycroft 176 1.1 mycroft /* 177 1.1 mycroft * We're living on an isa. 178 1.1 mycroft */ 179 1.25 gdamore iobase = ia->ia_io[0].ir_addr; 180 1.25 gdamore iot = ia->ia_iot; 181 1.25 gdamore 182 1.25 gdamore if (!com_is_console(iot, iobase, &ioh) && 183 1.25 gdamore bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) { 184 1.10 thorpej printf(": can't map i/o space\n"); 185 1.10 thorpej return; 186 1.10 thorpej } 187 1.6 is 188 1.33 cube sc->sc_dev = self; 189 1.33 cube 190 1.41 thorpej com_init_regs(&sc->sc_regs, iot, ioh, iobase); 191 1.25 gdamore 192 1.6 is sc->sc_frequency = COM_FREQ; 193 1.17 thorpej irq = ia->ia_irq[0].ir_irq; 194 1.1 mycroft 195 1.25 gdamore #ifdef COM_HAYESP 196 1.25 gdamore for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) { 197 1.25 gdamore bus_space_handle_t hayespioh; 198 1.25 gdamore #define HAYESP_NPORTS 8 199 1.25 gdamore if (bus_space_map(iot, *hayespp, HAYESP_NPORTS, 0, &hayespioh)) 200 1.25 gdamore continue; 201 1.25 gdamore if (com_isa_isHAYESP(hayespioh, sc)) { 202 1.25 gdamore break; 203 1.25 gdamore } 204 1.25 gdamore bus_space_unmap(iot, hayespioh, HAYESP_NPORTS); 205 1.25 gdamore } 206 1.25 gdamore #endif 207 1.25 gdamore 208 1.1 mycroft com_attach_subr(sc); 209 1.1 mycroft 210 1.32 dyoung if (!pmf_device_register1(self, com_isa_suspend, com_isa_resume, 211 1.32 dyoung com_cleanup)) 212 1.30 dyoung aprint_error_dev(self, "couldn't establish power handler\n"); 213 1.30 dyoung 214 1.32 dyoung isc->sc_ic = ia->ia_ic; 215 1.32 dyoung isc->sc_irq = irq; 216 1.40 jdolecek isc->sc_ih = isa_intr_establish_xname(ia->ia_ic, irq, IST_EDGE, 217 1.40 jdolecek IPL_SERIAL, comintr, sc, device_xname(sc->sc_dev)); 218 1.32 dyoung } 219 1.32 dyoung 220 1.32 dyoung static bool 221 1.39 dyoung com_isa_suspend(device_t self, const pmf_qual_t *qual) 222 1.32 dyoung { 223 1.32 dyoung struct com_isa_softc *isc = device_private(self); 224 1.32 dyoung 225 1.38 dyoung if (!com_suspend(self, qual)) 226 1.32 dyoung return false; 227 1.32 dyoung 228 1.32 dyoung isa_intr_disestablish(isc->sc_ic, isc->sc_ih); 229 1.32 dyoung isc->sc_ih = NULL; 230 1.32 dyoung 231 1.32 dyoung return true; 232 1.32 dyoung } 233 1.32 dyoung 234 1.32 dyoung static bool 235 1.39 dyoung com_isa_resume(device_t self, const pmf_qual_t *qual) 236 1.32 dyoung { 237 1.32 dyoung struct com_isa_softc *isc = device_private(self); 238 1.32 dyoung struct com_softc *sc = &isc->sc_com; 239 1.1 mycroft 240 1.32 dyoung isc->sc_ih = isa_intr_establish(isc->sc_ic, isc->sc_irq, IST_EDGE, 241 1.32 dyoung IPL_SERIAL, comintr, sc); 242 1.32 dyoung 243 1.38 dyoung return com_resume(self, qual); 244 1.1 mycroft } 245 1.1 mycroft 246 1.30 dyoung static int 247 1.31 dyoung com_isa_detach(device_t self, int flags) 248 1.30 dyoung { 249 1.32 dyoung struct com_isa_softc *isc = device_private(self); 250 1.32 dyoung struct com_softc *sc = &isc->sc_com; 251 1.32 dyoung const struct com_regs *cr = &sc->sc_regs; 252 1.32 dyoung int rc; 253 1.32 dyoung 254 1.36 dyoung if ((rc = com_detach(self, flags)) != 0) 255 1.36 dyoung return rc; 256 1.36 dyoung 257 1.32 dyoung if (isc->sc_ih != NULL) 258 1.32 dyoung isa_intr_disestablish(isc->sc_ic, isc->sc_ih); 259 1.32 dyoung 260 1.30 dyoung pmf_device_deregister(self); 261 1.30 dyoung 262 1.32 dyoung com_cleanup(self, 0); 263 1.32 dyoung 264 1.32 dyoung #ifdef COM_HAYESP 265 1.32 dyoung if (sc->sc_type == COM_TYPE_HAYESP) 266 1.32 dyoung bus_space_unmap(cr->cr_iot, sc->sc_hayespioh, HAYESP_NPORTS); 267 1.32 dyoung #endif 268 1.32 dyoung bus_space_unmap(cr->cr_iot, cr->cr_ioh, COM_NPORTS); 269 1.32 dyoung 270 1.32 dyoung return 0; 271 1.30 dyoung } 272 1.30 dyoung 273 1.25 gdamore #ifdef COM_HAYESP 274 1.25 gdamore int 275 1.25 gdamore com_isa_isHAYESP(bus_space_handle_t hayespioh, struct com_softc *sc) 276 1.1 mycroft { 277 1.25 gdamore char val, dips; 278 1.25 gdamore int combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; 279 1.28 cube bus_space_tag_t iot = sc->sc_regs.cr_iot; 280 1.25 gdamore 281 1.25 gdamore /* 282 1.25 gdamore * Hayes ESP cards have two iobases. One is for compatibility with 283 1.25 gdamore * 16550 serial chips, and at the same ISA PC base addresses. The 284 1.25 gdamore * other is for ESP-specific enhanced features, and lies at a 285 1.25 gdamore * different addressing range entirely (0x140, 0x180, 0x280, or 0x300). 286 1.25 gdamore */ 287 1.25 gdamore 288 1.25 gdamore /* Test for ESP signature */ 289 1.25 gdamore if ((bus_space_read_1(iot, hayespioh, 0) & 0xf3) == 0) 290 1.25 gdamore return (0); 291 1.25 gdamore 292 1.25 gdamore /* 293 1.25 gdamore * ESP is present at ESP enhanced base address; unknown com port 294 1.25 gdamore */ 295 1.1 mycroft 296 1.25 gdamore /* Get the dip-switch configurations */ 297 1.25 gdamore bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS); 298 1.25 gdamore dips = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1); 299 1.25 gdamore 300 1.25 gdamore /* Determine which com port this ESP card services: bits 0,1 of */ 301 1.25 gdamore /* dips is the port # (0-3); combaselist[val] is the com_iobase */ 302 1.25 gdamore if (sc->sc_regs.cr_iobase != combaselist[dips & 0x03]) 303 1.25 gdamore return (0); 304 1.25 gdamore 305 1.25 gdamore printf(": ESP"); 306 1.25 gdamore 307 1.25 gdamore /* Check ESP Self Test bits. */ 308 1.25 gdamore /* Check for ESP version 2.0: bits 4,5,6 == 010 */ 309 1.25 gdamore bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETTEST); 310 1.25 gdamore val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1); /* Clear reg1 */ 311 1.25 gdamore val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS2); 312 1.25 gdamore if ((val & 0x70) < 0x20) { 313 1.25 gdamore printf("-old (%o)", val & 0x70); 314 1.25 gdamore /* we do not support the necessary features */ 315 1.25 gdamore return (0); 316 1.25 gdamore } 317 1.25 gdamore 318 1.25 gdamore /* Check for ability to emulate 16550: bit 8 == 1 */ 319 1.25 gdamore if ((dips & 0x80) == 0) { 320 1.25 gdamore printf(" slave"); 321 1.25 gdamore /* XXX Does slave really mean no 16550 support?? */ 322 1.25 gdamore return (0); 323 1.25 gdamore } 324 1.25 gdamore 325 1.25 gdamore /* 326 1.25 gdamore * If we made it this far, we are a full-featured ESP v2.0 (or 327 1.25 gdamore * better), at the correct com port address. 328 1.25 gdamore */ 329 1.25 gdamore sc->sc_type = COM_TYPE_HAYESP; 330 1.25 gdamore sc->sc_hayespioh = hayespioh; 331 1.25 gdamore sc->sc_fifolen = 1024; 332 1.25 gdamore sc->sc_prescaler = 0; /* set prescaler to x1. */ 333 1.25 gdamore printf(", 1024 byte fifo\n"); 334 1.25 gdamore return (1); 335 1.1 mycroft } 336 1.25 gdamore #endif 337