1 /* $OpenBSD: if_rl_cardbus.c,v 1.3 2002/10/12 01:09:44 krw Exp $ */ 2 /* $NetBSD: if_rl_cardbus.c,v 1.3.8.3 2001/11/14 19:14:02 nathanw Exp $ */ 3 4 /* 5 * Copyright (c) 2000 Masanori Kanaoka 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /* 32 * if_rl_cardbus.c: 33 * Cardbus specific routines for RealTek 8139 ethernet adapter. 34 * Tested for 35 * - elecom-Laneed LD-10/100CBA (Accton MPX5030) 36 * - MELCO LPC3-TX-CB (RealTek 8139) 37 */ 38 39 #include "bpfilter.h" 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/mbuf.h> 44 #include <sys/socket.h> 45 #include <sys/ioctl.h> 46 #include <sys/errno.h> 47 #include <sys/malloc.h> 48 #include <sys/kernel.h> 49 #include <sys/device.h> 50 51 #include <net/if.h> 52 #include <net/if_dl.h> 53 #include <net/if_types.h> 54 #include <net/if_media.h> 55 56 #include <machine/endian.h> 57 58 #if NBPFILTER > 0 59 #include <net/bpf.h> 60 #endif 61 62 #ifdef INET 63 #include <netinet/in.h> 64 #include <netinet/in_systm.h> 65 #include <netinet/in_var.h> 66 #include <netinet/ip.h> 67 #include <netinet/if_ether.h> 68 #endif 69 70 #include <machine/bus.h> 71 #include <machine/intr.h> 72 73 #include <dev/mii/miivar.h> 74 75 #include <dev/pci/pcivar.h> 76 #include <dev/pci/pcireg.h> 77 #include <dev/pci/pcidevs.h> 78 79 #include <dev/cardbus/cardbusvar.h> 80 #include <dev/cardbus/cardbusdevs.h> 81 82 /* 83 * Default to using PIO access for this driver. On SMP systems, 84 * there appear to be problems with memory mapped mode: it looks like 85 * doing too many memory mapped access back to back in rapid succession 86 * can hang the bus. I'm inclined to blame this on crummy design/construction 87 * on the part of RealTek. Memory mapped mode does appear to work on 88 * uniprocessor systems though. 89 */ 90 #define RL_USEIOSPACE 91 92 #include <dev/ic/rtl81x9reg.h> 93 94 /* 95 * Various supported device vendors/types and their names. 96 */ 97 static const struct rl_type rl_cardbus_devs[] = { 98 { CARDBUS_VENDOR_ACCTON, CARDBUS_PRODUCT_ACCTON_MPX5030 }, 99 { CARDBUS_VENDOR_REALTEK, CARDBUS_PRODUCT_REALTEK_RT8138 }, 100 { CARDBUS_VENDOR_REALTEK, CARDBUS_PRODUCT_REALTEK_RT8139 }, 101 { CARDBUS_VENDOR_COREGA, CARDBUS_PRODUCT_COREGA_CB_TXD }, 102 { 0, 0 } 103 }; 104 105 struct rl_cardbus_softc { 106 struct rl_softc sc_rl; /* real rtk softc */ 107 108 /* CardBus-specific goo. */ 109 void *sc_ih; 110 cardbus_devfunc_t sc_ct; 111 cardbustag_t sc_tag; 112 int sc_csr; 113 int sc_cben; 114 int sc_bar_reg; 115 pcireg_t sc_bar_val; 116 bus_size_t sc_mapsize; 117 int sc_intrline; 118 }; 119 120 static int rl_cardbus_match(struct device *, void *, void *); 121 static void rl_cardbus_attach(struct device *, struct device *, void *); 122 static int rl_cardbus_detach(struct device *, int); 123 void rl_cardbus_setup(struct rl_cardbus_softc *); 124 125 struct cfattach rl_cardbus_ca = { 126 sizeof(struct rl_cardbus_softc), rl_cardbus_match, rl_cardbus_attach, 127 rl_cardbus_detach 128 }; 129 130 const struct rl_type *rl_cardbus_lookup (const struct cardbus_attach_args *); 131 132 const struct rl_type * 133 rl_cardbus_lookup(ca) 134 const struct cardbus_attach_args *ca; 135 { 136 const struct rl_type *t; 137 138 for (t = rl_cardbus_devs; t->rl_vid != 0; t++){ 139 if (CARDBUS_VENDOR(ca->ca_id) == t->rl_vid && 140 CARDBUS_PRODUCT(ca->ca_id) == t->rl_did) { 141 return (t); 142 } 143 } 144 return (NULL); 145 } 146 147 int 148 rl_cardbus_match(parent, match, aux) 149 struct device *parent; 150 void *match; 151 void *aux; 152 { 153 struct cardbus_attach_args *ca = aux; 154 155 if (rl_cardbus_lookup(ca) != NULL) 156 return (1); 157 158 return (0); 159 } 160 161 162 void 163 rl_cardbus_attach(parent, self, aux) 164 struct device *parent, *self; 165 void *aux; 166 { 167 struct rl_cardbus_softc *csc = (struct rl_cardbus_softc *)self; 168 struct rl_softc *sc = &csc->sc_rl; 169 struct cardbus_attach_args *ca = aux; 170 struct cardbus_softc *psc = 171 (struct cardbus_softc *)sc->sc_dev.dv_parent; 172 cardbus_chipset_tag_t cc = psc->sc_cc; 173 cardbus_function_tag_t cf = psc->sc_cf; 174 cardbus_devfunc_t ct = ca->ca_ct; 175 const struct rl_type *t; 176 bus_addr_t adr; 177 178 sc->sc_dmat = ca->ca_dmat; 179 csc->sc_ct = ct; 180 csc->sc_tag = ca->ca_tag; 181 csc->sc_intrline = ca->ca_intrline; 182 183 t = rl_cardbus_lookup(ca); 184 if (t == NULL) { 185 printf("\n"); 186 panic("rl_cardbus_attach: impossible"); 187 } 188 189 /* 190 * Map control/status registers. 191 */ 192 csc->sc_csr = CARDBUS_COMMAND_MASTER_ENABLE; 193 #ifdef RL_USEIOSPACE 194 if (Cardbus_mapreg_map(ct, RL_PCI_LOIO, CARDBUS_MAPREG_TYPE_IO, 0, 195 &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) { 196 #if rbus 197 #else 198 (*ct->ct_cf->cardbus_io_open)(cc, 0, adr, adr+csc->sc_mapsize); 199 #endif 200 csc->sc_cben = CARDBUS_IO_ENABLE; 201 csc->sc_csr |= CARDBUS_COMMAND_IO_ENABLE; 202 csc->sc_bar_reg = RL_PCI_LOIO; 203 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_IO; 204 } 205 #else 206 if (Cardbus_mapreg_map(ct, RL_PCI_LOMEM, CARDBUS_MAPREG_TYPE_MEM, 0, 207 &sc->rl_btag, &sc->rl_bhandle, &adr, &csc->sc_mapsize) == 0) { 208 #if rbus 209 #else 210 (*ct->ct_cf->cardbus_mem_open)(cc, 0, adr, adr+csc->sc_mapsize); 211 #endif 212 csc->sc_cben = CARDBUS_MEM_ENABLE; 213 csc->sc_csr |= CARDBUS_COMMAND_MEM_ENABLE; 214 csc->sc_bar_reg = RL_PCI_LOMEM; 215 csc->sc_bar_val = adr | CARDBUS_MAPREG_TYPE_MEM; 216 } 217 #endif 218 else { 219 printf("%s: unable to map deviceregisters\n", 220 sc->sc_dev.dv_xname); 221 return; 222 } 223 224 Cardbus_function_enable(ct); 225 226 rl_cardbus_setup(csc); 227 228 /* 229 * Map and establish the interrupt. 230 */ 231 csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET, 232 rl_intr, sc); 233 if (csc->sc_ih == NULL) { 234 printf(": couldn't establish interrupt\n"); 235 Cardbus_function_disable(csc->sc_ct); 236 return; 237 } 238 printf(": irq %d", csc->sc_intrline); 239 240 /* XXX - hardcode this, for now */ 241 sc->rl_type = RL_8139; 242 243 rl_attach(sc); 244 } 245 246 int 247 rl_cardbus_detach(self, flags) 248 struct device *self; 249 int flags; 250 { 251 struct rl_cardbus_softc *csc = (void *) self; 252 struct rl_softc *sc = &csc->sc_rl; 253 struct cardbus_devfunc *ct = csc->sc_ct; 254 int rv; 255 256 #ifdef DIAGNOSTIC 257 if (ct == NULL) 258 panic("%s: data structure lacks", sc->sc_dev.dv_xname); 259 #endif 260 rv = rl_detach(sc); 261 if (rv) 262 return (rv); 263 /* 264 * Unhook the interrut handler. 265 */ 266 if (csc->sc_ih != NULL) 267 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, csc->sc_ih); 268 269 /* 270 * Release bus space and close window. 271 */ 272 if (csc->sc_bar_reg != 0) 273 Cardbus_mapreg_unmap(ct, csc->sc_bar_reg, 274 sc->rl_btag, sc->rl_bhandle, csc->sc_mapsize); 275 276 return (0); 277 } 278 279 void 280 rl_cardbus_setup(csc) 281 struct rl_cardbus_softc *csc; 282 { 283 struct rl_softc *sc = &csc->sc_rl; 284 cardbus_devfunc_t ct = csc->sc_ct; 285 cardbus_chipset_tag_t cc = ct->ct_cc; 286 cardbus_function_tag_t cf = ct->ct_cf; 287 pcireg_t reg,command; 288 int pmreg; 289 290 /* 291 * Handle power management nonsense. 292 */ 293 if (cardbus_get_capability(cc, cf, csc->sc_tag, 294 PCI_CAP_PWRMGMT, &pmreg, 0)) { 295 command = cardbus_conf_read(cc, cf, csc->sc_tag, pmreg + 4); 296 if (command & RL_PSTATE_MASK) { 297 pcireg_t iobase, membase, irq; 298 299 /* Save important PCI config data. */ 300 iobase = cardbus_conf_read(cc, cf, csc->sc_tag, 301 RL_PCI_LOIO); 302 membase = cardbus_conf_read(cc, cf,csc->sc_tag, 303 RL_PCI_LOMEM); 304 irq = cardbus_conf_read(cc, cf,csc->sc_tag, 305 PCI_PRODUCT_DELTA_8139); 306 307 /* Reset the power state. */ 308 printf("%s: chip is is in D%d power mode " 309 "-- setting to D0\n", sc->sc_dev.dv_xname, 310 command & RL_PSTATE_MASK); 311 command &= 0xFFFFFFFC; 312 cardbus_conf_write(cc, cf, csc->sc_tag, 313 pmreg + 4, command); 314 315 /* Restore PCI config data. */ 316 cardbus_conf_write(cc, cf, csc->sc_tag, 317 RL_PCI_LOIO, iobase); 318 cardbus_conf_write(cc, cf, csc->sc_tag, 319 RL_PCI_LOMEM, membase); 320 cardbus_conf_write(cc, cf, csc->sc_tag, 321 PCI_PRODUCT_DELTA_8139, irq); 322 } 323 } 324 325 /* Make sure the right access type is on the CardBus bridge. */ 326 (*ct->ct_cf->cardbus_ctrl)(cc, csc->sc_cben); 327 (*ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); 328 329 /* Program the BAR */ 330 cardbus_conf_write(cc, cf, csc->sc_tag, 331 csc->sc_bar_reg, csc->sc_bar_val); 332 333 /* Enable the appropriate bits in the CARDBUS CSR. */ 334 reg = cardbus_conf_read(cc, cf, csc->sc_tag, 335 CARDBUS_COMMAND_STATUS_REG); 336 reg &= ~(CARDBUS_COMMAND_IO_ENABLE|CARDBUS_COMMAND_MEM_ENABLE); 337 reg |= csc->sc_csr; 338 cardbus_conf_write(cc, cf, csc->sc_tag, 339 CARDBUS_COMMAND_STATUS_REG, reg); 340 341 /* 342 * Make sure the latency timer is set to some reasonable 343 * value. 344 */ 345 reg = cardbus_conf_read(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG); 346 if (CARDBUS_LATTIMER(reg) < 0x20) { 347 reg &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT); 348 reg |= (0x20 << CARDBUS_LATTIMER_SHIFT); 349 cardbus_conf_write(cc, cf, csc->sc_tag, CARDBUS_BHLC_REG, reg); 350 } 351 } 352 353