1 1.39 riastrad /* $NetBSD: xirc.c,v 1.39 2023/05/10 00:12:20 riastradh Exp $ */ 2 1.1 mycroft 3 1.1 mycroft /*- 4 1.1 mycroft * Copyright (c) 1999, 2000, 2004 The NetBSD Foundation, Inc. 5 1.1 mycroft * All rights reserved. 6 1.1 mycroft * 7 1.1 mycroft * This code is derived from software contributed to The NetBSD Foundation 8 1.1 mycroft * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.1 mycroft * NASA Ames Research Center and by Charles M. Hannum. 10 1.1 mycroft * 11 1.1 mycroft * Redistribution and use in source and binary forms, with or without 12 1.1 mycroft * modification, are permitted provided that the following conditions 13 1.1 mycroft * are met: 14 1.1 mycroft * 1. Redistributions of source code must retain the above copyright 15 1.1 mycroft * notice, this list of conditions and the following disclaimer. 16 1.1 mycroft * 2. Redistributions in binary form must reproduce the above copyright 17 1.1 mycroft * notice, this list of conditions and the following disclaimer in the 18 1.1 mycroft * documentation and/or other materials provided with the distribution. 19 1.1 mycroft * 20 1.1 mycroft * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 mycroft * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 mycroft * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 mycroft * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 mycroft * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 mycroft * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 mycroft * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 mycroft * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 mycroft * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 mycroft * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 mycroft * POSSIBILITY OF SUCH DAMAGE. 31 1.1 mycroft */ 32 1.1 mycroft 33 1.1 mycroft #include <sys/cdefs.h> 34 1.39 riastrad __KERNEL_RCSID(0, "$NetBSD: xirc.c,v 1.39 2023/05/10 00:12:20 riastradh Exp $"); 35 1.1 mycroft 36 1.13 perry #include "opt_inet.h" 37 1.1 mycroft 38 1.1 mycroft #include <sys/param.h> 39 1.1 mycroft #include <sys/systm.h> 40 1.1 mycroft #include <sys/mbuf.h> 41 1.1 mycroft #include <sys/socket.h> 42 1.1 mycroft #include <sys/ioctl.h> 43 1.1 mycroft #include <sys/errno.h> 44 1.1 mycroft #include <sys/syslog.h> 45 1.1 mycroft #include <sys/select.h> 46 1.1 mycroft #include <sys/tty.h> 47 1.1 mycroft #include <sys/device.h> 48 1.1 mycroft 49 1.13 perry #include <net/if.h> 50 1.13 perry #include <net/if_dl.h> 51 1.1 mycroft #include <net/if_ether.h> 52 1.13 perry #include <net/if_media.h> 53 1.34 msaitoh #include <net/bpf.h> 54 1.1 mycroft 55 1.1 mycroft #ifdef INET 56 1.1 mycroft #include <netinet/in.h> 57 1.1 mycroft #include <netinet/in_systm.h> 58 1.1 mycroft #include <netinet/in_var.h> 59 1.1 mycroft #include <netinet/ip.h> 60 1.1 mycroft #include <netinet/if_inarp.h> 61 1.1 mycroft #endif 62 1.13 perry 63 1.21 ad #include <sys/intr.h> 64 1.21 ad #include <sys/bus.h> 65 1.1 mycroft 66 1.1 mycroft #include <dev/pcmcia/pcmciareg.h> 67 1.1 mycroft #include <dev/pcmcia/pcmciavar.h> 68 1.1 mycroft #include <dev/pcmcia/pcmciadevs.h> 69 1.1 mycroft 70 1.1 mycroft #include "xirc.h" 71 1.1 mycroft 72 1.1 mycroft #if NCOM_XIRC > 0 73 1.1 mycroft #include <dev/ic/comreg.h> 74 1.1 mycroft #include <dev/ic/comvar.h> 75 1.1 mycroft #endif 76 1.1 mycroft 77 1.1 mycroft #if NXI_XIRC > 0 78 1.1 mycroft #include <dev/mii/mii.h> 79 1.1 mycroft #include <dev/mii/miivar.h> 80 1.1 mycroft 81 1.1 mycroft #include <dev/pcmcia/if_xivar.h> 82 1.1 mycroft #endif 83 1.1 mycroft #include <dev/pcmcia/if_xireg.h> 84 1.1 mycroft 85 1.1 mycroft struct xirc_softc { 86 1.31 dyoung device_t sc_dev; /* generic device glue */ 87 1.1 mycroft 88 1.1 mycroft struct pcmcia_function *sc_pf; /* our PCMCIA function */ 89 1.1 mycroft void *sc_ih; /* interrupt handle */ 90 1.1 mycroft 91 1.1 mycroft u_int16_t sc_id; 92 1.4 mycroft u_int8_t sc_mako_intmask; 93 1.1 mycroft int sc_chipset; 94 1.1 mycroft 95 1.1 mycroft /* 96 1.1 mycroft * Data for the Modem portion. 97 1.1 mycroft */ 98 1.29 cegger device_t sc_modem; 99 1.1 mycroft struct pcmcia_io_handle sc_modem_pcioh; 100 1.1 mycroft int sc_modem_io_window; 101 1.1 mycroft 102 1.1 mycroft /* 103 1.1 mycroft * Data for the Ethernet portion. 104 1.1 mycroft */ 105 1.29 cegger device_t sc_ethernet; 106 1.1 mycroft struct pcmcia_io_handle sc_ethernet_pcioh; 107 1.1 mycroft int sc_ethernet_io_window; 108 1.1 mycroft 109 1.1 mycroft int sc_flags; 110 1.1 mycroft #define XIRC_MODEM_MAPPED 0x01 111 1.1 mycroft #define XIRC_ETHERNET_MAPPED 0x02 112 1.1 mycroft #define XIRC_MODEM_ENABLED 0x04 113 1.1 mycroft #define XIRC_ETHERNET_ENABLED 0x08 114 1.1 mycroft #define XIRC_MODEM_ALLOCED 0x10 115 1.1 mycroft #define XIRC_ETHERNET_ALLOCED 0x20 116 1.1 mycroft }; 117 1.1 mycroft 118 1.29 cegger int xirc_match(device_t, cfdata_t, void *); 119 1.29 cegger void xirc_attach(device_t, device_t, void *); 120 1.29 cegger int xirc_detach(device_t, int); 121 1.30 dyoung void xirc_childdet(device_t, device_t); 122 1.1 mycroft 123 1.31 dyoung CFATTACH_DECL2_NEW(xirc, sizeof(struct xirc_softc), 124 1.31 dyoung xirc_match, xirc_attach, xirc_detach, NULL, NULL, xirc_childdet); 125 1.1 mycroft 126 1.12 perry int xirc_print(void *, const char *); 127 1.1 mycroft 128 1.12 perry int xirc_manfid_ciscallback(struct pcmcia_tuple *, void *); 129 1.1 mycroft struct pcmcia_config_entry * 130 1.12 perry xirc_mako_alloc(struct xirc_softc *); 131 1.1 mycroft struct pcmcia_config_entry * 132 1.12 perry xirc_dingo_alloc_modem(struct xirc_softc *); 133 1.1 mycroft struct pcmcia_config_entry * 134 1.12 perry xirc_dingo_alloc_ethernet(struct xirc_softc *); 135 1.1 mycroft 136 1.12 perry int xirc_enable(struct xirc_softc *, int, int); 137 1.12 perry void xirc_disable(struct xirc_softc *, int, int); 138 1.1 mycroft 139 1.12 perry int xirc_intr(void *); 140 1.1 mycroft 141 1.1 mycroft int 142 1.29 cegger xirc_match(device_t parent, cfdata_t match, 143 1.19 christos void *aux) 144 1.1 mycroft { 145 1.1 mycroft struct pcmcia_attach_args *pa = aux; 146 1.1 mycroft 147 1.1 mycroft /* XXX Toshiba, Accton */ 148 1.1 mycroft 149 1.1 mycroft if (pa->manufacturer == PCMCIA_VENDOR_COMPAQ2 && 150 1.1 mycroft pa->product == PCMCIA_PRODUCT_COMPAQ2_CPQ_10_100) 151 1.1 mycroft return (1); 152 1.1 mycroft 153 1.1 mycroft if (pa->manufacturer == PCMCIA_VENDOR_INTEL && 154 1.1 mycroft pa->product == PCMCIA_PRODUCT_INTEL_EEPRO100) 155 1.1 mycroft return (1); 156 1.1 mycroft 157 1.1 mycroft if (pa->manufacturer == PCMCIA_VENDOR_XIRCOM && 158 1.4 mycroft (pa->product & (XIMEDIA_ETHER << 8)) != 0) 159 1.1 mycroft return (2); 160 1.1 mycroft 161 1.1 mycroft return (0); 162 1.1 mycroft } 163 1.1 mycroft 164 1.1 mycroft void 165 1.29 cegger xirc_attach(device_t parent, device_t self, void *aux) 166 1.1 mycroft { 167 1.30 dyoung struct xirc_softc *sc = device_private(self); 168 1.1 mycroft struct pcmcia_attach_args *pa = aux; 169 1.1 mycroft struct pcmcia_config_entry *cfe; 170 1.1 mycroft int rv; 171 1.9 mycroft int error; 172 1.1 mycroft 173 1.31 dyoung sc->sc_dev = self; 174 1.31 dyoung 175 1.1 mycroft sc->sc_pf = pa->pf; 176 1.1 mycroft 177 1.1 mycroft pcmcia_socket_enable(parent); 178 1.1 mycroft rv = pcmcia_scan_cis(parent, xirc_manfid_ciscallback, &sc->sc_id); 179 1.1 mycroft pcmcia_socket_disable(parent); 180 1.1 mycroft if (!rv) { 181 1.23 cegger aprint_error_dev(self, "failed to find ID\n"); 182 1.1 mycroft return; 183 1.1 mycroft } 184 1.1 mycroft 185 1.1 mycroft switch (sc->sc_id & 0x100f) { 186 1.1 mycroft case 0x0001: /* CE */ 187 1.1 mycroft case 0x0002: /* CE2 */ 188 1.1 mycroft sc->sc_chipset = XI_CHIPSET_SCIPPER; 189 1.1 mycroft break; 190 1.1 mycroft case 0x0003: /* CE3 */ 191 1.1 mycroft sc->sc_chipset = XI_CHIPSET_MOHAWK; 192 1.1 mycroft break; 193 1.1 mycroft case 0x1001: 194 1.1 mycroft case 0x1002: 195 1.1 mycroft case 0x1003: 196 1.1 mycroft case 0x1004: 197 1.1 mycroft sc->sc_chipset = XI_CHIPSET_SCIPPER; 198 1.1 mycroft break; 199 1.1 mycroft case 0x1005: 200 1.1 mycroft sc->sc_chipset = XI_CHIPSET_MOHAWK; 201 1.1 mycroft break; 202 1.1 mycroft case 0x1006: 203 1.1 mycroft case 0x1007: 204 1.1 mycroft sc->sc_chipset = XI_CHIPSET_DINGO; 205 1.1 mycroft break; 206 1.1 mycroft default: 207 1.23 cegger aprint_error_dev(self, "unknown ID %04x\n", 208 1.1 mycroft sc->sc_id); 209 1.1 mycroft return; 210 1.1 mycroft } 211 1.1 mycroft 212 1.23 cegger aprint_normal_dev(self, "id=%04x\n", sc->sc_id); 213 1.1 mycroft 214 1.1 mycroft if (sc->sc_id & (XIMEDIA_MODEM << 8)) { 215 1.1 mycroft if (sc->sc_chipset >= XI_CHIPSET_DINGO) { 216 1.1 mycroft cfe = xirc_dingo_alloc_modem(sc); 217 1.5 mycroft if (cfe && sc->sc_id & (XIMEDIA_ETHER << 8)) { 218 1.5 mycroft if (!xirc_dingo_alloc_ethernet(sc)) { 219 1.5 mycroft pcmcia_io_free(pa->pf, 220 1.5 mycroft &sc->sc_modem_pcioh); 221 1.5 mycroft cfe = 0; 222 1.5 mycroft } 223 1.1 mycroft } 224 1.5 mycroft } else 225 1.4 mycroft cfe = xirc_mako_alloc(sc); 226 1.5 mycroft } else 227 1.1 mycroft cfe = xirc_dingo_alloc_ethernet(sc); 228 1.5 mycroft if (!cfe) { 229 1.23 cegger aprint_error_dev(self, "failed to allocate I/O space\n"); 230 1.5 mycroft goto fail; 231 1.1 mycroft } 232 1.1 mycroft 233 1.1 mycroft /* Enable the card. */ 234 1.1 mycroft pcmcia_function_init(pa->pf, cfe); 235 1.5 mycroft 236 1.7 mycroft if (sc->sc_id & (XIMEDIA_MODEM << 8)) { 237 1.7 mycroft if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_IO8, 238 1.7 mycroft &sc->sc_modem_pcioh, &sc->sc_modem_io_window)) { 239 1.23 cegger aprint_error_dev(self, "unable to map I/O space\n"); 240 1.7 mycroft goto fail; 241 1.7 mycroft } 242 1.7 mycroft sc->sc_flags |= XIRC_MODEM_MAPPED; 243 1.7 mycroft } 244 1.7 mycroft 245 1.7 mycroft if (sc->sc_id & (XIMEDIA_ETHER << 8)) { 246 1.7 mycroft if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_AUTO, 247 1.7 mycroft &sc->sc_ethernet_pcioh, &sc->sc_ethernet_io_window)) { 248 1.23 cegger aprint_error_dev(self, "unable to map I/O space\n"); 249 1.7 mycroft goto fail; 250 1.7 mycroft } 251 1.7 mycroft sc->sc_flags |= XIRC_ETHERNET_MAPPED; 252 1.7 mycroft } 253 1.7 mycroft 254 1.9 mycroft error = xirc_enable(sc, XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED, 255 1.9 mycroft sc->sc_id & (XIMEDIA_MODEM|XIMEDIA_ETHER)); 256 1.9 mycroft if (error) 257 1.1 mycroft goto fail; 258 1.1 mycroft 259 1.4 mycroft sc->sc_mako_intmask = 0xee; 260 1.4 mycroft 261 1.1 mycroft if (sc->sc_id & (XIMEDIA_MODEM << 8)) 262 1.14 christos /*XXXUNCONST*/ 263 1.37 thorpej sc->sc_modem = config_found(self, __UNCONST("com"), xirc_print, 264 1.38 thorpej CFARGS_NONE); 265 1.1 mycroft if (sc->sc_id & (XIMEDIA_ETHER << 8)) 266 1.14 christos /*XXXUNCONST*/ 267 1.14 christos sc->sc_ethernet = config_found(self, __UNCONST("xi"), 268 1.38 thorpej xirc_print, CFARGS_NONE); 269 1.1 mycroft 270 1.5 mycroft xirc_disable(sc, XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED, 271 1.5 mycroft sc->sc_id & (XIMEDIA_MODEM|XIMEDIA_ETHER)); 272 1.1 mycroft return; 273 1.1 mycroft 274 1.1 mycroft fail: 275 1.7 mycroft /* I/O spaces will be freed by detach. */ 276 1.7 mycroft ; 277 1.1 mycroft } 278 1.1 mycroft 279 1.1 mycroft int 280 1.26 dsl xirc_manfid_ciscallback(struct pcmcia_tuple *tuple, void *arg) 281 1.1 mycroft { 282 1.1 mycroft u_int16_t *id = arg; 283 1.1 mycroft 284 1.1 mycroft if (tuple->code != PCMCIA_CISTPL_MANFID) 285 1.1 mycroft return (0); 286 1.1 mycroft 287 1.1 mycroft if (tuple->length < 5) 288 1.1 mycroft return (0); 289 1.1 mycroft 290 1.1 mycroft *id = (pcmcia_tuple_read_1(tuple, 3) << 8) | 291 1.1 mycroft pcmcia_tuple_read_1(tuple, 4); 292 1.1 mycroft return (1); 293 1.1 mycroft } 294 1.1 mycroft 295 1.1 mycroft struct pcmcia_config_entry * 296 1.26 dsl xirc_mako_alloc(struct xirc_softc *sc) 297 1.1 mycroft { 298 1.1 mycroft struct pcmcia_config_entry *cfe; 299 1.1 mycroft 300 1.1 mycroft SIMPLEQ_FOREACH(cfe, &sc->sc_pf->cfe_head, cfe_list) { 301 1.1 mycroft if (cfe->num_iospace != 1) 302 1.1 mycroft continue; 303 1.1 mycroft 304 1.1 mycroft if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[0].start, 305 1.1 mycroft cfe->iospace[0].length, cfe->iospace[0].length, 306 1.1 mycroft &sc->sc_modem_pcioh)) 307 1.1 mycroft continue; 308 1.1 mycroft 309 1.8 mycroft cfe->iospace[1].start = cfe->iospace[0].start+8; 310 1.8 mycroft cfe->iospace[1].length = 18; 311 1.8 mycroft if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[1].start, 312 1.8 mycroft cfe->iospace[1].length, 0x20, 313 1.8 mycroft &sc->sc_ethernet_pcioh)) { 314 1.8 mycroft cfe->iospace[1].start = cfe->iospace[0].start-24; 315 1.8 mycroft if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[1].start, 316 1.8 mycroft cfe->iospace[1].length, 0x20, 317 1.8 mycroft &sc->sc_ethernet_pcioh)) 318 1.8 mycroft continue; 319 1.1 mycroft } 320 1.1 mycroft 321 1.1 mycroft /* Found one! */ 322 1.1 mycroft sc->sc_flags |= XIRC_MODEM_ALLOCED; 323 1.1 mycroft sc->sc_flags |= XIRC_ETHERNET_ALLOCED; 324 1.1 mycroft return (cfe); 325 1.1 mycroft } 326 1.1 mycroft 327 1.1 mycroft return (0); 328 1.1 mycroft } 329 1.1 mycroft 330 1.1 mycroft struct pcmcia_config_entry * 331 1.26 dsl xirc_dingo_alloc_modem(struct xirc_softc *sc) 332 1.1 mycroft { 333 1.1 mycroft struct pcmcia_config_entry *cfe; 334 1.1 mycroft 335 1.1 mycroft SIMPLEQ_FOREACH(cfe, &sc->sc_pf->cfe_head, cfe_list) { 336 1.1 mycroft if (cfe->num_iospace != 1) 337 1.1 mycroft continue; 338 1.1 mycroft 339 1.1 mycroft if (pcmcia_io_alloc(sc->sc_pf, cfe->iospace[0].start, 340 1.1 mycroft cfe->iospace[0].length, cfe->iospace[0].length, 341 1.1 mycroft &sc->sc_modem_pcioh)) 342 1.1 mycroft continue; 343 1.1 mycroft 344 1.1 mycroft /* Found one! */ 345 1.1 mycroft sc->sc_flags |= XIRC_MODEM_ALLOCED; 346 1.1 mycroft return (cfe); 347 1.1 mycroft } 348 1.1 mycroft 349 1.1 mycroft return (0); 350 1.1 mycroft } 351 1.1 mycroft 352 1.1 mycroft struct pcmcia_config_entry * 353 1.26 dsl xirc_dingo_alloc_ethernet(struct xirc_softc *sc) 354 1.1 mycroft { 355 1.1 mycroft struct pcmcia_config_entry *cfe; 356 1.1 mycroft bus_addr_t port; 357 1.1 mycroft 358 1.1 mycroft for (port = 0x300; port < 0x400; port += XI_IOSIZE) { 359 1.1 mycroft if (pcmcia_io_alloc(sc->sc_pf, port, 360 1.1 mycroft XI_IOSIZE, XI_IOSIZE, &sc->sc_ethernet_pcioh)) 361 1.1 mycroft continue; 362 1.1 mycroft 363 1.1 mycroft /* Found one for the ethernet! */ 364 1.1 mycroft sc->sc_flags |= XIRC_ETHERNET_ALLOCED; 365 1.1 mycroft cfe = SIMPLEQ_FIRST(&sc->sc_pf->cfe_head); 366 1.1 mycroft return (cfe); 367 1.1 mycroft } 368 1.1 mycroft 369 1.1 mycroft return (0); 370 1.1 mycroft } 371 1.1 mycroft 372 1.1 mycroft int 373 1.26 dsl xirc_print(void *aux, const char *pnp) 374 1.1 mycroft { 375 1.1 mycroft const char *name = aux; 376 1.1 mycroft 377 1.1 mycroft if (pnp) 378 1.1 mycroft aprint_normal("%s at %s(*)", name, pnp); 379 1.1 mycroft 380 1.1 mycroft return (UNCONF); 381 1.1 mycroft } 382 1.1 mycroft 383 1.30 dyoung void 384 1.30 dyoung xirc_childdet(device_t self, device_t child) 385 1.30 dyoung { 386 1.30 dyoung struct xirc_softc *sc = device_private(self); 387 1.30 dyoung 388 1.30 dyoung if (sc->sc_ethernet == child) 389 1.30 dyoung sc->sc_ethernet = NULL; 390 1.30 dyoung 391 1.30 dyoung if (sc->sc_modem == child) 392 1.30 dyoung sc->sc_modem = NULL; 393 1.30 dyoung } 394 1.30 dyoung 395 1.1 mycroft int 396 1.29 cegger xirc_detach(device_t self, int flags) 397 1.1 mycroft { 398 1.30 dyoung struct xirc_softc *sc = device_private(self); 399 1.39 riastrad int error; 400 1.1 mycroft 401 1.39 riastrad error = config_detach_children(self, flags); 402 1.39 riastrad if (error) 403 1.39 riastrad return error; 404 1.1 mycroft 405 1.1 mycroft /* Unmap our i/o windows. */ 406 1.1 mycroft if (sc->sc_flags & XIRC_ETHERNET_MAPPED) 407 1.1 mycroft pcmcia_io_unmap(sc->sc_pf, sc->sc_ethernet_io_window); 408 1.1 mycroft if (sc->sc_flags & XIRC_MODEM_MAPPED) 409 1.1 mycroft pcmcia_io_unmap(sc->sc_pf, sc->sc_modem_io_window); 410 1.1 mycroft 411 1.1 mycroft /* Free our i/o spaces. */ 412 1.1 mycroft if (sc->sc_flags & XIRC_ETHERNET_ALLOCED) 413 1.1 mycroft pcmcia_io_free(sc->sc_pf, &sc->sc_ethernet_pcioh); 414 1.1 mycroft if (sc->sc_flags & XIRC_MODEM_ALLOCED) 415 1.1 mycroft pcmcia_io_free(sc->sc_pf, &sc->sc_modem_pcioh); 416 1.1 mycroft sc->sc_flags = 0; 417 1.39 riastrad return 0; 418 1.1 mycroft } 419 1.1 mycroft 420 1.1 mycroft int 421 1.26 dsl xirc_intr(void *arg) 422 1.1 mycroft { 423 1.1 mycroft struct xirc_softc *sc = arg; 424 1.1 mycroft int rval = 0; 425 1.1 mycroft 426 1.1 mycroft #if NCOM_XIRC > 0 427 1.1 mycroft if (sc->sc_modem != NULL && 428 1.1 mycroft (sc->sc_flags & XIRC_MODEM_ENABLED) != 0) 429 1.25 drochner rval |= comintr(device_private(sc->sc_modem)); 430 1.1 mycroft #endif 431 1.1 mycroft 432 1.1 mycroft #if NXI_XIRC > 0 433 1.1 mycroft if (sc->sc_ethernet != NULL && 434 1.1 mycroft (sc->sc_flags & XIRC_ETHERNET_ENABLED) != 0) 435 1.25 drochner rval |= xi_intr(device_private(sc->sc_ethernet)); 436 1.1 mycroft #endif 437 1.1 mycroft 438 1.1 mycroft return (rval); 439 1.1 mycroft } 440 1.1 mycroft 441 1.1 mycroft int 442 1.27 dsl xirc_enable(struct xirc_softc *sc, int flag, int media) 443 1.1 mycroft { 444 1.9 mycroft int error; 445 1.1 mycroft 446 1.5 mycroft if ((sc->sc_flags & flag) == flag) { 447 1.31 dyoung printf("%s: already enabled\n", device_xname(sc->sc_dev)); 448 1.5 mycroft return (0); 449 1.1 mycroft } 450 1.1 mycroft 451 1.1 mycroft if ((sc->sc_flags & (XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED)) != 0) { 452 1.1 mycroft sc->sc_flags |= flag; 453 1.1 mycroft return (0); 454 1.1 mycroft } 455 1.1 mycroft 456 1.1 mycroft /* 457 1.1 mycroft * Establish our interrupt handler. 458 1.1 mycroft * 459 1.1 mycroft * XXX Note, we establish this at IPL_NET. This is suboptimal 460 1.1 mycroft * XXX the Modem portion, but is necessary to make the Ethernet 461 1.1 mycroft * XXX portion have the correct interrupt level semantics. 462 1.1 mycroft * 463 1.1 mycroft * XXX Eventually we should use the `enabled' bits in the 464 1.1 mycroft * XXX flags word to determine which level we should be at. 465 1.1 mycroft */ 466 1.9 mycroft sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_NET, xirc_intr, sc); 467 1.9 mycroft if (!sc->sc_ih) 468 1.2 mycroft return (EIO); 469 1.1 mycroft 470 1.9 mycroft error = pcmcia_function_enable(sc->sc_pf); 471 1.9 mycroft if (error) { 472 1.1 mycroft pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 473 1.10 mycroft sc->sc_ih = 0; 474 1.9 mycroft return (error); 475 1.1 mycroft } 476 1.1 mycroft 477 1.1 mycroft sc->sc_flags |= flag; 478 1.4 mycroft 479 1.4 mycroft if (sc->sc_chipset < XI_CHIPSET_DINGO && 480 1.4 mycroft sc->sc_id & (XIMEDIA_MODEM << 8)) { 481 1.4 mycroft sc->sc_mako_intmask |= media; 482 1.4 mycroft bus_space_write_1(sc->sc_ethernet_pcioh.iot, 483 1.4 mycroft sc->sc_ethernet_pcioh.ioh, 0x10, sc->sc_mako_intmask); 484 1.4 mycroft } 485 1.4 mycroft 486 1.1 mycroft return (0); 487 1.1 mycroft } 488 1.1 mycroft 489 1.1 mycroft void 490 1.27 dsl xirc_disable(struct xirc_softc *sc, int flag, int media) 491 1.1 mycroft { 492 1.1 mycroft 493 1.5 mycroft if ((sc->sc_flags & flag) == 0) { 494 1.31 dyoung printf("%s: already disabled\n", device_xname(sc->sc_dev)); 495 1.5 mycroft return; 496 1.5 mycroft } 497 1.5 mycroft 498 1.4 mycroft if (sc->sc_chipset < XI_CHIPSET_DINGO && 499 1.4 mycroft sc->sc_id & (XIMEDIA_MODEM << 8)) { 500 1.4 mycroft sc->sc_mako_intmask &= ~media; 501 1.4 mycroft bus_space_write_1(sc->sc_ethernet_pcioh.iot, 502 1.4 mycroft sc->sc_ethernet_pcioh.ioh, 0x10, sc->sc_mako_intmask); 503 1.4 mycroft } 504 1.4 mycroft 505 1.1 mycroft sc->sc_flags &= ~flag; 506 1.1 mycroft if ((sc->sc_flags & (XIRC_MODEM_ENABLED|XIRC_ETHERNET_ENABLED)) != 0) 507 1.1 mycroft return; 508 1.1 mycroft 509 1.6 mycroft pcmcia_function_disable(sc->sc_pf); 510 1.1 mycroft pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); 511 1.9 mycroft sc->sc_ih = 0; 512 1.1 mycroft } 513 1.1 mycroft 514 1.1 mycroft /****** Here begins the com attachment code. ******/ 515 1.1 mycroft 516 1.1 mycroft #if NCOM_XIRC > 0 517 1.22 cube int com_xirc_match(device_t, cfdata_t , void *); 518 1.22 cube void com_xirc_attach(device_t, device_t, void *); 519 1.22 cube int com_xirc_detach(device_t, int); 520 1.1 mycroft 521 1.1 mycroft /* No xirc-specific goo in the softc; it's all in the parent. */ 522 1.22 cube CFATTACH_DECL_NEW(com_xirc, sizeof(struct com_softc), 523 1.30 dyoung com_xirc_match, com_xirc_attach, com_detach, NULL); 524 1.1 mycroft 525 1.12 perry int com_xirc_enable(struct com_softc *); 526 1.12 perry void com_xirc_disable(struct com_softc *); 527 1.1 mycroft 528 1.1 mycroft int 529 1.22 cube com_xirc_match(device_t parent, cfdata_t match, void *aux) 530 1.1 mycroft { 531 1.1 mycroft extern struct cfdriver com_cd; 532 1.1 mycroft const char *name = aux; 533 1.1 mycroft 534 1.1 mycroft if (strcmp(name, com_cd.cd_name) == 0) 535 1.1 mycroft return (1); 536 1.1 mycroft 537 1.1 mycroft return (0); 538 1.1 mycroft } 539 1.1 mycroft 540 1.1 mycroft void 541 1.22 cube com_xirc_attach(device_t parent, device_t self, void *aux) 542 1.1 mycroft { 543 1.22 cube struct com_softc *sc = device_private(self); 544 1.22 cube struct xirc_softc *msc = device_private(parent); 545 1.22 cube 546 1.22 cube sc->sc_dev = self; 547 1.1 mycroft 548 1.1 mycroft aprint_normal("\n"); 549 1.1 mycroft 550 1.35 thorpej com_init_regs(&sc->sc_regs, 551 1.17 gdamore msc->sc_modem_pcioh.iot, 552 1.17 gdamore msc->sc_modem_pcioh.ioh, 553 1.17 gdamore -1); 554 1.1 mycroft 555 1.1 mycroft sc->enabled = 1; 556 1.1 mycroft 557 1.1 mycroft sc->sc_frequency = COM_FREQ; 558 1.1 mycroft 559 1.1 mycroft sc->enable = com_xirc_enable; 560 1.1 mycroft sc->disable = com_xirc_disable; 561 1.1 mycroft 562 1.22 cube aprint_normal("%s", device_xname(self)); 563 1.1 mycroft 564 1.1 mycroft com_attach_subr(sc); 565 1.1 mycroft 566 1.1 mycroft sc->enabled = 0; 567 1.1 mycroft } 568 1.1 mycroft 569 1.1 mycroft int 570 1.22 cube com_xirc_enable(struct com_softc *sc) 571 1.1 mycroft { 572 1.16 thorpej struct xirc_softc *msc = 573 1.22 cube device_private(device_parent(sc->sc_dev)); 574 1.1 mycroft 575 1.4 mycroft return (xirc_enable(msc, XIRC_MODEM_ENABLED, XIMEDIA_MODEM)); 576 1.1 mycroft } 577 1.1 mycroft 578 1.1 mycroft void 579 1.22 cube com_xirc_disable(struct com_softc *sc) 580 1.1 mycroft { 581 1.16 thorpej struct xirc_softc *msc = 582 1.22 cube device_private(device_parent(sc->sc_dev)); 583 1.1 mycroft 584 1.4 mycroft xirc_disable(msc, XIRC_MODEM_ENABLED, XIMEDIA_MODEM); 585 1.1 mycroft } 586 1.1 mycroft 587 1.1 mycroft #endif /* NCOM_XIRC > 0 */ 588 1.1 mycroft 589 1.1 mycroft /****** Here begins the xi attachment code. ******/ 590 1.1 mycroft 591 1.1 mycroft #if NXI_XIRC > 0 592 1.29 cegger int xi_xirc_match(device_t, cfdata_t, void *); 593 1.29 cegger void xi_xirc_attach(device_t, device_t, void *); 594 1.1 mycroft 595 1.1 mycroft /* No xirc-specific goo in the softc; it's all in the parent. */ 596 1.33 drochner CFATTACH_DECL_NEW(xi_xirc, sizeof(struct xi_softc), 597 1.30 dyoung xi_xirc_match, xi_xirc_attach, xi_detach, NULL); 598 1.1 mycroft 599 1.12 perry int xi_xirc_enable(struct xi_softc *); 600 1.12 perry void xi_xirc_disable(struct xi_softc *); 601 1.12 perry int xi_xirc_lan_nid_ciscallback(struct pcmcia_tuple *, void *); 602 1.1 mycroft 603 1.1 mycroft int 604 1.30 dyoung xi_xirc_match(device_t parent, cfdata_t match, void *aux) 605 1.1 mycroft { 606 1.1 mycroft extern struct cfdriver xi_cd; 607 1.1 mycroft const char *name = aux; 608 1.1 mycroft 609 1.1 mycroft if (strcmp(name, xi_cd.cd_name) == 0) 610 1.1 mycroft return (1); 611 1.1 mycroft 612 1.1 mycroft return (0); 613 1.1 mycroft } 614 1.1 mycroft 615 1.1 mycroft void 616 1.29 cegger xi_xirc_attach(device_t parent, device_t self, void *aux) 617 1.1 mycroft { 618 1.30 dyoung struct xi_softc *sc = device_private(self); 619 1.30 dyoung struct xirc_softc *msc = device_private(parent); 620 1.1 mycroft u_int8_t myla[ETHER_ADDR_LEN]; 621 1.1 mycroft 622 1.31 dyoung sc->sc_dev = self; 623 1.31 dyoung 624 1.1 mycroft aprint_normal("\n"); 625 1.1 mycroft 626 1.1 mycroft sc->sc_bst = msc->sc_ethernet_pcioh.iot; 627 1.1 mycroft sc->sc_bsh = msc->sc_ethernet_pcioh.ioh; 628 1.1 mycroft 629 1.1 mycroft sc->sc_chipset = msc->sc_chipset; 630 1.1 mycroft 631 1.1 mycroft sc->sc_enable = xi_xirc_enable; 632 1.1 mycroft sc->sc_disable = xi_xirc_disable; 633 1.1 mycroft 634 1.31 dyoung if (!pcmcia_scan_cis(device_parent(msc->sc_dev), 635 1.16 thorpej xi_xirc_lan_nid_ciscallback, myla)) { 636 1.23 cegger aprint_error_dev(self, "can't find MAC address\n"); 637 1.1 mycroft return; 638 1.1 mycroft } 639 1.1 mycroft 640 1.1 mycroft /* Perform generic initialization. */ 641 1.1 mycroft xi_attach(sc, myla); 642 1.1 mycroft } 643 1.1 mycroft 644 1.1 mycroft int 645 1.26 dsl xi_xirc_enable(struct xi_softc *sc) 646 1.1 mycroft { 647 1.31 dyoung struct xirc_softc *msc = device_private(device_parent(sc->sc_dev)); 648 1.1 mycroft 649 1.4 mycroft return (xirc_enable(msc, XIRC_ETHERNET_ENABLED, XIMEDIA_ETHER)); 650 1.1 mycroft } 651 1.1 mycroft 652 1.1 mycroft void 653 1.26 dsl xi_xirc_disable(struct xi_softc *sc) 654 1.1 mycroft { 655 1.31 dyoung struct xirc_softc *msc = device_private(device_parent(sc->sc_dev)); 656 1.1 mycroft 657 1.4 mycroft xirc_disable(msc, XIRC_ETHERNET_ENABLED, XIMEDIA_ETHER); 658 1.1 mycroft } 659 1.1 mycroft 660 1.1 mycroft int 661 1.26 dsl xi_xirc_lan_nid_ciscallback(struct pcmcia_tuple *tuple, void *arg) 662 1.1 mycroft { 663 1.1 mycroft u_int8_t *myla = arg; 664 1.1 mycroft int i; 665 1.1 mycroft 666 1.1 mycroft if (tuple->length < 2) 667 1.1 mycroft return (0); 668 1.1 mycroft 669 1.1 mycroft switch (tuple->code) { 670 1.1 mycroft case PCMCIA_CISTPL_FUNCE: 671 1.1 mycroft switch (pcmcia_tuple_read_1(tuple, 0)) { 672 1.1 mycroft case PCMCIA_TPLFE_TYPE_LAN_NID: 673 1.1 mycroft if (pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN) 674 1.1 mycroft return (0); 675 1.1 mycroft for (i = 0; i < ETHER_ADDR_LEN; i++) 676 1.1 mycroft myla[i] = pcmcia_tuple_read_1(tuple, i + 2); 677 1.1 mycroft return (1); 678 1.1 mycroft 679 1.1 mycroft case 0x02: 680 1.1 mycroft /* 681 1.1 mycroft * Not sure about this, I don't have a CE2 682 1.1 mycroft * that puts the ethernet addr here. 683 1.1 mycroft */ 684 1.1 mycroft if (pcmcia_tuple_read_1(tuple, 1) != 0x01 || 685 1.1 mycroft pcmcia_tuple_read_1(tuple, 2) != ETHER_ADDR_LEN) 686 1.1 mycroft return (0); 687 1.1 mycroft for (i = 0; i < ETHER_ADDR_LEN; i++) 688 1.1 mycroft myla[i] = pcmcia_tuple_read_1(tuple, i + 3); 689 1.1 mycroft return (1); 690 1.1 mycroft } 691 1.36 mrg break; 692 1.1 mycroft 693 1.1 mycroft case 0x89: 694 1.1 mycroft if (pcmcia_tuple_read_1(tuple, 0) != 0x04 || 695 1.1 mycroft pcmcia_tuple_read_1(tuple, 1) != ETHER_ADDR_LEN) 696 1.1 mycroft return (0); 697 1.1 mycroft for (i = 0; i < ETHER_ADDR_LEN; i++) 698 1.1 mycroft myla[i] = pcmcia_tuple_read_1(tuple, i + 2); 699 1.1 mycroft return (1); 700 1.1 mycroft } 701 1.1 mycroft 702 1.1 mycroft return (0); 703 1.1 mycroft } 704 1.1 mycroft 705 1.1 mycroft #endif /* NXI_XIRC > 0 */ 706