1 /* $OpenBSD: if_xl_cardbus.c,v 1.33 2015/11/24 17:11:39 mpi 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 * 19 * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER 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 */ 33 34 #include "bpfilter.h" 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/mbuf.h> 39 #include <sys/socket.h> 40 #include <sys/ioctl.h> 41 #include <sys/errno.h> 42 #include <sys/malloc.h> 43 #include <sys/kernel.h> 44 #include <sys/device.h> 45 46 #include <net/if.h> 47 #include <net/if_media.h> 48 49 #include <netinet/in.h> 50 #include <netinet/if_ether.h> 51 52 #include <machine/cpu.h> 53 #include <machine/bus.h> 54 55 #include <dev/cardbus/cardbusvar.h> 56 #include <dev/pci/pcidevs.h> 57 58 #include <dev/mii/miivar.h> 59 60 #include <dev/ic/xlreg.h> 61 62 #if defined XL_DEBUG 63 #define DPRINTF(a) printf a 64 #else 65 #define DPRINTF(a) 66 #endif 67 68 #define CARDBUS_3C575BTX_FUNCSTAT_PCIREG CARDBUS_BASE2_REG /* means 0x18 */ 69 70 int xl_cardbus_match(struct device *, void *, void *); 71 void xl_cardbus_attach(struct device *, struct device *,void *); 72 int xl_cardbus_detach(struct device *, int); 73 void xl_cardbus_intr_ack(struct xl_softc *); 74 75 #define XL_CARDBUS_BOOMERANG 0x0001 76 #define XL_CARDBUS_CYCLONE 0x0002 77 78 #define XL_CARDBUS_INTR 0x0004 79 #define XL_CARDBUS_INTR_ACK 0x8000 80 81 struct xl_cardbus_softc { 82 struct xl_softc sc_softc; 83 84 cardbus_devfunc_t sc_ct; 85 int sc_intrline; 86 u_int8_t sc_cardbus_flags; 87 u_int8_t sc_cardtype; 88 89 /* CardBus function status space. 575B requests it. */ 90 bus_space_tag_t sc_funct; 91 bus_space_handle_t sc_funch; 92 bus_size_t sc_funcsize; 93 94 bus_size_t sc_mapsize; /* size of mapped bus space region */ 95 }; 96 97 struct cfattach xl_cardbus_ca = { 98 sizeof(struct xl_cardbus_softc), xl_cardbus_match, 99 xl_cardbus_attach, xl_cardbus_detach 100 }; 101 102 const struct xl_cardbus_product { 103 u_int32_t ecp_prodid; /* CardBus product ID */ 104 int ecp_flags; /* initial softc flags */ 105 pcireg_t ecp_csr; /* PCI CSR flags */ 106 int ecp_cardtype; /* card type */ 107 } xl_cardbus_products[] = { 108 { PCI_PRODUCT_3COM_3C575, 109 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM, 110 PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE, 111 XL_CARDBUS_BOOMERANG }, 112 113 { PCI_PRODUCT_3COM_3CCFE575BT, 114 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 115 XL_FLAG_INVERT_LED_PWR, 116 PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 117 PCI_COMMAND_MASTER_ENABLE, 118 XL_CARDBUS_CYCLONE }, 119 120 { PCI_PRODUCT_3COM_3CCFE575CT, 121 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 122 XL_FLAG_INVERT_MII_PWR, 123 PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 124 PCI_COMMAND_MASTER_ENABLE, 125 XL_CARDBUS_CYCLONE }, 126 127 { PCI_PRODUCT_3COM_3CCFEM656, 128 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 129 XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR, 130 PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 131 PCI_COMMAND_MASTER_ENABLE, 132 XL_CARDBUS_CYCLONE }, 133 134 { PCI_PRODUCT_3COM_3CCFEM656B, 135 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 136 XL_FLAG_INVERT_LED_PWR | XL_FLAG_INVERT_MII_PWR, 137 PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 138 PCI_COMMAND_MASTER_ENABLE, 139 XL_CARDBUS_CYCLONE }, 140 141 { PCI_PRODUCT_3COM_3CCFEM656C, 142 XL_FLAG_PHYOK | XL_FLAG_EEPROM_OFFSET_30 | XL_FLAG_8BITROM | 143 XL_FLAG_INVERT_MII_PWR, 144 PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 145 PCI_COMMAND_MASTER_ENABLE, 146 XL_CARDBUS_CYCLONE }, 147 148 { 0, 149 0, 150 0, 151 0 }, 152 }; 153 154 const struct xl_cardbus_product *xl_cardbus_lookup(const struct cardbus_attach_args *); 155 156 const struct xl_cardbus_product * 157 xl_cardbus_lookup(const struct cardbus_attach_args *ca) 158 { 159 const struct xl_cardbus_product *ecp; 160 161 if (PCI_VENDOR(ca->ca_id) != PCI_VENDOR_3COM) 162 return (NULL); 163 164 for (ecp = xl_cardbus_products; ecp->ecp_prodid != 0; ecp++) 165 if (PCI_PRODUCT(ca->ca_id) == ecp->ecp_prodid) 166 return (ecp); 167 return (NULL); 168 } 169 170 int 171 xl_cardbus_match(struct device *parent, void *match, void *aux) 172 { 173 struct cardbus_attach_args *ca = aux; 174 175 if (xl_cardbus_lookup(ca) != NULL) 176 return (1); 177 178 return (0); 179 } 180 181 void 182 xl_cardbus_attach(struct device *parent, struct device *self, void *aux) 183 { 184 struct xl_cardbus_softc *csc = (void *)self; 185 struct xl_softc *sc = &csc->sc_softc; 186 struct cardbus_attach_args *ca = aux; 187 cardbus_devfunc_t ct = ca->ca_ct; 188 cardbus_chipset_tag_t cc = ct->ct_cc; 189 cardbus_function_tag_t cf = ct->ct_cf; 190 pcireg_t command, bhlc; 191 const struct xl_cardbus_product *ecp; 192 bus_space_handle_t ioh; 193 bus_addr_t adr; 194 195 if (Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, PCI_MAPREG_TYPE_IO, 0, 196 &sc->xl_btag, &ioh, &adr, &csc->sc_mapsize)) { 197 printf(": can't map i/o space\n"); 198 return; 199 } 200 201 ecp = xl_cardbus_lookup(ca); 202 if (ecp == NULL) { 203 printf("\n"); 204 panic("xl_cardbus_attach: impossible"); 205 } 206 207 sc->xl_flags = ecp->ecp_flags; 208 sc->sc_dmat = ca->ca_dmat; 209 210 sc->xl_bhandle = ioh; 211 212 (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); 213 214 command = pci_conf_read(ca->ca_pc, ca->ca_tag, 215 PCI_COMMAND_STATUS_REG); 216 command |= ecp->ecp_csr; 217 csc->sc_cardtype = ecp->ecp_cardtype; 218 219 if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) { 220 /* map CardBus function status window */ 221 if (Cardbus_mapreg_map(ct, CARDBUS_BASE2_REG, 222 PCI_MAPREG_TYPE_MEM, 0, &csc->sc_funct, 223 &csc->sc_funch, 0, &csc->sc_funcsize)) { 224 printf("%s: unable to map function status window\n", 225 self->dv_xname); 226 return; 227 } 228 229 /* 230 * Make sure CardBus bridge can access memory space. Usually 231 * memory access is enabled by BIOS, but some BIOSes do not 232 * enable it. 233 */ 234 (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); 235 } 236 237 (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); 238 pci_conf_write(ca->ca_pc, ca->ca_tag, PCI_COMMAND_STATUS_REG, 239 command); 240 241 /* 242 * set latency timer 243 */ 244 bhlc = pci_conf_read(ca->ca_pc, ca->ca_tag, PCI_BHLC_REG); 245 if (PCI_LATTIMER(bhlc) < 0x20) { 246 /* at least the value of latency timer should 0x20. */ 247 DPRINTF(("if_xl_cardbus: lattimer 0x%x -> 0x20\n", 248 PCI_LATTIMER(bhlc))); 249 bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); 250 bhlc |= (0x20 << PCI_LATTIMER_SHIFT); 251 pci_conf_write(ca->ca_pc, ca->ca_tag, PCI_BHLC_REG, bhlc); 252 } 253 254 csc->sc_ct = ca->ca_ct; 255 csc->sc_intrline = ca->ca_intrline; 256 257 /* Map and establish the interrupt. */ 258 259 sc->xl_intrhand = cardbus_intr_establish(cc, cf, ca->ca_intrline, 260 IPL_NET, xl_intr, csc, self->dv_xname); 261 262 if (sc->xl_intrhand == NULL) { 263 printf(": couldn't establish interrupt"); 264 printf(" at %d", ca->ca_intrline); 265 printf("\n"); 266 return; 267 } 268 printf(": irq %d", ca->ca_intrline); 269 270 sc->intr_ack = xl_cardbus_intr_ack; 271 272 xl_attach(sc); 273 274 if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) 275 bus_space_write_4(csc->sc_funct, csc->sc_funch, 276 XL_CARDBUS_INTR, XL_CARDBUS_INTR_ACK); 277 278 } 279 280 int 281 xl_cardbus_detach(struct device *self, int arg) 282 { 283 struct xl_cardbus_softc *csc = (void *)self; 284 struct xl_softc *sc = &csc->sc_softc; 285 struct cardbus_devfunc *ct = csc->sc_ct; 286 287 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, 288 sc->xl_intrhand); 289 xl_detach(sc); 290 if (csc->sc_cardtype == XL_CARDBUS_CYCLONE) 291 Cardbus_mapreg_unmap(ct, CARDBUS_BASE2_REG, 292 csc->sc_funct, csc->sc_funch, csc->sc_funcsize); 293 Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->xl_btag, 294 sc->xl_bhandle, csc->sc_mapsize); 295 return (0); 296 } 297 298 void 299 xl_cardbus_intr_ack(struct xl_softc *sc) 300 { 301 struct xl_cardbus_softc *csc = (struct xl_cardbus_softc *)sc; 302 303 bus_space_write_4(csc->sc_funct, csc->sc_funch, XL_CARDBUS_INTR, 304 XL_CARDBUS_INTR_ACK); 305 } 306