puc_cardbus.c revision 1.2
1/* $OpenBSD: puc_cardbus.c,v 1.2 2006/10/12 16:35:52 grange Exp $ */ 2 3/* 4 * Copyright (c) 2006 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN 16 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include <sys/param.h> 21#include <sys/systm.h> 22#include <sys/device.h> 23#include <sys/tty.h> 24 25#include <machine/bus.h> 26#include <dev/ic/comvar.h> 27 28#include <dev/pci/pcireg.h> 29#include <dev/pci/pcivar.h> 30#include <dev/pci/pcidevs.h> 31#include <dev/cardbus/cardbusvar.h> 32 33#include <dev/pci/pucvar.h> 34 35struct puc_cardbus_softc { 36 struct puc_softc sc_psc; 37 38 struct cardbus_devfunc *ct; 39 int intrline; 40}; 41 42int puc_cardbus_match(struct device *, void *, void *); 43void puc_cardbus_attach(struct device *, struct device *, void *); 44int puc_cardbus_detach(struct device *, int); 45 46const char *puc_cardbus_intr_string(struct puc_attach_args *); 47void *puc_cardbus_intr_establish(struct puc_attach_args *, int, 48 int (*)(void *), void *, char *); 49 50struct cfattach puc_cardbus_ca = { 51 sizeof(struct puc_cardbus_softc), puc_cardbus_match, 52 puc_cardbus_attach, puc_cardbus_detach 53}; 54 55int 56puc_cardbus_match(struct device *parent, void *match, void *aux) 57{ 58 struct cardbus_attach_args *ca = aux; 59 struct cardbus_devfunc *ct = ca->ca_ct; 60 cardbus_chipset_tag_t cc = ct->ct_cc; 61 cardbus_function_tag_t cf = ct->ct_cf; 62 cardbusreg_t bhlc, reg; 63 64 bhlc = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG); 65 if (PCI_HDRTYPE_TYPE(bhlc) != 0) 66 return(0); 67 68 /* this one is some sort of a bridge and not a puc */ 69 if (PCI_VENDOR(ca->ca_id) == PCI_VENDOR_OXFORD2 && 70 PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_OXFORD2_EXSYS_EX41098) 71 return (0); 72 73 reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_SUBSYS_ID_REG); 74 if (puc_find_description(PCI_VENDOR(ca->ca_id), 75 PCI_PRODUCT(ca->ca_id), PCI_VENDOR(reg), PCI_PRODUCT(reg))) 76 return (10); 77 78 return (0); 79} 80 81void 82puc_cardbus_attach(struct device *parent, struct device *self, void *aux) 83{ 84 struct puc_cardbus_softc *csc = (struct puc_cardbus_softc *)self; 85 struct puc_softc *sc = &csc->sc_psc; 86 struct cardbus_attach_args *ca = aux; 87 struct cardbus_devfunc *ct = ca->ca_ct; 88 cardbus_chipset_tag_t cc = ct->ct_cc; 89 cardbus_function_tag_t cf = ct->ct_cf; 90 struct puc_attach_args paa; 91 cardbusreg_t reg; 92 int i; 93 94 Cardbus_function_enable(ct); 95 96 csc->ct = ct; 97 98 reg = cardbus_conf_read(cc, cf, ca->ca_tag, PCI_SUBSYS_ID_REG); 99 sc->sc_desc = puc_find_description(PCI_VENDOR(ca->ca_id), 100 PCI_PRODUCT(ca->ca_id), PCI_VENDOR(reg), PCI_PRODUCT(reg)); 101 102 puc_print_ports(sc->sc_desc); 103 104 /* the fifth one is some memory we dunno */ 105 for (i = 0; i < PUC_NBARS; i++) { 106 cardbusreg_t type; 107 int bar; 108 109 sc->sc_bar_mappings[i].mapped = 0; 110 bar = PCI_MAPREG_START + 4 * i; 111 if (!cardbus_mapreg_probe(cc, cf, ca->ca_tag, bar, &type)) 112 continue; 113 114 if (!(sc->sc_bar_mappings[i].mapped = !Cardbus_mapreg_map(ct, 115 bar, type, 0, 116 &sc->sc_bar_mappings[i].t, &sc->sc_bar_mappings[i].h, 117 &sc->sc_bar_mappings[i].a, &sc->sc_bar_mappings[i].s))) 118 printf("%s: couldn't map BAR at offset 0x%lx\n", 119 sc->sc_dev.dv_xname, (long)bar); 120 sc->sc_bar_mappings[i].type = type; 121 } 122 123 csc->intrline = ca->ca_intrline; 124 125 if (cardbus_get_capability(cc, cf, ca->ca_tag, PCI_CAP_PWRMGMT, ®, 126 0)) { 127 reg = cardbus_conf_read(cc, cf, ca->ca_tag, reg + 4) & 3; 128 if (reg) { 129 printf("%s: awakening from state D%d\n", 130 sc->sc_dev.dv_xname, reg); 131 cardbus_conf_write(cc, cf, ca->ca_tag, reg + 4, 0); 132 } 133 } 134 135 (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE); 136 (*cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE); 137 (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE); 138 139 paa.puc = sc; 140 paa.hwtype = COM_UART_OX16C950; /* XXX */ 141 paa.intr_string = &puc_cardbus_intr_string; 142 paa.intr_establish = &puc_cardbus_intr_establish; 143 puc_common_attach(sc, &paa); 144} 145 146const char * 147puc_cardbus_intr_string(struct puc_attach_args *paa) 148{ 149 struct puc_cardbus_softc *sc = paa->puc; 150 static char str[16]; 151 152 snprintf(str, sizeof str, "irq %d", sc->intrline); 153 return (str); 154} 155 156void * 157puc_cardbus_intr_establish(struct puc_attach_args *paa, int type, 158 int (*func)(void *), void *arg, char *name) 159{ 160 struct puc_cardbus_softc *sc = paa->puc; 161 struct cardbus_devfunc *ct = sc->ct; 162 163 return (cardbus_intr_establish(ct->ct_cc, ct->ct_cf, sc->intrline, 164 type, func, arg, name)); 165} 166 167int 168puc_cardbus_detach(struct device *self, int flags) 169{ 170 struct puc_cardbus_softc *csc = (struct puc_cardbus_softc *)self; 171 struct puc_softc *sc = &csc->sc_psc; 172 struct cardbus_devfunc *ct = csc->ct; 173 int i, rv; 174 175 for (i = PUC_MAX_PORTS; i--; ) 176 if (sc->sc_ports[i].dev) 177 if ((rv = config_detach(sc->sc_ports[i].dev, flags))) 178 return (rv); 179 180 for (i = PUC_NBARS; i--; ) 181 if (sc->sc_bar_mappings[i].mapped) 182 Cardbus_mapreg_unmap(ct, sc->sc_bar_mappings[i].type, 183 sc->sc_bar_mappings[i].t, sc->sc_bar_mappings[i].h, 184 sc->sc_bar_mappings[i].s); 185 186 return (0); 187} 188