1 /* $OpenBSD: com_pcmcia.c,v 1.54 2014/09/14 14:17:25 jsg Exp $ */ 2 /* $NetBSD: com_pcmcia.c,v 1.15 1998/08/22 17:47:58 msaitoh Exp $ */ 3 4 /* 5 * Copyright (c) 1997 - 1999, Jason Downs. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name(s) of the author(s) nor the name OpenBSD 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS 20 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 /*- 32 * Copyright (c) 1998 The NetBSD Foundation, Inc. 33 * All rights reserved. 34 * 35 * This code is derived from software contributed to The NetBSD Foundation 36 * by Charles M. Hannum. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 48 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 49 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 51 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 57 * POSSIBILITY OF SUCH DAMAGE. 58 */ 59 60 /*- 61 * Copyright (c) 1991 The Regents of the University of California. 62 * All rights reserved. 63 * 64 * Redistribution and use in source and binary forms, with or without 65 * modification, are permitted provided that the following conditions 66 * are met: 67 * 1. Redistributions of source code must retain the above copyright 68 * notice, this list of conditions and the following disclaimer. 69 * 2. Redistributions in binary form must reproduce the above copyright 70 * notice, this list of conditions and the following disclaimer in the 71 * documentation and/or other materials provided with the distribution. 72 * 3. Neither the name of the University nor the names of its contributors 73 * may be used to endorse or promote products derived from this software 74 * without specific prior written permission. 75 * 76 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 77 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 78 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 79 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 80 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 81 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 82 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 83 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 84 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 85 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 86 * SUCH DAMAGE. 87 * 88 * @(#)com.c 7.5 (Berkeley) 5/16/91 89 */ 90 91 #include <sys/param.h> 92 #include <sys/systm.h> 93 #include <sys/ioctl.h> 94 #include <sys/selinfo.h> 95 #include <sys/tty.h> 96 #include <sys/conf.h> 97 #include <sys/file.h> 98 #include <sys/uio.h> 99 #include <sys/kernel.h> 100 #include <sys/syslog.h> 101 #include <sys/types.h> 102 #include <sys/device.h> 103 104 #include <machine/intr.h> 105 #include <machine/bus.h> 106 107 #include <dev/pcmcia/pcmciavar.h> 108 #include <dev/pcmcia/pcmciareg.h> 109 #include <dev/pcmcia/pcmciadevs.h> 110 111 #include "com.h" 112 113 #include <dev/ic/comreg.h> 114 #include <dev/ic/comvar.h> 115 #include <dev/ic/ns16550reg.h> 116 117 #include <dev/isa/isareg.h> 118 119 #define com_lcr com_cfcr 120 121 /* Devices that we need to match by CIS strings */ 122 struct com_pcmcia_product { 123 char *cis1_info[4]; 124 } com_pcmcia_prod[] = { 125 { PCMCIA_CIS_MEGAHERTZ_XJ2288 }, 126 { PCMCIA_CIS_NOVATEL_NRM6831 }, 127 }; 128 129 int com_pcmcia_match(struct device *, void *, void *); 130 void com_pcmcia_attach(struct device *, struct device *, void *); 131 int com_pcmcia_detach(struct device *, int); 132 void com_pcmcia_cleanup(void *); 133 int com_pcmcia_activate(struct device *, int); 134 135 int com_pcmcia_enable(struct com_softc *); 136 void com_pcmcia_disable(struct com_softc *); 137 int com_pcmcia_enable1(struct com_softc *); 138 void com_pcmcia_disable1(struct com_softc *); 139 140 struct com_pcmcia_softc { 141 struct com_softc sc_com; /* real "com" softc */ 142 143 /* PCMCIA-specific goo */ 144 struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */ 145 int sc_io_window; /* our i/o window */ 146 struct pcmcia_function *sc_pf; /* our PCMCIA function */ 147 void *sc_ih; /* interrupt handler */ 148 }; 149 150 struct cfattach com_pcmcia_ca = { 151 sizeof(struct com_pcmcia_softc), com_pcmcia_match, com_pcmcia_attach, 152 com_pcmcia_detach, com_pcmcia_activate 153 }; 154 155 int 156 com_pcmcia_match(parent, match, aux) 157 struct device *parent; 158 void *match, *aux; 159 { 160 struct pcmcia_attach_args *pa = aux; 161 struct pcmcia_config_entry *cfe; 162 int i, j, comportmask; 163 164 /* 1. Does it claim to be a serial device? */ 165 if (pa->pf->function == PCMCIA_FUNCTION_SERIAL) 166 return 1; 167 168 /* 2. Does it have all four 'standard' port ranges? */ 169 comportmask = 0; 170 SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) { 171 switch (cfe->iospace[0].start) { 172 case IO_COM1: 173 comportmask |= 1; 174 break; 175 case IO_COM2: 176 comportmask |= 2; 177 break; 178 case IO_COM3: 179 comportmask |= 4; 180 break; 181 case IO_COM4: 182 comportmask |= 8; 183 break; 184 } 185 } 186 187 if (comportmask == 15) 188 return 1; 189 190 /* 3. Is this a card we know about? */ 191 for (i = 0; i < nitems(com_pcmcia_prod); i++) { 192 for (j = 0; j < 4; j++) 193 if (com_pcmcia_prod[i].cis1_info[j] && 194 pa->card->cis1_info[j] && 195 strcmp(pa->card->cis1_info[j], 196 com_pcmcia_prod[i].cis1_info[j])) 197 break; 198 if (j == 4) 199 return 1; 200 } 201 202 return 0; 203 } 204 205 int 206 com_pcmcia_activate(dev, act) 207 struct device *dev; 208 int act; 209 { 210 struct com_pcmcia_softc *sc = (void *) dev; 211 212 switch (act) { 213 case DVACT_SUSPEND: 214 if (sc->sc_ih) 215 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 216 sc->sc_ih = NULL; 217 pcmcia_function_disable(sc->sc_pf); 218 break; 219 case DVACT_RESUME: 220 pcmcia_function_enable(sc->sc_pf); 221 sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_TTY, 222 comintr, sc, sc->sc_com.sc_dev.dv_xname); 223 com_resume(&sc->sc_com); 224 break; 225 case DVACT_DEACTIVATE: 226 if (sc->sc_ih) 227 pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 228 sc->sc_ih = NULL; 229 pcmcia_function_disable(sc->sc_pf); 230 break; 231 } 232 return (0); 233 } 234 235 void 236 com_pcmcia_attach(parent, self, aux) 237 struct device *parent, *self; 238 void *aux; 239 { 240 struct com_pcmcia_softc *psc = (void *) self; 241 struct com_softc *sc = &psc->sc_com; 242 struct pcmcia_attach_args *pa = aux; 243 struct pcmcia_config_entry *cfe; 244 const char *intrstr; 245 int autoalloc = 0; 246 247 psc->sc_pf = pa->pf; 248 249 retry: 250 /* find a cfe we can use */ 251 252 for (cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); cfe; 253 cfe = SIMPLEQ_NEXT(cfe, cfe_list)) { 254 #if 0 255 /* 256 * Some modem cards (e.g. Xircom CM33) also have 257 * mem space. Don't bother with this check. 258 */ 259 if (cfe->num_memspace != 0) 260 continue; 261 #endif 262 263 if (cfe->num_iospace != 1) 264 continue; 265 266 if (!pcmcia_io_alloc(pa->pf, 267 autoalloc ? 0 : cfe->iospace[0].start, 268 cfe->iospace[0].length, COM_NPORTS, &psc->sc_pcioh)) { 269 goto found; 270 } 271 } 272 if (autoalloc == 0) { 273 autoalloc = 1; 274 goto retry; 275 } else if (!cfe) { 276 printf(": can't allocate i/o space\n"); 277 return; 278 } 279 280 found: 281 sc->sc_iot = psc->sc_pcioh.iot; 282 sc->sc_ioh = psc->sc_pcioh.ioh; 283 284 /* Enable the card. */ 285 pcmcia_function_init(pa->pf, cfe); 286 if (com_pcmcia_enable1(sc)) 287 printf(": function enable failed\n"); 288 289 sc->enabled = 1; 290 291 /* map in the io space */ 292 293 if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ? 294 PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, psc->sc_pcioh.size, 295 &psc->sc_pcioh, &psc->sc_io_window)) { 296 printf(": can't map i/o space\n"); 297 return; 298 } 299 300 printf(" port 0x%lx/%lu", psc->sc_pcioh.addr, 301 (u_long)psc->sc_pcioh.size); 302 303 sc->sc_iobase = -1; 304 sc->enable = com_pcmcia_enable; 305 sc->disable = com_pcmcia_disable; 306 sc->sc_frequency = COM_FREQ; 307 308 sc->sc_hwflags = 0; 309 sc->sc_swflags = 0; 310 311 if (psc->sc_pf->sc->card.manufacturer == PCMCIA_VENDOR_AUDIOVOX && 312 psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_AUDIOVOX_RTM8000) 313 sc->sc_fifolen = 16; 314 315 com_attach_subr(sc); 316 317 /* establish the interrupt. */ 318 psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_TTY, comintr, sc, 319 sc->sc_dev.dv_xname); 320 intrstr = pcmcia_intr_string(psc->sc_pf, psc->sc_ih); 321 if (*intrstr) 322 printf(", %s", intrstr); 323 324 #ifdef notyet 325 sc->enabled = 0; 326 327 com_pcmcia_disable1(sc); 328 #endif 329 } 330 331 int 332 com_pcmcia_detach(dev, flags) 333 struct device *dev; 334 int flags; 335 { 336 struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *)dev; 337 int error; 338 339 /* Release all resources. */ 340 error = com_detach(dev, flags); 341 if (error) 342 return (error); 343 344 pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window); 345 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh); 346 347 return (0); 348 } 349 350 int 351 com_pcmcia_enable(sc) 352 struct com_softc *sc; 353 { 354 struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc; 355 struct pcmcia_function *pf = psc->sc_pf; 356 357 /* establish the interrupt. */ 358 psc->sc_ih = pcmcia_intr_establish(pf, IPL_TTY, comintr, sc, 359 sc->sc_dev.dv_xname); 360 if (psc->sc_ih == NULL) { 361 printf("%s: couldn't establish interrupt\n", 362 sc->sc_dev.dv_xname); 363 return (1); 364 } 365 return com_pcmcia_enable1(sc); 366 } 367 368 int 369 com_pcmcia_enable1(sc) 370 struct com_softc *sc; 371 { 372 struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc; 373 struct pcmcia_function *pf = psc->sc_pf; 374 int ret; 375 376 if ((ret = pcmcia_function_enable(pf))) 377 return(ret); 378 379 if ((psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) || 380 (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556) || 381 (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556B)) { 382 int reg; 383 384 /* turn off the ethernet-disable bit */ 385 386 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION); 387 if (reg & 0x08) { 388 reg &= ~0x08; 389 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg); 390 } 391 } 392 393 return(ret); 394 } 395 396 void 397 com_pcmcia_disable(sc) 398 struct com_softc *sc; 399 { 400 struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc; 401 402 pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); 403 com_pcmcia_disable1(sc); 404 } 405 406 void 407 com_pcmcia_disable1(sc) 408 struct com_softc *sc; 409 { 410 struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc; 411 412 pcmcia_function_disable(psc->sc_pf); 413 } 414