1 /* $OpenBSD: if_xl_cardbus.c,v 1.12 2002/10/12 01:09:44 krw Exp $ */ 2 /* $NetBSD: if_xl_cardbus.c,v 1.13 2000/03/07 00:32:52 mycroft Exp $ */ 3 4 /* 5 * CardBus specific routines for 3Com 3C575-family CardBus ethernet adapter 6 * 7 * Copyright (c) 1998 and 1999 8 * HAYAKAWA Koichi. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the author. 21 * 4. Neither the name of the author nor the names of any co-contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * 38 */ 39 40 #include "bpfilter.h" 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/mbuf.h> 45 #include <sys/socket.h> 46 #include <sys/ioctl.h> 47 #include <sys/errno.h> 48 #include <sys/malloc.h> 49 #include <sys/kernel.h> 50 #include <sys/proc.h> 51 #include <sys/device.h> 52 53 #include <net/if.h> 54 #include <net/if_dl.h> 55 #include <net/if_types.h> 56 #include <net/if_media.h> 57 58 #ifdef INET 59 #include <netinet/in.h> 60 #include <netinet/in_systm.h> 61 #include <netinet/in_var.h> 62 #include <netinet/ip.h> 63 #include <netinet/if_ether.h> 64 #endif 65 66 #include <machine/cpu.h> 67 #include <machine/bus.h> 68 69 #include <dev/cardbus/cardbusvar.h> 70 #include <dev/cardbus/cardbusdevs.h> 71 72 #include <dev/mii/mii.h> 73 #include <dev/mii/miivar.h> 74 75 #include <dev/ic/xlreg.h> 76 77 #if defined XL_DEBUG 78 #define DPRINTF(a) printf a 79 #else 80 #define DPRINTF(a) 81 #endif 82 83 #define CARDBUS_3C575BTX_FUNCSTAT_PCIREG CARDBUS_BASE2_REG /* means 0x18 */ 84 85 int xl_cardbus_match(struct device *, void *, void *); 86 void xl_cardbus_attach(struct device *, struct device *,void *); 87 int xl_cardbus_detach(struct device *, int); 88 void xl_cardbus_intr_ack(struct xl_softc *); 89 90 #define XL_CARDBUS_BOOMERANG 0x0001 91 #define XL_CARDBUS_CYCLONE 0x0002 92 93 #define XL_CARDBUS_INTR 0x0004 94 #define XL_CARDBUS_INTR_ACK 0x8000 95 96 struct xl_cardbus_softc { 97 struct xl_softc sc_softc; 98 99 cardbus_devfunc_t sc_ct; 100 int sc_intrline; 101 u_int8_t sc_cardbus_flags; 102 u_int8_t sc_cardtype; 103 104 /* CardBus function status space. 575B requests it. */ 105 bus_space_tag_t sc_funct; 106 bus_space_handle_t sc_funch; 107 bus_size_t sc_funcsize; 108 109 bus_size_t sc_mapsize; /* size of mapped bus space region */ 110 }; 111 112 struct cfattach xl_cardbus_ca = { 113 sizeof(struct xl_cardbus_softc), xl_cardbus_match, 114 xl_cardbus_attach, xl_cardbus_detach 115 }; 116 117 const struct xl_cardbus_product { 118 u_int32_t ecp_prodid; /* CardBus product ID */ 119 int ecp_flags; /* initial softc flags */ 120 pcireg_t ecp_csr; /* PCI CSR flags */ 121 int ecp_cardtype; /* card type */ 122 const char *ecp_name; /* device name */ 123 } xl_cardbus_products[] = { 124 { CARDBUS_PRODUCT_3COM_3C575, 125 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM, 126 CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE, 127 XL_CARDBUS_BOOMERANG, 128 "3c575-TX Ethernet" }, 129 130 { CARDBUS_PRODUCT_3COM_3CCFE575BT, 131 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 132 XL_FLAG_INVERT_LED_PWR, 133 CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE | 134 CARDBUS_COMMAND_MASTER_ENABLE, 135 XL_CARDBUS_CYCLONE, 136 "3c575B-TX Ethernet" }, 137 138 { CARDBUS_PRODUCT_3COM_3CCFE575CT, 139 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 140 XL_FLAG_INVERT_MII_PWR, 141 CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE | 142 CARDBUS_COMMAND_MASTER_ENABLE, 143 XL_CARDBUS_CYCLONE, 144 "3c575C-TX Ethernet" }, 145 146 { CARDBUS_PRODUCT_3COM_3CCFEM656, 147 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 148 XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR, 149 CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE | 150 CARDBUS_COMMAND_MASTER_ENABLE, 151 XL_CARDBUS_CYCLONE, 152 "3c656-TX Ethernet" }, 153 154 { CARDBUS_PRODUCT_3COM_3CCFEM656B, 155 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 156 XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR, 157 CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE | 158 CARDBUS_COMMAND_MASTER_ENABLE, 159 XL_CARDBUS_CYCLONE, 160 "3c656B-TX Ethernet" }, 161 162 { CARDBUS_PRODUCT_3COM_3CCFEM656C, 163 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 164 XL_FLAG_INVERT_MII_PWR, 165 CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MEM_ENABLE | 166 CARDBUS_COMMAND_MASTER_ENABLE, 167 XL_CARDBUS_CYCLONE, 168 "3c656C-TX Ethernet" }, 169 170 { 0, 171 0, 172 0, 173 NULL }, 174 }; 175 176 const struct xl_cardbus_product *xl_cardbus_lookup(const struct cardbus_attach_args *); 177 178 const struct xl_cardbus_product * 179 xl_cardbus_lookup(ca) 180 const struct cardbus_attach_args *ca; 181 { 182 const struct xl_cardbus_product *ecp; 183 184 if (CARDBUS_VENDOR(ca->ca_id) != CARDBUS_VENDOR_3COM) 185 return (NULL); 186 187 for (ecp = xl_cardbus_products; ecp->ecp_name != NULL; ecp++) 188 if (CARDBUS_PRODUCT(ca->ca_id) == ecp->ecp_prodid) 189 return (ecp); 190 return (NULL); 191 } 192 193 int 194 xl_cardbus_match(parent, match, aux) 195 struct device *parent; 196 void *match; 197 void *aux; 198 { 199 struct cardbus_attach_args *ca = aux; 200 201 if (xl_cardbus_lookup(ca) != NULL) 202 return (1); 203 204 return (0); 205 } 206 207 void 208 xl_cardbus_attach(parent, self, aux) 209 struct device *parent; 210 struct device *self; 211 void *aux; 212 { 213 struct xl_cardbus_softc *csc = (void *)self; 214 struct xl_softc *sc = &csc->sc_softc; 215 struct cardbus_attach_args *ca = aux; 216 cardbus_devfunc_t ct = ca->ca_ct; 217 cardbus_chipset_tag_t cc = ct->ct_cc; 218 cardbus_function_tag_t cf = ct->ct_cf; 219 cardbusreg_t iob, command, bhlc; 220 const struct xl_cardbus_product *ecp; 221 bus_space_handle_t ioh; 222 bus_addr_t adr; 223 224 if (Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, 0, 225 &sc->xl_btag, &ioh, &adr, &csc->sc_mapsize)) { 226 printf(": can't map i/o space\n"); 227 return; 228 } 229 230 ecp = xl_cardbus_lookup(ca); 231 if (ecp == NULL) { 232 printf("\n"); 233 panic("xl_cardbus_attach: impossible"); 234 } 235 236 printf(": 3Com %s", ecp->ecp_name); 237 238 sc->xl_flags = ecp->ecp_flags; 239 sc->sc_dmat = ca->ca_dmat; 240 241 iob = adr; 242 sc->xl_bhandle = ioh; 243 244 #if rbus 245 #else 246 (ct->ct_cf->cardbus_io_open)(cc, 0, iob, iob + 0x40); 247 #endif 248 (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); 249 250 command = cardbus_conf_read(cc, cf, ca->ca_tag, 251 CARDBUS_COMMAND_STATUS_REG); 252 command |= ecp->ecp_csr; 253 csc->sc_cardtype = ecp->ecp_cardtype; 254 255 if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) { 256 /* map CardBus function status window */ 257 if (Cardbus_mapreg_map(ct, CARDBUS_BASE2_REG, 258 CARDBUS_MAPREG_TYPE_MEM, 0, &csc->sc_funct, 259 &csc->sc_funch, 0, &csc->sc_funcsize)) { 260 printf("%s: unable to map function status window\n", 261 self->dv_xname); 262 return; 263 } 264 265 /* 266 * Make sure CardBus bridge can access memory space. Usually 267 * memory access is enabled by BIOS, but some BIOSes do not 268 * enable it. 269 */ 270 (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); 271 } 272 273 (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); 274 cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG, 275 command); 276 277 /* 278 * set latency timmer 279 */ 280 bhlc = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG); 281 if (CARDBUS_LATTIMER(bhlc) < 0x20) { 282 /* at least the value of latency timer should 0x20. */ 283 DPRINTF(("if_xl_cardbus: lattimer 0x%x -> 0x20\n", 284 CARDBUS_LATTIMER(bhlc))); 285 bhlc &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT); 286 bhlc |= (0x20 << CARDBUS_LATTIMER_SHIFT); 287 cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG, bhlc); 288 } 289 290 csc->sc_ct = ca->ca_ct; 291 csc->sc_intrline = ca->ca_intrline; 292 293 /* Map and establish the interrupt. */ 294 295 sc->xl_intrhand = cardbus_intr_establish(cc, cf, ca->ca_intrline, 296 IPL_NET, xl_intr, csc); 297 298 if (sc->xl_intrhand == NULL) { 299 printf(": couldn't establish interrupt"); 300 printf(" at %d", ca->ca_intrline); 301 printf("\n"); 302 return; 303 } 304 printf(": irq %d", ca->ca_intrline); 305 306 sc->intr_ack = xl_cardbus_intr_ack; 307 308 xl_attach(sc); 309 310 if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) 311 bus_space_write_4(csc->sc_funct, csc->sc_funch, 312 XL_CARDBUS_INTR, XL_CARDBUS_INTR_ACK); 313 314 } 315 316 int 317 xl_cardbus_detach(self, arg) 318 struct device *self; 319 int arg; 320 { 321 struct xl_cardbus_softc *csc = (void *)self; 322 struct xl_softc *sc = &csc->sc_softc; 323 struct cardbus_devfunc *ct = csc->sc_ct; 324 int rv = 0; 325 326 #if defined(DIAGNOSTIC) 327 if (ct == NULL) { 328 panic("%s: data structure lacks", sc->sc_dev.dv_xname); 329 } 330 #endif 331 332 rv = xl_detach(sc); 333 if (rv == 0) { 334 /* 335 * Unhook the interrupt handler. 336 */ 337 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, 338 sc->xl_intrhand); 339 340 if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) { 341 Cardbus_mapreg_unmap(ct, CARDBUS_BASE2_REG, 342 csc->sc_funct, csc->sc_funch, csc->sc_funcsize); 343 } 344 345 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->xl_btag, 346 sc->xl_bhandle, csc->sc_mapsize); 347 } 348 return (rv); 349 } 350 351 void 352 xl_cardbus_intr_ack(sc) 353 struct xl_softc *sc; 354 { 355 struct xl_cardbus_softc *csc = (struct xl_cardbus_softc *)sc; 356 357 bus_space_write_4(csc->sc_funct, csc->sc_funch, XL_CARDBUS_INTR, 358 XL_CARDBUS_INTR_ACK); 359 } 360