1 1.217 thorpej /* $NetBSD: pccbb.c,v 1.217 2021/08/07 16:19:14 thorpej Exp $ */ 2 1.2 haya 3 1.1 haya /* 4 1.21 haya * Copyright (c) 1998, 1999 and 2000 5 1.21 haya * HAYAKAWA Koichi. All rights reserved. 6 1.1 haya * 7 1.1 haya * Redistribution and use in source and binary forms, with or without 8 1.1 haya * modification, are permitted provided that the following conditions 9 1.1 haya * are met: 10 1.1 haya * 1. Redistributions of source code must retain the above copyright 11 1.1 haya * notice, this list of conditions and the following disclaimer. 12 1.1 haya * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 haya * notice, this list of conditions and the following disclaimer in the 14 1.1 haya * documentation and/or other materials provided with the distribution. 15 1.1 haya * 16 1.1 haya * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 haya * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 haya * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 haya * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 haya * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 haya * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 haya * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 haya * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 haya * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 haya * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.1 haya */ 27 1.71 lukem 28 1.71 lukem #include <sys/cdefs.h> 29 1.217 thorpej __KERNEL_RCSID(0, "$NetBSD: pccbb.c,v 1.217 2021/08/07 16:19:14 thorpej Exp $"); 30 1.1 haya 31 1.1 haya /* 32 1.1 haya #define CBB_DEBUG 33 1.1 haya #define SHOW_REGS 34 1.1 haya */ 35 1.1 haya 36 1.1 haya #include <sys/param.h> 37 1.1 haya #include <sys/systm.h> 38 1.1 haya #include <sys/kernel.h> 39 1.1 haya #include <sys/errno.h> 40 1.1 haya #include <sys/ioctl.h> 41 1.54 augustss #include <sys/reboot.h> /* for bootverbose */ 42 1.1 haya #include <sys/syslog.h> 43 1.1 haya #include <sys/device.h> 44 1.1 haya #include <sys/malloc.h> 45 1.55 haya #include <sys/proc.h> 46 1.1 haya 47 1.148 ad #include <sys/intr.h> 48 1.148 ad #include <sys/bus.h> 49 1.1 haya 50 1.1 haya #include <dev/pci/pcivar.h> 51 1.1 haya #include <dev/pci/pcireg.h> 52 1.1 haya #include <dev/pci/pcidevs.h> 53 1.1 haya 54 1.1 haya #include <dev/pci/pccbbreg.h> 55 1.1 haya 56 1.1 haya #include <dev/cardbus/cardslotvar.h> 57 1.1 haya #include <dev/cardbus/cardbusvar.h> 58 1.1 haya 59 1.1 haya #include <dev/pcmcia/pcmciareg.h> 60 1.1 haya #include <dev/pcmcia/pcmciavar.h> 61 1.1 haya 62 1.1 haya #include <dev/ic/i82365reg.h> 63 1.1 haya #include <dev/pci/pccbbvar.h> 64 1.1 haya 65 1.1 haya #ifndef __NetBSD_Version__ 66 1.1 haya struct cfdriver cbb_cd = { 67 1.22 chopps NULL, "cbb", DV_DULL 68 1.1 haya }; 69 1.1 haya #endif 70 1.1 haya 71 1.73 christos #ifdef CBB_DEBUG 72 1.1 haya #define DPRINTF(x) printf x 73 1.1 haya #define STATIC 74 1.1 haya #else 75 1.1 haya #define DPRINTF(x) 76 1.1 haya #define STATIC static 77 1.1 haya #endif 78 1.1 haya 79 1.151 dyoung int pccbb_burstup = 1; 80 1.151 dyoung 81 1.55 haya /* 82 1.142 dyoung * delay_ms() is wait in milliseconds. It should be used instead 83 1.140 dyoung * of delay() if you want to wait more than 1 ms. 84 1.55 haya */ 85 1.142 dyoung static inline void 86 1.189 dyoung delay_ms(int millis, struct pccbb_softc *sc) 87 1.142 dyoung { 88 1.142 dyoung if (cold) 89 1.142 dyoung delay(millis * 1000); 90 1.142 dyoung else 91 1.189 dyoung kpause("pccbb", false, mstohz(millis), NULL); 92 1.142 dyoung } 93 1.55 haya 94 1.187 cegger int pcicbbmatch(device_t, cfdata_t, void *); 95 1.162 dyoung void pccbbattach(device_t, device_t, void *); 96 1.188 dyoung void pccbbchilddet(device_t, device_t); 97 1.158 dyoung int pccbbdetach(device_t, int); 98 1.116 perry int pccbbintr(void *); 99 1.116 perry static void pci113x_insert(void *); 100 1.116 perry static int pccbbintr_function(struct pccbb_softc *); 101 1.1 haya 102 1.116 perry static int pccbb_detect_card(struct pccbb_softc *); 103 1.1 haya 104 1.213 msaitoh static void pccbb_pcmcia_write(struct pccbb_softc *, int, uint8_t); 105 1.213 msaitoh static uint8_t pccbb_pcmcia_read(struct pccbb_softc *, int); 106 1.177 drochner #define Pcic_read(sc, reg) pccbb_pcmcia_read((sc), (reg)) 107 1.177 drochner #define Pcic_write(sc, reg, val) pccbb_pcmcia_write((sc), (reg), (val)) 108 1.1 haya 109 1.116 perry STATIC int cb_reset(struct pccbb_softc *); 110 1.116 perry STATIC int cb_detect_voltage(struct pccbb_softc *); 111 1.116 perry STATIC int cbbprint(void *, const char *); 112 1.116 perry 113 1.213 msaitoh static int cb_chipset(uint32_t, int *); 114 1.116 perry STATIC void pccbb_pcmcia_attach_setup(struct pccbb_softc *, 115 1.116 perry struct pcmciabus_attach_args *); 116 1.1 haya 117 1.116 perry STATIC int pccbb_ctrl(cardbus_chipset_tag_t, int); 118 1.213 msaitoh STATIC int pccbb_power(struct pccbb_softc *, int); 119 1.160 dyoung STATIC int pccbb_power_ct(cardbus_chipset_tag_t, int); 120 1.213 msaitoh STATIC int pccbb_cardenable(struct pccbb_softc *, int); 121 1.171 drochner static void *pccbb_intr_establish(struct pccbb_softc *, 122 1.213 msaitoh int, int (*ih) (void *), void *); 123 1.213 msaitoh static void pccbb_intr_disestablish(struct pccbb_softc *, void *); 124 1.116 perry 125 1.171 drochner static void *pccbb_cb_intr_establish(cardbus_chipset_tag_t, 126 1.213 msaitoh int, int (*ih) (void *), void *); 127 1.213 msaitoh static void pccbb_cb_intr_disestablish(cardbus_chipset_tag_t, void *); 128 1.116 perry 129 1.195 dyoung static pcitag_t pccbb_make_tag(cardbus_chipset_tag_t, int, int); 130 1.195 dyoung static pcireg_t pccbb_conf_read(cardbus_chipset_tag_t, pcitag_t, int); 131 1.213 msaitoh static void pccbb_conf_write(cardbus_chipset_tag_t, pcitag_t, int, pcireg_t); 132 1.116 perry static void pccbb_chipinit(struct pccbb_softc *); 133 1.165 dyoung static void pccbb_intrinit(struct pccbb_softc *); 134 1.116 perry 135 1.116 perry STATIC int pccbb_pcmcia_mem_alloc(pcmcia_chipset_handle_t, bus_size_t, 136 1.116 perry struct pcmcia_mem_handle *); 137 1.116 perry STATIC void pccbb_pcmcia_mem_free(pcmcia_chipset_handle_t, 138 1.116 perry struct pcmcia_mem_handle *); 139 1.116 perry STATIC int pccbb_pcmcia_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, 140 1.183 bouyer bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *); 141 1.116 perry STATIC void pccbb_pcmcia_mem_unmap(pcmcia_chipset_handle_t, int); 142 1.116 perry STATIC int pccbb_pcmcia_io_alloc(pcmcia_chipset_handle_t, bus_addr_t, 143 1.116 perry bus_size_t, bus_size_t, struct pcmcia_io_handle *); 144 1.116 perry STATIC void pccbb_pcmcia_io_free(pcmcia_chipset_handle_t, 145 1.116 perry struct pcmcia_io_handle *); 146 1.116 perry STATIC int pccbb_pcmcia_io_map(pcmcia_chipset_handle_t, int, bus_addr_t, 147 1.116 perry bus_size_t, struct pcmcia_io_handle *, int *); 148 1.116 perry STATIC void pccbb_pcmcia_io_unmap(pcmcia_chipset_handle_t, int); 149 1.116 perry STATIC void *pccbb_pcmcia_intr_establish(pcmcia_chipset_handle_t, 150 1.116 perry struct pcmcia_function *, int, int (*)(void *), void *); 151 1.116 perry STATIC void pccbb_pcmcia_intr_disestablish(pcmcia_chipset_handle_t, void *); 152 1.116 perry STATIC void pccbb_pcmcia_socket_enable(pcmcia_chipset_handle_t); 153 1.116 perry STATIC void pccbb_pcmcia_socket_disable(pcmcia_chipset_handle_t); 154 1.116 perry STATIC void pccbb_pcmcia_socket_settype(pcmcia_chipset_handle_t, int); 155 1.213 msaitoh STATIC int pccbb_pcmcia_card_detect(pcmcia_chipset_handle_t); 156 1.116 perry 157 1.176 drochner static int pccbb_pcmcia_wait_ready(struct pccbb_softc *); 158 1.176 drochner static void pccbb_pcmcia_delay(struct pccbb_softc *, int, const char *); 159 1.116 perry 160 1.176 drochner static void pccbb_pcmcia_do_io_map(struct pccbb_softc *, int); 161 1.176 drochner static void pccbb_pcmcia_do_mem_map(struct pccbb_softc *, int); 162 1.1 haya 163 1.32 enami /* bus-space allocation and deallocation functions */ 164 1.1 haya 165 1.116 perry static int pccbb_rbus_cb_space_alloc(cardbus_chipset_tag_t, rbus_tag_t, 166 1.213 msaitoh bus_addr_t, bus_size_t, bus_addr_t, bus_size_t, 167 1.213 msaitoh int, bus_addr_t *, bus_space_handle_t *); 168 1.116 perry static int pccbb_rbus_cb_space_free(cardbus_chipset_tag_t, rbus_tag_t, 169 1.116 perry bus_space_handle_t, bus_size_t); 170 1.1 haya 171 1.1 haya 172 1.1 haya 173 1.116 perry static int pccbb_open_win(struct pccbb_softc *, bus_space_tag_t, 174 1.213 msaitoh bus_addr_t, bus_size_t, bus_space_handle_t, int); 175 1.116 perry static int pccbb_close_win(struct pccbb_softc *, bus_space_tag_t, 176 1.116 perry bus_space_handle_t, bus_size_t); 177 1.116 perry static int pccbb_winlist_insert(struct pccbb_win_chain_head *, bus_addr_t, 178 1.116 perry bus_size_t, bus_space_handle_t, int); 179 1.116 perry static int pccbb_winlist_delete(struct pccbb_win_chain_head *, 180 1.116 perry bus_space_handle_t, bus_size_t); 181 1.213 msaitoh static void pccbb_winset(bus_addr_t, struct pccbb_softc *, bus_space_tag_t); 182 1.1 haya void pccbb_winlist_show(struct pccbb_win_chain *); 183 1.1 haya 184 1.1 haya 185 1.1 haya /* for config_defer */ 186 1.162 dyoung static void pccbb_pci_callback(device_t); 187 1.1 haya 188 1.194 dyoung static bool pccbb_suspend(device_t, const pmf_qual_t *); 189 1.194 dyoung static bool pccbb_resume(device_t, const pmf_qual_t *); 190 1.156 jmcneill 191 1.1 haya #if defined SHOW_REGS 192 1.213 msaitoh static void cb_show_regs(pci_chipset_tag_t, pcitag_t, 193 1.213 msaitoh bus_space_tag_t, bus_space_handle_t); 194 1.1 haya #endif 195 1.1 haya 196 1.185 dyoung CFATTACH_DECL3_NEW(cbb_pci, sizeof(struct pccbb_softc), 197 1.188 dyoung pcicbbmatch, pccbbattach, pccbbdetach, NULL, NULL, pccbbchilddet, 198 1.185 dyoung DVF_DETACH_SHUTDOWN); 199 1.1 haya 200 1.174 drochner static const struct pcmcia_chip_functions pccbb_pcmcia_funcs = { 201 1.22 chopps pccbb_pcmcia_mem_alloc, 202 1.22 chopps pccbb_pcmcia_mem_free, 203 1.22 chopps pccbb_pcmcia_mem_map, 204 1.22 chopps pccbb_pcmcia_mem_unmap, 205 1.22 chopps pccbb_pcmcia_io_alloc, 206 1.22 chopps pccbb_pcmcia_io_free, 207 1.22 chopps pccbb_pcmcia_io_map, 208 1.22 chopps pccbb_pcmcia_io_unmap, 209 1.22 chopps pccbb_pcmcia_intr_establish, 210 1.22 chopps pccbb_pcmcia_intr_disestablish, 211 1.22 chopps pccbb_pcmcia_socket_enable, 212 1.22 chopps pccbb_pcmcia_socket_disable, 213 1.101 mycroft pccbb_pcmcia_socket_settype, 214 1.22 chopps pccbb_pcmcia_card_detect 215 1.1 haya }; 216 1.1 haya 217 1.174 drochner static const struct cardbus_functions pccbb_funcs = { 218 1.22 chopps pccbb_rbus_cb_space_alloc, 219 1.22 chopps pccbb_rbus_cb_space_free, 220 1.26 haya pccbb_cb_intr_establish, 221 1.26 haya pccbb_cb_intr_disestablish, 222 1.22 chopps pccbb_ctrl, 223 1.160 dyoung pccbb_power_ct, 224 1.22 chopps pccbb_make_tag, 225 1.22 chopps pccbb_conf_read, 226 1.22 chopps pccbb_conf_write, 227 1.1 haya }; 228 1.1 haya 229 1.1 haya int 230 1.187 cegger pcicbbmatch(device_t parent, cfdata_t match, void *aux) 231 1.1 haya { 232 1.22 chopps struct pci_attach_args *pa = (struct pci_attach_args *)aux; 233 1.1 haya 234 1.22 chopps if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 235 1.22 chopps PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_CARDBUS && 236 1.22 chopps PCI_INTERFACE(pa->pa_class) == 0) { 237 1.22 chopps return 1; 238 1.22 chopps } 239 1.1 haya 240 1.22 chopps return 0; 241 1.1 haya } 242 1.1 haya 243 1.1 haya #define MAKEID(vendor, prod) (((vendor) << PCI_VENDOR_SHIFT) \ 244 1.1 haya | ((prod) << PCI_PRODUCT_SHIFT)) 245 1.1 haya 246 1.60 jdolecek const struct yenta_chipinfo { 247 1.22 chopps pcireg_t yc_id; /* vendor tag | product tag */ 248 1.22 chopps int yc_chiptype; 249 1.22 chopps int yc_flags; 250 1.1 haya } yc_chipsets[] = { 251 1.22 chopps /* Texas Instruments chips */ 252 1.22 chopps { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1130), CB_TI113X, 253 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 254 1.22 chopps { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1131), CB_TI113X, 255 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 256 1.96 nakayama { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1250), CB_TI125X, 257 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 258 1.22 chopps { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1220), CB_TI12XX, 259 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 260 1.22 chopps { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1221), CB_TI12XX, 261 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 262 1.22 chopps { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1225), CB_TI12XX, 263 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 264 1.96 nakayama { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251), CB_TI125X, 265 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 266 1.96 nakayama { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251B), CB_TI125X, 267 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 268 1.22 chopps { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1211), CB_TI12XX, 269 1.64 soren PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 270 1.64 soren { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1410), CB_TI12XX, 271 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 272 1.151 dyoung { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1420), CB_TI1420, 273 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 274 1.96 nakayama { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1450), CB_TI125X, 275 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 276 1.22 chopps { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1451), CB_TI12XX, 277 1.84 martin PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 278 1.200 phx { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1510), CB_TI12XX, 279 1.200 phx PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 280 1.99 he { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1520), CB_TI12XX, 281 1.99 he PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 282 1.84 martin { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI4410YENTA), CB_TI12XX, 283 1.22 chopps PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 284 1.99 he { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI4520YENTA), CB_TI12XX, 285 1.99 he PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 286 1.180 christos { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI7420YENTA), CB_TI12XX, 287 1.180 christos PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32}, 288 1.22 chopps 289 1.22 chopps /* Ricoh chips */ 290 1.22 chopps { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C475), CB_RX5C47X, 291 1.22 chopps PCCBB_PCMCIA_MEM_32}, 292 1.22 chopps { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RL5C476), CB_RX5C47X, 293 1.22 chopps PCCBB_PCMCIA_MEM_32}, 294 1.22 chopps { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C477), CB_RX5C47X, 295 1.22 chopps PCCBB_PCMCIA_MEM_32}, 296 1.22 chopps { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C478), CB_RX5C47X, 297 1.22 chopps PCCBB_PCMCIA_MEM_32}, 298 1.22 chopps { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C465), CB_RX5C46X, 299 1.22 chopps PCCBB_PCMCIA_MEM_32}, 300 1.22 chopps { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_Rx5C466), CB_RX5C46X, 301 1.22 chopps PCCBB_PCMCIA_MEM_32}, 302 1.22 chopps 303 1.22 chopps /* Toshiba products */ 304 1.22 chopps { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95), 305 1.22 chopps CB_TOPIC95, PCCBB_PCMCIA_MEM_32}, 306 1.22 chopps { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95B), 307 1.22 chopps CB_TOPIC95B, PCCBB_PCMCIA_MEM_32}, 308 1.22 chopps { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC97), 309 1.22 chopps CB_TOPIC97, PCCBB_PCMCIA_MEM_32}, 310 1.22 chopps { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC100), 311 1.22 chopps CB_TOPIC97, PCCBB_PCMCIA_MEM_32}, 312 1.22 chopps 313 1.22 chopps /* Cirrus Logic products */ 314 1.22 chopps { MAKEID(PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6832), 315 1.22 chopps CB_CIRRUS, PCCBB_PCMCIA_MEM_32}, 316 1.22 chopps { MAKEID(PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6833), 317 1.22 chopps CB_CIRRUS, PCCBB_PCMCIA_MEM_32}, 318 1.1 haya 319 1.169 dyoung /* O2 Micro products */ 320 1.169 dyoung { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6729), 321 1.169 dyoung CB_O2MICRO, PCCBB_PCMCIA_MEM_32}, 322 1.169 dyoung { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6730), 323 1.169 dyoung CB_O2MICRO, PCCBB_PCMCIA_MEM_32}, 324 1.169 dyoung { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6832), 325 1.169 dyoung CB_O2MICRO, PCCBB_PCMCIA_MEM_32}, 326 1.169 dyoung { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6836), 327 1.169 dyoung CB_O2MICRO, PCCBB_PCMCIA_MEM_32}, 328 1.169 dyoung { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6872), 329 1.169 dyoung CB_O2MICRO, PCCBB_PCMCIA_MEM_32}, 330 1.169 dyoung { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6922), 331 1.169 dyoung CB_O2MICRO, PCCBB_PCMCIA_MEM_32}, 332 1.169 dyoung { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6933), 333 1.169 dyoung CB_O2MICRO, PCCBB_PCMCIA_MEM_32}, 334 1.169 dyoung { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6972), 335 1.169 dyoung CB_O2MICRO, PCCBB_PCMCIA_MEM_32}, 336 1.179 dyoung { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_7223), 337 1.179 dyoung CB_O2MICRO, PCCBB_PCMCIA_MEM_32}, 338 1.169 dyoung 339 1.22 chopps /* sentinel, or Generic chip */ 340 1.22 chopps { 0 /* null id */ , CB_UNKNOWN, PCCBB_PCMCIA_MEM_32}, 341 1.1 haya }; 342 1.1 haya 343 1.1 haya static int 344 1.213 msaitoh cb_chipset(uint32_t pci_id, int *flagp) 345 1.1 haya { 346 1.60 jdolecek const struct yenta_chipinfo *yc; 347 1.1 haya 348 1.35 enami /* Loop over except the last default entry. */ 349 1.35 enami for (yc = yc_chipsets; yc < yc_chipsets + 350 1.168 dyoung __arraycount(yc_chipsets) - 1; yc++) 351 1.39 kleink if (pci_id == yc->yc_id) 352 1.35 enami break; 353 1.1 haya 354 1.35 enami if (flagp != NULL) 355 1.35 enami *flagp = yc->yc_flags; 356 1.1 haya 357 1.213 msaitoh return yc->yc_chiptype; 358 1.1 haya } 359 1.1 haya 360 1.1 haya void 361 1.188 dyoung pccbbchilddet(device_t self, device_t child) 362 1.188 dyoung { 363 1.188 dyoung struct pccbb_softc *sc = device_private(self); 364 1.188 dyoung int s; 365 1.188 dyoung 366 1.188 dyoung KASSERT(sc->sc_csc == device_private(child)); 367 1.188 dyoung 368 1.188 dyoung s = splbio(); 369 1.188 dyoung if (sc->sc_csc == device_private(child)) 370 1.188 dyoung sc->sc_csc = NULL; 371 1.188 dyoung splx(s); 372 1.188 dyoung } 373 1.188 dyoung 374 1.188 dyoung void 375 1.162 dyoung pccbbattach(device_t parent, device_t self, void *aux) 376 1.22 chopps { 377 1.162 dyoung struct pccbb_softc *sc = device_private(self); 378 1.22 chopps struct pci_attach_args *pa = aux; 379 1.22 chopps pci_chipset_tag_t pc = pa->pa_pc; 380 1.205 christos pcireg_t reg, sock_base; 381 1.22 chopps bus_addr_t sockbase; 382 1.22 chopps int flags; 383 1.22 chopps 384 1.88 nakayama #ifdef __HAVE_PCCBB_ATTACH_HOOK 385 1.88 nakayama pccbb_attach_hook(parent, self, pa); 386 1.88 nakayama #endif 387 1.88 nakayama 388 1.172 drochner sc->sc_dev = self; 389 1.172 drochner 390 1.189 dyoung mutex_init(&sc->sc_pwr_mtx, MUTEX_DEFAULT, IPL_BIO); 391 1.189 dyoung cv_init(&sc->sc_pwr_cv, "pccpwr"); 392 1.189 dyoung 393 1.149 joerg callout_init(&sc->sc_insert_ch, 0); 394 1.149 joerg callout_setfunc(&sc->sc_insert_ch, pci113x_insert, sc); 395 1.149 joerg 396 1.22 chopps sc->sc_chipset = cb_chipset(pa->pa_id, &flags); 397 1.22 chopps 398 1.204 drochner pci_aprint_devinfo(pa, NULL); 399 1.204 drochner DPRINTF(("(chipflags %x)", flags)); 400 1.1 haya 401 1.27 thorpej TAILQ_INIT(&sc->sc_memwindow); 402 1.27 thorpej TAILQ_INIT(&sc->sc_iowindow); 403 1.27 thorpej 404 1.22 chopps sc->sc_rbus_iot = rbus_pccbb_parent_io(pa); 405 1.22 chopps sc->sc_rbus_memt = rbus_pccbb_parent_mem(pa); 406 1.65 mcr 407 1.65 mcr #if 0 408 1.65 mcr printf("pa->pa_memt: %08x vs rbus_mem->rb_bt: %08x\n", 409 1.65 mcr pa->pa_memt, sc->sc_rbus_memt->rb_bt); 410 1.65 mcr #endif 411 1.1 haya 412 1.88 nakayama sc->sc_flags &= ~CBB_MEMHMAPPED; 413 1.1 haya 414 1.117 perry /* 415 1.22 chopps * MAP socket registers and ExCA registers on memory-space 416 1.22 chopps * When no valid address is set on socket base registers (on pci 417 1.22 chopps * config space), get it not polite way. 418 1.22 chopps */ 419 1.22 chopps sock_base = pci_conf_read(pc, pa->pa_tag, PCI_SOCKBASE); 420 1.22 chopps 421 1.22 chopps if (PCI_MAPREG_MEM_ADDR(sock_base) >= 0x100000 && 422 1.22 chopps PCI_MAPREG_MEM_ADDR(sock_base) != 0xfffffff0) { 423 1.22 chopps /* The address must be valid. */ 424 1.22 chopps if (pci_mapreg_map(pa, PCI_SOCKBASE, PCI_MAPREG_TYPE_MEM, 0, 425 1.210 msaitoh &sc->sc_base_memt, &sc->sc_base_memh, &sockbase, 426 1.210 msaitoh &sc->sc_base_size)) { 427 1.172 drochner aprint_error_dev(self, 428 1.164 dyoung "can't map socket base address 0x%lx\n", 429 1.164 dyoung (unsigned long)sock_base); 430 1.22 chopps /* 431 1.22 chopps * I think it's funny: socket base registers must be 432 1.22 chopps * mapped on memory space, but ... 433 1.22 chopps */ 434 1.213 msaitoh if (pci_mapreg_map(pa, PCI_SOCKBASE, 435 1.213 msaitoh PCI_MAPREG_TYPE_IO, 0, &sc->sc_base_memt, 436 1.213 msaitoh &sc->sc_base_memh, &sockbase, &sc->sc_base_size)) { 437 1.172 drochner aprint_error_dev(self, 438 1.164 dyoung "can't map socket base address" 439 1.190 blymn " 0x%lx: io mode\n", 440 1.63 jmc (unsigned long)sockbase); 441 1.22 chopps /* give up... allocate reg space via rbus. */ 442 1.22 chopps pci_conf_write(pc, pa->pa_tag, PCI_SOCKBASE, 0); 443 1.88 nakayama } else 444 1.88 nakayama sc->sc_flags |= CBB_MEMHMAPPED; 445 1.22 chopps } else { 446 1.22 chopps DPRINTF(("%s: socket base address 0x%lx\n", 447 1.213 msaitoh device_xname(self), (unsigned long)sockbase)); 448 1.88 nakayama sc->sc_flags |= CBB_MEMHMAPPED; 449 1.22 chopps } 450 1.22 chopps } 451 1.1 haya 452 1.22 chopps sc->sc_mem_start = 0; /* XXX */ 453 1.22 chopps sc->sc_mem_end = 0xffffffff; /* XXX */ 454 1.1 haya 455 1.22 chopps /* pccbb_machdep.c end */ 456 1.1 haya 457 1.1 haya #if defined CBB_DEBUG 458 1.22 chopps { 459 1.121 sekiya static const char *intrname[] = { "NON", "A", "B", "C", "D" }; 460 1.172 drochner aprint_debug_dev(self, "intrpin %s, intrtag %d\n", 461 1.23 cgd intrname[pa->pa_intrpin], pa->pa_intrline); 462 1.22 chopps } 463 1.1 haya #endif 464 1.1 haya 465 1.22 chopps /* setup softc */ 466 1.22 chopps sc->sc_pc = pc; 467 1.22 chopps sc->sc_iot = pa->pa_iot; 468 1.22 chopps sc->sc_memt = pa->pa_memt; 469 1.22 chopps sc->sc_dmat = pa->pa_dmat; 470 1.22 chopps sc->sc_tag = pa->pa_tag; 471 1.22 chopps 472 1.51 sommerfe memcpy(&sc->sc_pa, pa, sizeof(*pa)); 473 1.1 haya 474 1.22 chopps sc->sc_pcmcia_flags = flags; /* set PCMCIA facility */ 475 1.1 haya 476 1.43 jhawk /* Disable legacy register mapping. */ 477 1.43 jhawk switch (sc->sc_chipset) { 478 1.43 jhawk case CB_RX5C46X: /* fallthrough */ 479 1.43 jhawk #if 0 480 1.44 jhawk /* The RX5C47X-series requires writes to the PCI_LEGACY register. */ 481 1.43 jhawk case CB_RX5C47X: 482 1.43 jhawk #endif 483 1.117 perry /* 484 1.44 jhawk * The legacy pcic io-port on Ricoh RX5C46X CardBus bridges 485 1.44 jhawk * cannot be disabled by substituting 0 into PCI_LEGACY 486 1.44 jhawk * register. Ricoh CardBus bridges have special bits on Bridge 487 1.44 jhawk * control reg (addr 0x3e on PCI config space). 488 1.43 jhawk */ 489 1.146 dyoung reg = pci_conf_read(pc, pa->pa_tag, PCI_BRIDGE_CONTROL_REG); 490 1.43 jhawk reg &= ~(CB_BCRI_RL_3E0_ENA | CB_BCRI_RL_3E2_ENA); 491 1.146 dyoung pci_conf_write(pc, pa->pa_tag, PCI_BRIDGE_CONTROL_REG, reg); 492 1.43 jhawk break; 493 1.43 jhawk 494 1.43 jhawk default: 495 1.43 jhawk /* XXX I don't know proper way to kill legacy I/O. */ 496 1.43 jhawk pci_conf_write(pc, pa->pa_tag, PCI_LEGACY, 0x0); 497 1.43 jhawk break; 498 1.43 jhawk } 499 1.43 jhawk 500 1.156 jmcneill if (!pmf_device_register(self, pccbb_suspend, pccbb_resume)) 501 1.156 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 502 1.156 jmcneill 503 1.22 chopps config_defer(self, pccbb_pci_callback); 504 1.1 haya } 505 1.1 haya 506 1.158 dyoung int 507 1.158 dyoung pccbbdetach(device_t self, int flags) 508 1.158 dyoung { 509 1.158 dyoung struct pccbb_softc *sc = device_private(self); 510 1.158 dyoung pci_chipset_tag_t pc = sc->sc_pa.pa_pc; 511 1.158 dyoung bus_space_tag_t bmt = sc->sc_base_memt; 512 1.158 dyoung bus_space_handle_t bmh = sc->sc_base_memh; 513 1.158 dyoung uint32_t sockmask; 514 1.158 dyoung int rc; 515 1.158 dyoung 516 1.158 dyoung if ((rc = config_detach_children(self, flags)) != 0) 517 1.158 dyoung return rc; 518 1.158 dyoung 519 1.161 dyoung if (!LIST_EMPTY(&sc->sc_pil)) { 520 1.161 dyoung panic("%s: interrupt handlers still registered", 521 1.172 drochner device_xname(self)); 522 1.161 dyoung return EBUSY; 523 1.161 dyoung } 524 1.161 dyoung 525 1.158 dyoung if (sc->sc_ih != NULL) { 526 1.158 dyoung pci_intr_disestablish(pc, sc->sc_ih); 527 1.158 dyoung sc->sc_ih = NULL; 528 1.158 dyoung } 529 1.158 dyoung 530 1.158 dyoung /* CSC Interrupt: turn off card detect and power cycle interrupts */ 531 1.158 dyoung sockmask = bus_space_read_4(bmt, bmh, CB_SOCKET_MASK); 532 1.165 dyoung sockmask &= ~(CB_SOCKET_MASK_CSTS | CB_SOCKET_MASK_CD | 533 1.165 dyoung CB_SOCKET_MASK_POWER); 534 1.158 dyoung bus_space_write_4(bmt, bmh, CB_SOCKET_MASK, sockmask); 535 1.158 dyoung /* reset interrupt */ 536 1.158 dyoung bus_space_write_4(bmt, bmh, CB_SOCKET_EVENT, 537 1.158 dyoung bus_space_read_4(bmt, bmh, CB_SOCKET_EVENT)); 538 1.158 dyoung 539 1.158 dyoung switch (sc->sc_flags & (CBB_MEMHMAPPED|CBB_SPECMAPPED)) { 540 1.158 dyoung case CBB_MEMHMAPPED: 541 1.158 dyoung bus_space_unmap(bmt, bmh, sc->sc_base_size); 542 1.158 dyoung break; 543 1.158 dyoung case CBB_MEMHMAPPED|CBB_SPECMAPPED: 544 1.158 dyoung #if rbus 545 1.158 dyoung { 546 1.213 msaitoh rbus_space_free(sc->sc_rbus_memt, bmh, 0x1000, NULL); 547 1.158 dyoung } 548 1.158 dyoung #else 549 1.158 dyoung bus_space_free(bmt, bmh, 0x1000); 550 1.158 dyoung #endif 551 1.158 dyoung } 552 1.158 dyoung sc->sc_flags &= ~(CBB_MEMHMAPPED|CBB_SPECMAPPED); 553 1.26 haya 554 1.158 dyoung if (!TAILQ_EMPTY(&sc->sc_iowindow)) 555 1.208 nakayama aprint_error_dev(self, "i/o windows not empty\n"); 556 1.158 dyoung if (!TAILQ_EMPTY(&sc->sc_memwindow)) 557 1.208 nakayama aprint_error_dev(self, "memory windows not empty\n"); 558 1.26 haya 559 1.207 ozaki callout_halt(&sc->sc_insert_ch, NULL); 560 1.158 dyoung callout_destroy(&sc->sc_insert_ch); 561 1.191 blymn 562 1.191 blymn mutex_destroy(&sc->sc_pwr_mtx); 563 1.191 blymn cv_destroy(&sc->sc_pwr_cv); 564 1.191 blymn 565 1.158 dyoung return 0; 566 1.158 dyoung } 567 1.26 haya 568 1.26 haya /* 569 1.162 dyoung * static void pccbb_pci_callback(device_t self) 570 1.26 haya * 571 1.26 haya * The actual attach routine: get memory space for YENTA register 572 1.26 haya * space, setup YENTA register and route interrupt. 573 1.26 haya * 574 1.26 haya * This function should be deferred because this device may obtain 575 1.26 haya * memory space dynamically. This function must avoid obtaining 576 1.43 jhawk * memory area which has already kept for another device. 577 1.26 haya */ 578 1.1 haya static void 579 1.162 dyoung pccbb_pci_callback(device_t self) 580 1.1 haya { 581 1.162 dyoung struct pccbb_softc *sc = device_private(self); 582 1.22 chopps pci_chipset_tag_t pc = sc->sc_pc; 583 1.22 chopps bus_addr_t sockbase; 584 1.22 chopps struct cbslot_attach_args cba; 585 1.22 chopps struct pcmciabus_attach_args paa; 586 1.22 chopps struct cardslot_attach_args caa; 587 1.172 drochner device_t csc; 588 1.1 haya 589 1.88 nakayama if (!(sc->sc_flags & CBB_MEMHMAPPED)) { 590 1.22 chopps /* The socket registers aren't mapped correctly. */ 591 1.1 haya #if rbus 592 1.22 chopps if (rbus_space_alloc(sc->sc_rbus_memt, 0, 0x1000, 0x0fff, 593 1.22 chopps (sc->sc_chipset == CB_RX5C47X 594 1.22 chopps || sc->sc_chipset == CB_TI113X) ? 0x10000 : 0x1000, 595 1.22 chopps 0, &sockbase, &sc->sc_base_memh)) { 596 1.22 chopps return; 597 1.22 chopps } 598 1.22 chopps sc->sc_base_memt = sc->sc_memt; 599 1.22 chopps pci_conf_write(pc, sc->sc_tag, PCI_SOCKBASE, sockbase); 600 1.120 sekiya DPRINTF(("%s: CardBus register address 0x%lx -> 0x%lx\n", 601 1.172 drochner device_xname(self), (unsigned long)sockbase, 602 1.94 christos (unsigned long)pci_conf_read(pc, sc->sc_tag, 603 1.22 chopps PCI_SOCKBASE))); 604 1.1 haya #else 605 1.22 chopps sc->sc_base_memt = sc->sc_memt; 606 1.1 haya #if !defined CBB_PCI_BASE 607 1.1 haya #define CBB_PCI_BASE 0x20000000 608 1.1 haya #endif 609 1.22 chopps if (bus_space_alloc(sc->sc_base_memt, CBB_PCI_BASE, 0xffffffff, 610 1.22 chopps 0x1000, 0x1000, 0, 0, &sockbase, &sc->sc_base_memh)) { 611 1.22 chopps /* cannot allocate memory space */ 612 1.22 chopps return; 613 1.22 chopps } 614 1.22 chopps pci_conf_write(pc, sc->sc_tag, PCI_SOCKBASE, sockbase); 615 1.120 sekiya DPRINTF(("%s: CardBus register address 0x%lx -> 0x%lx\n", 616 1.172 drochner device_xname(self), (unsigned long)sock_base, 617 1.94 christos (unsigned long)pci_conf_read(pc, 618 1.22 chopps sc->sc_tag, PCI_SOCKBASE))); 619 1.1 haya #endif 620 1.186 dyoung sc->sc_flags |= CBB_MEMHMAPPED|CBB_SPECMAPPED; 621 1.22 chopps } 622 1.19 haya 623 1.165 dyoung /* clear data structure for child device interrupt handlers */ 624 1.165 dyoung LIST_INIT(&sc->sc_pil); 625 1.165 dyoung 626 1.32 enami /* bus bridge initialization */ 627 1.22 chopps pccbb_chipinit(sc); 628 1.1 haya 629 1.199 dyoung sc->sc_pil_intr_enable = true; 630 1.38 haya 631 1.22 chopps { 632 1.213 msaitoh uint32_t sockstat; 633 1.69 haya 634 1.69 haya sockstat = bus_space_read_4(sc->sc_base_memt, 635 1.69 haya sc->sc_base_memh, CB_SOCKET_STAT); 636 1.213 msaitoh if (0 == (sockstat & CB_SOCKET_STAT_CD)) 637 1.22 chopps sc->sc_flags |= CBB_CARDEXIST; 638 1.22 chopps } 639 1.1 haya 640 1.117 perry /* 641 1.117 perry * attach cardbus 642 1.22 chopps */ 643 1.98 mycroft { 644 1.22 chopps pcireg_t busreg = pci_conf_read(pc, sc->sc_tag, PCI_BUSNUM); 645 1.22 chopps pcireg_t bhlc = pci_conf_read(pc, sc->sc_tag, PCI_BHLC_REG); 646 1.22 chopps 647 1.32 enami /* initialize cbslot_attach */ 648 1.22 chopps cba.cba_iot = sc->sc_iot; 649 1.22 chopps cba.cba_memt = sc->sc_memt; 650 1.22 chopps cba.cba_dmat = sc->sc_dmat; 651 1.22 chopps cba.cba_bus = (busreg >> 8) & 0x0ff; 652 1.22 chopps cba.cba_cc = (void *)sc; 653 1.22 chopps cba.cba_cf = &pccbb_funcs; 654 1.1 haya 655 1.1 haya #if rbus 656 1.22 chopps cba.cba_rbus_iot = sc->sc_rbus_iot; 657 1.22 chopps cba.cba_rbus_memt = sc->sc_rbus_memt; 658 1.1 haya #endif 659 1.1 haya 660 1.22 chopps cba.cba_cacheline = PCI_CACHELINE(bhlc); 661 1.151 dyoung cba.cba_max_lattimer = PCI_LATTIMER(bhlc); 662 1.1 haya 663 1.213 msaitoh aprint_verbose_dev(self, "cacheline 0x%x lattimer 0x%x\n", 664 1.213 msaitoh cba.cba_cacheline, cba.cba_max_lattimer); 665 1.172 drochner aprint_verbose_dev(self, "bhlc 0x%x\n", bhlc); 666 1.1 haya #if defined SHOW_REGS 667 1.22 chopps cb_show_regs(sc->sc_pc, sc->sc_tag, sc->sc_base_memt, 668 1.22 chopps sc->sc_base_memh); 669 1.1 haya #endif 670 1.22 chopps } 671 1.1 haya 672 1.22 chopps pccbb_pcmcia_attach_setup(sc, &paa); 673 1.22 chopps caa.caa_cb_attach = NULL; 674 1.98 mycroft if (cba.cba_bus == 0) 675 1.172 drochner aprint_error_dev(self, 676 1.164 dyoung "secondary bus number uninitialized; try PCI_BUS_FIXUP\n"); 677 1.98 mycroft else 678 1.22 chopps caa.caa_cb_attach = &cba; 679 1.22 chopps caa.caa_16_attach = &paa; 680 1.1 haya 681 1.165 dyoung pccbb_intrinit(sc); 682 1.165 dyoung 683 1.216 thorpej if (NULL != (csc = config_found(self, &caa, cbbprint, 684 1.217 thorpej CFARGS(.iattr = "pcmciaslot")))) { 685 1.141 dyoung DPRINTF(("%s: found cardslot\n", __func__)); 686 1.172 drochner sc->sc_csc = device_private(csc); 687 1.22 chopps } 688 1.1 haya 689 1.22 chopps return; 690 1.1 haya } 691 1.1 haya 692 1.26 haya 693 1.26 haya 694 1.26 haya 695 1.26 haya 696 1.26 haya /* 697 1.26 haya * static void pccbb_chipinit(struct pccbb_softc *sc) 698 1.26 haya * 699 1.32 enami * This function initialize YENTA chip registers listed below: 700 1.26 haya * 1) PCI command reg, 701 1.26 haya * 2) PCI and CardBus latency timer, 702 1.43 jhawk * 3) route PCI interrupt, 703 1.43 jhawk * 4) close all memory and io windows. 704 1.69 haya * 5) turn off bus power. 705 1.118 christos * 6) card detect and power cycle interrupts on. 706 1.69 haya * 7) clear interrupt 707 1.26 haya */ 708 1.1 haya static void 709 1.143 dyoung pccbb_chipinit(struct pccbb_softc *sc) 710 1.1 haya { 711 1.22 chopps pci_chipset_tag_t pc = sc->sc_pc; 712 1.22 chopps pcitag_t tag = sc->sc_tag; 713 1.69 haya bus_space_tag_t bmt = sc->sc_base_memt; 714 1.69 haya bus_space_handle_t bmh = sc->sc_base_memh; 715 1.151 dyoung pcireg_t bcr, bhlc, cbctl, csr, lscp, mfunc, mrburst, slotctl, sockctl, 716 1.165 dyoung sysctrl; 717 1.22 chopps 718 1.117 perry /* 719 1.22 chopps * Set PCI command reg. 720 1.22 chopps * Some laptop's BIOSes (i.e. TICO) do not enable CardBus chip. 721 1.22 chopps */ 722 1.146 dyoung csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 723 1.30 mycroft /* I believe it is harmless. */ 724 1.146 dyoung csr |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE | 725 1.30 mycroft PCI_COMMAND_MASTER_ENABLE); 726 1.169 dyoung 727 1.169 dyoung /* All O2 Micro chips have broken parity-error reporting 728 1.169 dyoung * until proven otherwise. The OZ6933 PCI-CardBus Bridge 729 1.169 dyoung * is known to have the defect---see PR kern/38698. 730 1.169 dyoung */ 731 1.169 dyoung if (sc->sc_chipset != CB_O2MICRO) 732 1.169 dyoung csr |= PCI_COMMAND_PARITY_ENABLE; 733 1.169 dyoung 734 1.169 dyoung csr |= PCI_COMMAND_SERR_ENABLE; 735 1.146 dyoung pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr); 736 1.1 haya 737 1.117 perry /* 738 1.30 mycroft * Set CardBus latency timer. 739 1.22 chopps */ 740 1.146 dyoung lscp = pci_conf_read(pc, tag, PCI_CB_LSCP_REG); 741 1.146 dyoung if (PCI_CB_LATENCY(lscp) < 0x20) { 742 1.146 dyoung lscp &= ~(PCI_CB_LATENCY_MASK << PCI_CB_LATENCY_SHIFT); 743 1.146 dyoung lscp |= (0x20 << PCI_CB_LATENCY_SHIFT); 744 1.146 dyoung pci_conf_write(pc, tag, PCI_CB_LSCP_REG, lscp); 745 1.22 chopps } 746 1.30 mycroft DPRINTF(("CardBus latency timer 0x%x (%x)\n", 747 1.146 dyoung PCI_CB_LATENCY(lscp), pci_conf_read(pc, tag, PCI_CB_LSCP_REG))); 748 1.1 haya 749 1.117 perry /* 750 1.30 mycroft * Set PCI latency timer. 751 1.22 chopps */ 752 1.146 dyoung bhlc = pci_conf_read(pc, tag, PCI_BHLC_REG); 753 1.146 dyoung if (PCI_LATTIMER(bhlc) < 0x10) { 754 1.146 dyoung bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT); 755 1.146 dyoung bhlc |= (0x10 << PCI_LATTIMER_SHIFT); 756 1.146 dyoung pci_conf_write(pc, tag, PCI_BHLC_REG, bhlc); 757 1.22 chopps } 758 1.30 mycroft DPRINTF(("PCI latency timer 0x%x (%x)\n", 759 1.146 dyoung PCI_LATTIMER(bhlc), pci_conf_read(pc, tag, PCI_BHLC_REG))); 760 1.1 haya 761 1.1 haya 762 1.30 mycroft /* Route functional interrupts to PCI. */ 763 1.146 dyoung bcr = pci_conf_read(pc, tag, PCI_BRIDGE_CONTROL_REG); 764 1.146 dyoung bcr |= CB_BCR_INTR_IREQ_ENABLE; /* disable PCI Intr */ 765 1.146 dyoung bcr |= CB_BCR_WRITE_POST_ENABLE; /* enable write post */ 766 1.146 dyoung /* assert reset */ 767 1.214 msaitoh bcr |= PCI_BRIDGE_CONTROL_SECBR; 768 1.151 dyoung /* Set master abort mode to 1, forward SERR# from secondary 769 1.151 dyoung * to primary, and detect parity errors on secondary. 770 1.151 dyoung */ 771 1.214 msaitoh bcr |= PCI_BRIDGE_CONTROL_MABRT; 772 1.214 msaitoh bcr |= PCI_BRIDGE_CONTROL_SERR; 773 1.214 msaitoh bcr |= PCI_BRIDGE_CONTROL_PERE; 774 1.146 dyoung pci_conf_write(pc, tag, PCI_BRIDGE_CONTROL_REG, bcr); 775 1.1 haya 776 1.30 mycroft switch (sc->sc_chipset) { 777 1.30 mycroft case CB_TI113X: 778 1.146 dyoung cbctl = pci_conf_read(pc, tag, PCI_CBCTRL); 779 1.30 mycroft /* This bit is shared, but may read as 0 on some chips, so set 780 1.30 mycroft it explicitly on both functions. */ 781 1.146 dyoung cbctl |= PCI113X_CBCTRL_PCI_IRQ_ENA; 782 1.22 chopps /* CSC intr enable */ 783 1.146 dyoung cbctl |= PCI113X_CBCTRL_PCI_CSC; 784 1.45 haya /* functional intr prohibit | prohibit ISA routing */ 785 1.146 dyoung cbctl &= ~(PCI113X_CBCTRL_PCI_INTR | PCI113X_CBCTRL_INT_MASK); 786 1.146 dyoung pci_conf_write(pc, tag, PCI_CBCTRL, cbctl); 787 1.50 mycroft break; 788 1.50 mycroft 789 1.151 dyoung case CB_TI1420: 790 1.151 dyoung sysctrl = pci_conf_read(pc, tag, PCI_SYSCTRL); 791 1.151 dyoung mrburst = pccbb_burstup 792 1.151 dyoung ? PCI1420_SYSCTRL_MRBURST : PCI1420_SYSCTRL_MRBURSTDN; 793 1.151 dyoung if ((sysctrl & PCI1420_SYSCTRL_MRBURST) == mrburst) { 794 1.151 dyoung printf("%s: %swrite bursts enabled\n", 795 1.172 drochner device_xname(sc->sc_dev), 796 1.151 dyoung pccbb_burstup ? "read/" : ""); 797 1.151 dyoung } else if (pccbb_burstup) { 798 1.151 dyoung printf("%s: enabling read/write bursts\n", 799 1.172 drochner device_xname(sc->sc_dev)); 800 1.151 dyoung sysctrl |= PCI1420_SYSCTRL_MRBURST; 801 1.151 dyoung pci_conf_write(pc, tag, PCI_SYSCTRL, sysctrl); 802 1.151 dyoung } else { 803 1.151 dyoung printf("%s: disabling read bursts, " 804 1.151 dyoung "enabling write bursts\n", 805 1.172 drochner device_xname(sc->sc_dev)); 806 1.151 dyoung sysctrl |= PCI1420_SYSCTRL_MRBURSTDN; 807 1.151 dyoung sysctrl &= ~PCI1420_SYSCTRL_MRBURSTUP; 808 1.151 dyoung pci_conf_write(pc, tag, PCI_SYSCTRL, sysctrl); 809 1.151 dyoung } 810 1.151 dyoung /*FALLTHROUGH*/ 811 1.50 mycroft case CB_TI12XX: 812 1.96 nakayama /* 813 1.96 nakayama * Some TI 12xx (and [14][45]xx) based pci cards 814 1.96 nakayama * sometimes have issues with the MFUNC register not 815 1.96 nakayama * being initialized due to a bad EEPROM on board. 816 1.96 nakayama * Laptops that this matters on have this register 817 1.96 nakayama * properly initialized. 818 1.96 nakayama * 819 1.96 nakayama * The TI125X parts have a different register. 820 1.96 nakayama */ 821 1.146 dyoung mfunc = pci_conf_read(pc, tag, PCI12XX_MFUNC); 822 1.200 phx if ((mfunc & (PCI12XX_MFUNC_PIN0 | PCI12XX_MFUNC_PIN1)) == 0) { 823 1.200 phx /* Enable PCI interrupt /INTA */ 824 1.146 dyoung mfunc |= PCI12XX_MFUNC_PIN0_INTA; 825 1.200 phx 826 1.200 phx /* XXX this is TI1520 only */ 827 1.96 nakayama if ((pci_conf_read(pc, tag, PCI_SYSCTRL) & 828 1.200 phx PCI12XX_SYSCTRL_INTRTIE) == 0) 829 1.200 phx /* Enable PCI interrupt /INTB */ 830 1.146 dyoung mfunc |= PCI12XX_MFUNC_PIN1_INTB; 831 1.200 phx 832 1.146 dyoung pci_conf_write(pc, tag, PCI12XX_MFUNC, mfunc); 833 1.96 nakayama } 834 1.96 nakayama /* fallthrough */ 835 1.96 nakayama 836 1.96 nakayama case CB_TI125X: 837 1.96 nakayama /* 838 1.96 nakayama * Disable zoom video. Some machines initialize this 839 1.96 nakayama * improperly and experience has shown that this helps 840 1.96 nakayama * prevent strange behavior. 841 1.96 nakayama */ 842 1.96 nakayama pci_conf_write(pc, tag, PCI12XX_MMCTRL, 0); 843 1.96 nakayama 844 1.146 dyoung sysctrl = pci_conf_read(pc, tag, PCI_SYSCTRL); 845 1.146 dyoung sysctrl |= PCI12XX_SYSCTRL_VCCPROT; 846 1.146 dyoung pci_conf_write(pc, tag, PCI_SYSCTRL, sysctrl); 847 1.146 dyoung cbctl = pci_conf_read(pc, tag, PCI_CBCTRL); 848 1.146 dyoung cbctl |= PCI12XX_CBCTRL_CSC; 849 1.146 dyoung pci_conf_write(pc, tag, PCI_CBCTRL, cbctl); 850 1.30 mycroft break; 851 1.30 mycroft 852 1.30 mycroft case CB_TOPIC95B: 853 1.146 dyoung sockctl = pci_conf_read(pc, tag, TOPIC_SOCKET_CTRL); 854 1.146 dyoung sockctl |= TOPIC_SOCKET_CTRL_SCR_IRQSEL; 855 1.146 dyoung pci_conf_write(pc, tag, TOPIC_SOCKET_CTRL, sockctl); 856 1.146 dyoung slotctl = pci_conf_read(pc, tag, TOPIC_SLOT_CTRL); 857 1.67 haya DPRINTF(("%s: topic slot ctrl reg 0x%x -> ", 858 1.172 drochner device_xname(sc->sc_dev), slotctl)); 859 1.146 dyoung slotctl |= (TOPIC_SLOT_CTRL_SLOTON | TOPIC_SLOT_CTRL_SLOTEN | 860 1.67 haya TOPIC_SLOT_CTRL_ID_LOCK | TOPIC_SLOT_CTRL_CARDBUS); 861 1.146 dyoung slotctl &= ~TOPIC_SLOT_CTRL_SWDETECT; 862 1.146 dyoung DPRINTF(("0x%x\n", slotctl)); 863 1.146 dyoung pci_conf_write(pc, tag, TOPIC_SLOT_CTRL, slotctl); 864 1.67 haya break; 865 1.22 chopps 866 1.67 haya case CB_TOPIC97: 867 1.146 dyoung slotctl = pci_conf_read(pc, tag, TOPIC_SLOT_CTRL); 868 1.22 chopps DPRINTF(("%s: topic slot ctrl reg 0x%x -> ", 869 1.172 drochner device_xname(sc->sc_dev), slotctl)); 870 1.146 dyoung slotctl |= (TOPIC_SLOT_CTRL_SLOTON | TOPIC_SLOT_CTRL_SLOTEN | 871 1.30 mycroft TOPIC_SLOT_CTRL_ID_LOCK | TOPIC_SLOT_CTRL_CARDBUS); 872 1.146 dyoung slotctl &= ~TOPIC_SLOT_CTRL_SWDETECT; 873 1.146 dyoung slotctl |= TOPIC97_SLOT_CTRL_PCIINT; 874 1.146 dyoung slotctl &= ~(TOPIC97_SLOT_CTRL_STSIRQP | TOPIC97_SLOT_CTRL_IRQP); 875 1.146 dyoung DPRINTF(("0x%x\n", slotctl)); 876 1.146 dyoung pci_conf_write(pc, tag, TOPIC_SLOT_CTRL, slotctl); 877 1.69 haya /* make sure to assert LV card support bits */ 878 1.69 haya bus_space_write_1(sc->sc_base_memt, sc->sc_base_memh, 879 1.69 haya 0x800 + 0x3e, 880 1.69 haya bus_space_read_1(sc->sc_base_memt, sc->sc_base_memh, 881 1.69 haya 0x800 + 0x3e) | 0x03); 882 1.30 mycroft break; 883 1.22 chopps } 884 1.1 haya 885 1.30 mycroft /* Close all memory and I/O windows. */ 886 1.22 chopps pci_conf_write(pc, tag, PCI_CB_MEMBASE0, 0xffffffff); 887 1.22 chopps pci_conf_write(pc, tag, PCI_CB_MEMLIMIT0, 0); 888 1.22 chopps pci_conf_write(pc, tag, PCI_CB_MEMBASE1, 0xffffffff); 889 1.22 chopps pci_conf_write(pc, tag, PCI_CB_MEMLIMIT1, 0); 890 1.22 chopps pci_conf_write(pc, tag, PCI_CB_IOBASE0, 0xffffffff); 891 1.22 chopps pci_conf_write(pc, tag, PCI_CB_IOLIMIT0, 0); 892 1.22 chopps pci_conf_write(pc, tag, PCI_CB_IOBASE1, 0xffffffff); 893 1.22 chopps pci_conf_write(pc, tag, PCI_CB_IOLIMIT1, 0); 894 1.46 haya 895 1.46 haya /* reset 16-bit pcmcia bus */ 896 1.69 haya bus_space_write_1(bmt, bmh, 0x800 + PCIC_INTR, 897 1.69 haya bus_space_read_1(bmt, bmh, 0x800 + PCIC_INTR) & ~PCIC_INTR_RESET); 898 1.46 haya 899 1.69 haya /* turn off power */ 900 1.160 dyoung pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V); 901 1.165 dyoung } 902 1.165 dyoung 903 1.165 dyoung static void 904 1.165 dyoung pccbb_intrinit(struct pccbb_softc *sc) 905 1.165 dyoung { 906 1.165 dyoung pcireg_t sockmask; 907 1.165 dyoung const char *intrstr = NULL; 908 1.165 dyoung pci_intr_handle_t ih; 909 1.165 dyoung pci_chipset_tag_t pc = sc->sc_pc; 910 1.165 dyoung bus_space_tag_t bmt = sc->sc_base_memt; 911 1.165 dyoung bus_space_handle_t bmh = sc->sc_base_memh; 912 1.206 christos char intrbuf[PCI_INTRSTR_LEN]; 913 1.165 dyoung 914 1.165 dyoung /* Map and establish the interrupt. */ 915 1.165 dyoung if (pci_intr_map(&sc->sc_pa, &ih)) { 916 1.172 drochner aprint_error_dev(sc->sc_dev, "couldn't map interrupt\n"); 917 1.165 dyoung return; 918 1.165 dyoung } 919 1.206 christos intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf)); 920 1.165 dyoung 921 1.165 dyoung /* 922 1.165 dyoung * XXX pccbbintr should be called under the priority lower 923 1.184 msaitoh * than any other hard interrupts. 924 1.165 dyoung */ 925 1.165 dyoung KASSERT(sc->sc_ih == NULL); 926 1.211 msaitoh sc->sc_ih = pci_intr_establish_xname(pc, ih, IPL_BIO, pccbbintr, sc, 927 1.211 msaitoh device_xname(sc->sc_dev)); 928 1.165 dyoung 929 1.165 dyoung if (sc->sc_ih == NULL) { 930 1.172 drochner aprint_error_dev(sc->sc_dev, "couldn't establish interrupt"); 931 1.165 dyoung if (intrstr != NULL) 932 1.165 dyoung aprint_error(" at %s\n", intrstr); 933 1.165 dyoung else 934 1.165 dyoung aprint_error("\n"); 935 1.165 dyoung return; 936 1.165 dyoung } 937 1.165 dyoung 938 1.172 drochner aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr); 939 1.69 haya 940 1.118 christos /* CSC Interrupt: Card detect and power cycle interrupts on */ 941 1.146 dyoung sockmask = bus_space_read_4(bmt, bmh, CB_SOCKET_MASK); 942 1.165 dyoung sockmask |= CB_SOCKET_MASK_CSTS | CB_SOCKET_MASK_CD | 943 1.165 dyoung CB_SOCKET_MASK_POWER; 944 1.146 dyoung bus_space_write_4(bmt, bmh, CB_SOCKET_MASK, sockmask); 945 1.69 haya /* reset interrupt */ 946 1.69 haya bus_space_write_4(bmt, bmh, CB_SOCKET_EVENT, 947 1.69 haya bus_space_read_4(bmt, bmh, CB_SOCKET_EVENT)); 948 1.1 haya } 949 1.1 haya 950 1.4 haya /* 951 1.26 haya * STATIC void pccbb_pcmcia_attach_setup(struct pccbb_softc *sc, 952 1.26 haya * struct pcmciabus_attach_args *paa) 953 1.26 haya * 954 1.26 haya * This function attaches 16-bit PCcard bus. 955 1.4 haya */ 956 1.1 haya STATIC void 957 1.143 dyoung pccbb_pcmcia_attach_setup(struct pccbb_softc *sc, 958 1.143 dyoung struct pcmciabus_attach_args *paa) 959 1.1 haya { 960 1.31 mycroft /* 961 1.31 mycroft * We need to do a few things here: 962 1.31 mycroft * 1) Disable routing of CSC and functional interrupts to ISA IRQs by 963 1.31 mycroft * setting the IRQ numbers to 0. 964 1.31 mycroft * 2) Set bit 4 of PCIC_INTR, which is needed on some chips to enable 965 1.31 mycroft * routing of CSC interrupts (e.g. card removal) to PCI while in 966 1.31 mycroft * PCMCIA mode. We just leave this set all the time. 967 1.31 mycroft * 3) Enable card insertion/removal interrupts in case the chip also 968 1.31 mycroft * needs that while in PCMCIA mode. 969 1.31 mycroft * 4) Clear any pending CSC interrupt. 970 1.31 mycroft */ 971 1.177 drochner Pcic_write(sc, PCIC_INTR, PCIC_INTR_ENABLE); 972 1.45 haya if (sc->sc_chipset == CB_TI113X) { 973 1.177 drochner Pcic_write(sc, PCIC_CSC_INTR, 0); 974 1.45 haya } else { 975 1.177 drochner Pcic_write(sc, PCIC_CSC_INTR, PCIC_CSC_INTR_CD_ENABLE); 976 1.177 drochner Pcic_read(sc, PCIC_CSC); 977 1.45 haya } 978 1.22 chopps 979 1.32 enami /* initialize pcmcia bus attachment */ 980 1.22 chopps paa->paa_busname = "pcmcia"; 981 1.177 drochner paa->pct = &pccbb_pcmcia_funcs; 982 1.177 drochner paa->pch = sc; 983 1.22 chopps return; 984 1.1 haya } 985 1.1 haya 986 1.4 haya /* 987 1.4 haya * int pccbbintr(arg) 988 1.4 haya * void *arg; 989 1.4 haya * This routine handles the interrupt from Yenta PCI-CardBus bridge 990 1.4 haya * itself. 991 1.4 haya */ 992 1.1 haya int 993 1.143 dyoung pccbbintr(void *arg) 994 1.1 haya { 995 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)arg; 996 1.188 dyoung struct cardslot_softc *csc; 997 1.213 msaitoh uint32_t sockevent, sockstate; 998 1.22 chopps bus_space_tag_t memt = sc->sc_base_memt; 999 1.22 chopps bus_space_handle_t memh = sc->sc_base_memh; 1000 1.22 chopps 1001 1.172 drochner if (!device_has_power(sc->sc_dev)) 1002 1.165 dyoung return 0; 1003 1.165 dyoung 1004 1.22 chopps sockevent = bus_space_read_4(memt, memh, CB_SOCKET_EVENT); 1005 1.31 mycroft bus_space_write_4(memt, memh, CB_SOCKET_EVENT, sockevent); 1006 1.177 drochner Pcic_read(sc, PCIC_CSC); 1007 1.31 mycroft 1008 1.152 dyoung if (sockevent != 0) { 1009 1.201 jruoho DPRINTF(("%s: enter sockevent %" PRIx32 "\n", 1010 1.201 jruoho __func__, sockevent)); 1011 1.152 dyoung } 1012 1.152 dyoung 1013 1.182 dyoung /* XXX sockevent == CB_SOCKET_EVENT_CSTS|CB_SOCKET_EVENT_POWER 1014 1.182 dyoung * does occur in the wild. Check for a _POWER event before 1015 1.182 dyoung * possibly exiting because of an _CSTS event. 1016 1.182 dyoung */ 1017 1.182 dyoung if (sockevent & CB_SOCKET_EVENT_POWER) { 1018 1.182 dyoung DPRINTF(("Powercycling because of socket event\n")); 1019 1.182 dyoung /* XXX: Does not happen when attaching a 16-bit card */ 1020 1.189 dyoung mutex_enter(&sc->sc_pwr_mtx); 1021 1.182 dyoung sc->sc_pwrcycle++; 1022 1.189 dyoung cv_signal(&sc->sc_pwr_cv); 1023 1.189 dyoung mutex_exit(&sc->sc_pwr_mtx); 1024 1.182 dyoung } 1025 1.182 dyoung 1026 1.152 dyoung /* Sometimes a change of CSTSCHG# accompanies the first 1027 1.152 dyoung * interrupt from an Atheros WLAN. That generates a 1028 1.152 dyoung * CB_SOCKET_EVENT_CSTS event on the bridge. The event 1029 1.152 dyoung * isn't interesting to pccbb(4), so we used to ignore the 1030 1.152 dyoung * interrupt. Now, let the child devices try to handle 1031 1.152 dyoung * the interrupt, instead. The Atheros NIC produces 1032 1.152 dyoung * interrupts more reliably, now: used to be that it would 1033 1.152 dyoung * only interrupt if the driver avoided powering down the 1034 1.152 dyoung * NIC's cardslot, and then the NIC would only work after 1035 1.152 dyoung * it was reset a second time. 1036 1.152 dyoung */ 1037 1.152 dyoung if (sockevent == 0 || 1038 1.152 dyoung (sockevent & ~(CB_SOCKET_EVENT_POWER|CB_SOCKET_EVENT_CD)) != 0) { 1039 1.22 chopps /* This intr is not for me: it may be for my child devices. */ 1040 1.38 haya if (sc->sc_pil_intr_enable) { 1041 1.38 haya return pccbbintr_function(sc); 1042 1.38 haya } else { 1043 1.38 haya return 0; 1044 1.38 haya } 1045 1.22 chopps } 1046 1.1 haya 1047 1.22 chopps if (sockevent & CB_SOCKET_EVENT_CD) { 1048 1.31 mycroft sockstate = bus_space_read_4(memt, memh, CB_SOCKET_STAT); 1049 1.90 msaitoh if (0x00 != (sockstate & CB_SOCKET_STAT_CD)) { 1050 1.22 chopps /* A card should be removed. */ 1051 1.22 chopps if (sc->sc_flags & CBB_CARDEXIST) { 1052 1.164 dyoung DPRINTF(("%s: 0x%08x", 1053 1.172 drochner device_xname(sc->sc_dev), sockevent)); 1054 1.22 chopps DPRINTF((" card removed, 0x%08x\n", sockstate)); 1055 1.22 chopps sc->sc_flags &= ~CBB_CARDEXIST; 1056 1.188 dyoung if ((csc = sc->sc_csc) == NULL) 1057 1.188 dyoung ; 1058 1.188 dyoung else if (csc->sc_status & 1059 1.33 enami CARDSLOT_STATUS_CARD_16) { 1060 1.188 dyoung cardslot_event_throw(csc, 1061 1.22 chopps CARDSLOT_EVENT_REMOVAL_16); 1062 1.188 dyoung } else if (csc->sc_status & 1063 1.33 enami CARDSLOT_STATUS_CARD_CB) { 1064 1.22 chopps /* Cardbus intr removed */ 1065 1.188 dyoung cardslot_event_throw(csc, 1066 1.22 chopps CARDSLOT_EVENT_REMOVAL_CB); 1067 1.22 chopps } 1068 1.74 haya } else if (sc->sc_flags & CBB_INSERTING) { 1069 1.74 haya sc->sc_flags &= ~CBB_INSERTING; 1070 1.74 haya callout_stop(&sc->sc_insert_ch); 1071 1.22 chopps } 1072 1.34 enami } else if (0x00 == (sockstate & CB_SOCKET_STAT_CD) && 1073 1.34 enami /* 1074 1.34 enami * The pccbbintr may called from powerdown hook when 1075 1.34 enami * the system resumed, to detect the card 1076 1.34 enami * insertion/removal during suspension. 1077 1.34 enami */ 1078 1.34 enami (sc->sc_flags & CBB_CARDEXIST) == 0) { 1079 1.22 chopps if (sc->sc_flags & CBB_INSERTING) { 1080 1.37 thorpej callout_stop(&sc->sc_insert_ch); 1081 1.22 chopps } 1082 1.189 dyoung callout_schedule(&sc->sc_insert_ch, mstohz(200)); 1083 1.22 chopps sc->sc_flags |= CBB_INSERTING; 1084 1.22 chopps } 1085 1.22 chopps } 1086 1.1 haya 1087 1.213 msaitoh return 1; 1088 1.1 haya } 1089 1.1 haya 1090 1.21 haya /* 1091 1.21 haya * static int pccbbintr_function(struct pccbb_softc *sc) 1092 1.21 haya * 1093 1.21 haya * This function calls each interrupt handler registered at the 1094 1.32 enami * bridge. The interrupt handlers are called in registered order. 1095 1.21 haya */ 1096 1.21 haya static int 1097 1.143 dyoung pccbbintr_function(struct pccbb_softc *sc) 1098 1.21 haya { 1099 1.22 chopps int retval = 0, val; 1100 1.22 chopps struct pccbb_intrhand_list *pil; 1101 1.138 yamt int s; 1102 1.21 haya 1103 1.159 dyoung LIST_FOREACH(pil, &sc->sc_pil, pil_next) { 1104 1.138 yamt s = splraiseipl(pil->pil_icookie); 1105 1.41 haya val = (*pil->pil_func)(pil->pil_arg); 1106 1.138 yamt splx(s); 1107 1.41 haya 1108 1.22 chopps retval = retval == 1 ? 1 : 1109 1.22 chopps retval == 0 ? val : val != 0 ? val : retval; 1110 1.22 chopps } 1111 1.21 haya 1112 1.22 chopps return retval; 1113 1.21 haya } 1114 1.21 haya 1115 1.1 haya static void 1116 1.143 dyoung pci113x_insert(void *arg) 1117 1.1 haya { 1118 1.172 drochner struct pccbb_softc *sc = arg; 1119 1.188 dyoung struct cardslot_softc *csc; 1120 1.213 msaitoh uint32_t sockevent, sockstate; 1121 1.74 haya 1122 1.74 haya if (!(sc->sc_flags & CBB_INSERTING)) { 1123 1.74 haya /* We add a card only under inserting state. */ 1124 1.74 haya return; 1125 1.74 haya } 1126 1.74 haya sc->sc_flags &= ~CBB_INSERTING; 1127 1.1 haya 1128 1.22 chopps sockevent = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh, 1129 1.22 chopps CB_SOCKET_EVENT); 1130 1.22 chopps sockstate = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh, 1131 1.22 chopps CB_SOCKET_STAT); 1132 1.22 chopps 1133 1.22 chopps if (0 == (sockstate & CB_SOCKET_STAT_CD)) { /* card exist */ 1134 1.205 christos #ifdef CBB_DEBUG 1135 1.172 drochner DPRINTF(("%s: 0x%08x", device_xname(sc->sc_dev), sockevent)); 1136 1.205 christos #else 1137 1.205 christos __USE(sockevent); 1138 1.205 christos #endif 1139 1.205 christos 1140 1.22 chopps DPRINTF((" card inserted, 0x%08x\n", sockstate)); 1141 1.22 chopps sc->sc_flags |= CBB_CARDEXIST; 1142 1.32 enami /* call pccard interrupt handler here */ 1143 1.188 dyoung if ((csc = sc->sc_csc) == NULL) 1144 1.188 dyoung ; 1145 1.188 dyoung else if (sockstate & CB_SOCKET_STAT_16BIT) { 1146 1.22 chopps /* 16-bit card found */ 1147 1.188 dyoung cardslot_event_throw(csc, CARDSLOT_EVENT_INSERTION_16); 1148 1.22 chopps } else if (sockstate & CB_SOCKET_STAT_CB) { 1149 1.32 enami /* cardbus card found */ 1150 1.188 dyoung cardslot_event_throw(csc, CARDSLOT_EVENT_INSERTION_CB); 1151 1.22 chopps } else { 1152 1.22 chopps /* who are you? */ 1153 1.22 chopps } 1154 1.213 msaitoh } else 1155 1.189 dyoung callout_schedule(&sc->sc_insert_ch, mstohz(100)); 1156 1.1 haya } 1157 1.1 haya 1158 1.1 haya #define PCCBB_PCMCIA_OFFSET 0x800 1159 1.213 msaitoh static uint8_t 1160 1.173 drochner pccbb_pcmcia_read(struct pccbb_softc *sc, int reg) 1161 1.1 haya { 1162 1.173 drochner bus_space_barrier(sc->sc_base_memt, sc->sc_base_memh, 1163 1.48 haya PCCBB_PCMCIA_OFFSET + reg, 1, BUS_SPACE_BARRIER_READ); 1164 1.48 haya 1165 1.173 drochner return bus_space_read_1(sc->sc_base_memt, sc->sc_base_memh, 1166 1.22 chopps PCCBB_PCMCIA_OFFSET + reg); 1167 1.1 haya } 1168 1.1 haya 1169 1.1 haya static void 1170 1.213 msaitoh pccbb_pcmcia_write(struct pccbb_softc *sc, int reg, uint8_t val) 1171 1.1 haya { 1172 1.173 drochner bus_space_write_1(sc->sc_base_memt, sc->sc_base_memh, 1173 1.173 drochner PCCBB_PCMCIA_OFFSET + reg, val); 1174 1.48 haya 1175 1.173 drochner bus_space_barrier(sc->sc_base_memt, sc->sc_base_memh, 1176 1.48 haya PCCBB_PCMCIA_OFFSET + reg, 1, BUS_SPACE_BARRIER_WRITE); 1177 1.1 haya } 1178 1.1 haya 1179 1.4 haya /* 1180 1.4 haya * STATIC int pccbb_ctrl(cardbus_chipset_tag_t, int) 1181 1.4 haya */ 1182 1.1 haya STATIC int 1183 1.143 dyoung pccbb_ctrl(cardbus_chipset_tag_t ct, int command) 1184 1.1 haya { 1185 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)ct; 1186 1.1 haya 1187 1.22 chopps switch (command) { 1188 1.22 chopps case CARDBUS_CD: 1189 1.22 chopps if (2 == pccbb_detect_card(sc)) { 1190 1.22 chopps int retval = 0; 1191 1.22 chopps int status = cb_detect_voltage(sc); 1192 1.22 chopps if (PCCARD_VCC_5V & status) { 1193 1.22 chopps retval |= CARDBUS_5V_CARD; 1194 1.22 chopps } 1195 1.22 chopps if (PCCARD_VCC_3V & status) { 1196 1.22 chopps retval |= CARDBUS_3V_CARD; 1197 1.22 chopps } 1198 1.22 chopps if (PCCARD_VCC_XV & status) { 1199 1.22 chopps retval |= CARDBUS_XV_CARD; 1200 1.22 chopps } 1201 1.22 chopps if (PCCARD_VCC_YV & status) { 1202 1.22 chopps retval |= CARDBUS_YV_CARD; 1203 1.22 chopps } 1204 1.22 chopps return retval; 1205 1.22 chopps } else { 1206 1.22 chopps return 0; 1207 1.22 chopps } 1208 1.22 chopps case CARDBUS_RESET: 1209 1.22 chopps return cb_reset(sc); 1210 1.22 chopps case CARDBUS_IO_ENABLE: /* fallthrough */ 1211 1.22 chopps case CARDBUS_IO_DISABLE: /* fallthrough */ 1212 1.22 chopps case CARDBUS_MEM_ENABLE: /* fallthrough */ 1213 1.22 chopps case CARDBUS_MEM_DISABLE: /* fallthrough */ 1214 1.22 chopps case CARDBUS_BM_ENABLE: /* fallthrough */ 1215 1.22 chopps case CARDBUS_BM_DISABLE: /* fallthrough */ 1216 1.69 haya /* XXX: I think we don't need to call this function below. */ 1217 1.22 chopps return pccbb_cardenable(sc, command); 1218 1.22 chopps } 1219 1.1 haya 1220 1.22 chopps return 0; 1221 1.1 haya } 1222 1.1 haya 1223 1.160 dyoung STATIC int 1224 1.160 dyoung pccbb_power_ct(cardbus_chipset_tag_t ct, int command) 1225 1.160 dyoung { 1226 1.160 dyoung struct pccbb_softc *sc = (struct pccbb_softc *)ct; 1227 1.160 dyoung 1228 1.160 dyoung return pccbb_power(sc, command); 1229 1.160 dyoung } 1230 1.160 dyoung 1231 1.4 haya /* 1232 1.4 haya * STATIC int pccbb_power(cardbus_chipset_tag_t, int) 1233 1.4 haya * This function returns true when it succeeds and returns false when 1234 1.4 haya * it fails. 1235 1.4 haya */ 1236 1.1 haya STATIC int 1237 1.160 dyoung pccbb_power(struct pccbb_softc *sc, int command) 1238 1.1 haya { 1239 1.213 msaitoh uint32_t status, osock_ctrl, sock_ctrl, reg_ctrl; 1240 1.22 chopps bus_space_tag_t memt = sc->sc_base_memt; 1241 1.22 chopps bus_space_handle_t memh = sc->sc_base_memh; 1242 1.189 dyoung int on = 0, pwrcycle, times; 1243 1.144 dyoung struct timeval before, after, diff; 1244 1.22 chopps 1245 1.95 christos DPRINTF(("pccbb_power: %s and %s [0x%x]\n", 1246 1.22 chopps (command & CARDBUS_VCCMASK) == CARDBUS_VCC_UC ? "CARDBUS_VCC_UC" : 1247 1.22 chopps (command & CARDBUS_VCCMASK) == CARDBUS_VCC_5V ? "CARDBUS_VCC_5V" : 1248 1.22 chopps (command & CARDBUS_VCCMASK) == CARDBUS_VCC_3V ? "CARDBUS_VCC_3V" : 1249 1.22 chopps (command & CARDBUS_VCCMASK) == CARDBUS_VCC_XV ? "CARDBUS_VCC_XV" : 1250 1.22 chopps (command & CARDBUS_VCCMASK) == CARDBUS_VCC_YV ? "CARDBUS_VCC_YV" : 1251 1.22 chopps (command & CARDBUS_VCCMASK) == CARDBUS_VCC_0V ? "CARDBUS_VCC_0V" : 1252 1.22 chopps "UNKNOWN", 1253 1.22 chopps (command & CARDBUS_VPPMASK) == CARDBUS_VPP_UC ? "CARDBUS_VPP_UC" : 1254 1.22 chopps (command & CARDBUS_VPPMASK) == CARDBUS_VPP_12V ? "CARDBUS_VPP_12V" : 1255 1.22 chopps (command & CARDBUS_VPPMASK) == CARDBUS_VPP_VCC ? "CARDBUS_VPP_VCC" : 1256 1.22 chopps (command & CARDBUS_VPPMASK) == CARDBUS_VPP_0V ? "CARDBUS_VPP_0V" : 1257 1.22 chopps "UNKNOWN", command)); 1258 1.22 chopps 1259 1.22 chopps status = bus_space_read_4(memt, memh, CB_SOCKET_STAT); 1260 1.144 dyoung osock_ctrl = sock_ctrl = bus_space_read_4(memt, memh, CB_SOCKET_CTRL); 1261 1.22 chopps 1262 1.22 chopps switch (command & CARDBUS_VCCMASK) { 1263 1.22 chopps case CARDBUS_VCC_UC: 1264 1.22 chopps break; 1265 1.22 chopps case CARDBUS_VCC_5V: 1266 1.111 mycroft on++; 1267 1.22 chopps if (CB_SOCKET_STAT_5VCARD & status) { /* check 5 V card */ 1268 1.22 chopps sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK; 1269 1.22 chopps sock_ctrl |= CB_SOCKET_CTRL_VCC_5V; 1270 1.22 chopps } else { 1271 1.172 drochner aprint_error_dev(sc->sc_dev, 1272 1.164 dyoung "BAD voltage request: no 5 V card\n"); 1273 1.91 briggs return 0; 1274 1.22 chopps } 1275 1.22 chopps break; 1276 1.22 chopps case CARDBUS_VCC_3V: 1277 1.111 mycroft on++; 1278 1.22 chopps if (CB_SOCKET_STAT_3VCARD & status) { 1279 1.22 chopps sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK; 1280 1.22 chopps sock_ctrl |= CB_SOCKET_CTRL_VCC_3V; 1281 1.22 chopps } else { 1282 1.172 drochner aprint_error_dev(sc->sc_dev, 1283 1.164 dyoung "BAD voltage request: no 3.3 V card\n"); 1284 1.91 briggs return 0; 1285 1.22 chopps } 1286 1.22 chopps break; 1287 1.22 chopps case CARDBUS_VCC_0V: 1288 1.22 chopps sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK; 1289 1.22 chopps break; 1290 1.22 chopps default: 1291 1.22 chopps return 0; /* power NEVER changed */ 1292 1.22 chopps } 1293 1.1 haya 1294 1.22 chopps switch (command & CARDBUS_VPPMASK) { 1295 1.22 chopps case CARDBUS_VPP_UC: 1296 1.22 chopps break; 1297 1.22 chopps case CARDBUS_VPP_0V: 1298 1.22 chopps sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK; 1299 1.22 chopps break; 1300 1.22 chopps case CARDBUS_VPP_VCC: 1301 1.22 chopps sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK; 1302 1.22 chopps sock_ctrl |= ((sock_ctrl >> 4) & 0x07); 1303 1.22 chopps break; 1304 1.22 chopps case CARDBUS_VPP_12V: 1305 1.22 chopps sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK; 1306 1.22 chopps sock_ctrl |= CB_SOCKET_CTRL_VPP_12V; 1307 1.22 chopps break; 1308 1.22 chopps } 1309 1.172 drochner aprint_debug_dev(sc->sc_dev, "osock_ctrl %#" PRIx32 1310 1.164 dyoung " sock_ctrl %#" PRIx32 "\n", osock_ctrl, sock_ctrl); 1311 1.111 mycroft 1312 1.144 dyoung microtime(&before); 1313 1.189 dyoung mutex_enter(&sc->sc_pwr_mtx); 1314 1.189 dyoung pwrcycle = sc->sc_pwrcycle; 1315 1.189 dyoung 1316 1.22 chopps bus_space_write_4(memt, memh, CB_SOCKET_CTRL, sock_ctrl); 1317 1.111 mycroft 1318 1.144 dyoung /* 1319 1.144 dyoung * Wait as long as 200ms for a power-cycle interrupt. If 1320 1.144 dyoung * interrupts are enabled, but the socket has already 1321 1.144 dyoung * changed to the desired status, keep waiting for the 1322 1.144 dyoung * interrupt. "Consuming" the interrupt in this way keeps 1323 1.144 dyoung * the interrupt from prematurely waking some subsequent 1324 1.144 dyoung * pccbb_power call. 1325 1.144 dyoung * 1326 1.144 dyoung * XXX Not every bridge interrupts on the ->OFF transition. 1327 1.144 dyoung * XXX That's ok, we will time-out after 200ms. 1328 1.144 dyoung * 1329 1.144 dyoung * XXX The power cycle event will never happen when attaching 1330 1.144 dyoung * XXX a 16-bit card. That's ok, we will time-out after 1331 1.144 dyoung * XXX 200ms. 1332 1.144 dyoung */ 1333 1.144 dyoung for (times = 5; --times >= 0; ) { 1334 1.144 dyoung if (cold) 1335 1.144 dyoung DELAY(40 * 1000); 1336 1.144 dyoung else { 1337 1.189 dyoung (void)cv_timedwait(&sc->sc_pwr_cv, &sc->sc_pwr_mtx, 1338 1.189 dyoung mstohz(40)); 1339 1.144 dyoung if (pwrcycle == sc->sc_pwrcycle) 1340 1.144 dyoung continue; 1341 1.118 christos } 1342 1.144 dyoung status = bus_space_read_4(memt, memh, CB_SOCKET_STAT); 1343 1.144 dyoung if ((status & CB_SOCKET_STAT_PWRCYCLE) != 0 && on) 1344 1.144 dyoung break; 1345 1.144 dyoung if ((status & CB_SOCKET_STAT_PWRCYCLE) == 0 && !on) 1346 1.144 dyoung break; 1347 1.144 dyoung } 1348 1.189 dyoung mutex_exit(&sc->sc_pwr_mtx); 1349 1.144 dyoung microtime(&after); 1350 1.144 dyoung timersub(&after, &before, &diff); 1351 1.181 christos aprint_debug_dev(sc->sc_dev, "wait took%s %lld.%06lds\n", 1352 1.181 christos (on && times < 0) ? " too long" : "", (long long)diff.tv_sec, 1353 1.181 christos (long)diff.tv_usec); 1354 1.133 christos 1355 1.144 dyoung /* 1356 1.144 dyoung * Ok, wait a bit longer for things to settle. 1357 1.144 dyoung */ 1358 1.144 dyoung if (on && sc->sc_chipset == CB_TOPIC95B) 1359 1.144 dyoung delay_ms(100, sc); 1360 1.111 mycroft 1361 1.22 chopps status = bus_space_read_4(memt, memh, CB_SOCKET_STAT); 1362 1.1 haya 1363 1.132 christos if (on && sc->sc_chipset != CB_TOPIC95B) { 1364 1.111 mycroft if ((status & CB_SOCKET_STAT_PWRCYCLE) == 0) 1365 1.172 drochner aprint_error_dev(sc->sc_dev, "power on failed?\n"); 1366 1.111 mycroft } 1367 1.111 mycroft 1368 1.22 chopps if (status & CB_SOCKET_STAT_BADVCC) { /* bad Vcc request */ 1369 1.172 drochner aprint_error_dev(sc->sc_dev, 1370 1.164 dyoung "bad Vcc request. sock_ctrl 0x%x, sock_status 0x%x\n", 1371 1.164 dyoung sock_ctrl, status); 1372 1.172 drochner aprint_error_dev(sc->sc_dev, "disabling socket\n"); 1373 1.104 mycroft sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK; 1374 1.104 mycroft sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK; 1375 1.104 mycroft bus_space_write_4(memt, memh, CB_SOCKET_CTRL, sock_ctrl); 1376 1.111 mycroft status &= ~CB_SOCKET_STAT_BADVCC; 1377 1.145 christos bus_space_write_4(memt, memh, CB_SOCKET_FORCE, status); 1378 1.104 mycroft printf("new status 0x%x\n", bus_space_read_4(memt, memh, 1379 1.104 mycroft CB_SOCKET_STAT)); 1380 1.22 chopps return 0; 1381 1.77 mycroft } 1382 1.77 mycroft 1383 1.77 mycroft if (sc->sc_chipset == CB_TOPIC97) { 1384 1.77 mycroft reg_ctrl = pci_conf_read(sc->sc_pc, sc->sc_tag, TOPIC_REG_CTRL); 1385 1.77 mycroft reg_ctrl &= ~TOPIC97_REG_CTRL_TESTMODE; 1386 1.77 mycroft if ((command & CARDBUS_VCCMASK) == CARDBUS_VCC_0V) 1387 1.77 mycroft reg_ctrl &= ~TOPIC97_REG_CTRL_CLKRUN_ENA; 1388 1.77 mycroft else 1389 1.77 mycroft reg_ctrl |= TOPIC97_REG_CTRL_CLKRUN_ENA; 1390 1.77 mycroft pci_conf_write(sc->sc_pc, sc->sc_tag, TOPIC_REG_CTRL, reg_ctrl); 1391 1.22 chopps } 1392 1.48 haya 1393 1.22 chopps return 1; /* power changed correctly */ 1394 1.1 haya } 1395 1.1 haya 1396 1.4 haya /* 1397 1.4 haya * static int pccbb_detect_card(struct pccbb_softc *sc) 1398 1.4 haya * return value: 0 if no card exists. 1399 1.4 haya * 1 if 16-bit card exists. 1400 1.4 haya * 2 if cardbus card exists. 1401 1.4 haya */ 1402 1.1 haya static int 1403 1.143 dyoung pccbb_detect_card(struct pccbb_softc *sc) 1404 1.1 haya { 1405 1.22 chopps bus_space_handle_t base_memh = sc->sc_base_memh; 1406 1.22 chopps bus_space_tag_t base_memt = sc->sc_base_memt; 1407 1.213 msaitoh uint32_t sockstat = 1408 1.22 chopps bus_space_read_4(base_memt, base_memh, CB_SOCKET_STAT); 1409 1.22 chopps int retval = 0; 1410 1.22 chopps 1411 1.22 chopps /* CD1 and CD2 asserted */ 1412 1.22 chopps if (0x00 == (sockstat & CB_SOCKET_STAT_CD)) { 1413 1.22 chopps /* card must be present */ 1414 1.22 chopps if (!(CB_SOCKET_STAT_NOTCARD & sockstat)) { 1415 1.22 chopps /* NOTACARD DEASSERTED */ 1416 1.22 chopps if (CB_SOCKET_STAT_CB & sockstat) { 1417 1.22 chopps /* CardBus mode */ 1418 1.22 chopps retval = 2; 1419 1.22 chopps } else if (CB_SOCKET_STAT_16BIT & sockstat) { 1420 1.22 chopps /* 16-bit mode */ 1421 1.22 chopps retval = 1; 1422 1.22 chopps } 1423 1.22 chopps } 1424 1.22 chopps } 1425 1.22 chopps return retval; 1426 1.1 haya } 1427 1.1 haya 1428 1.4 haya /* 1429 1.4 haya * STATIC int cb_reset(struct pccbb_softc *sc) 1430 1.4 haya * This function resets CardBus card. 1431 1.4 haya */ 1432 1.1 haya STATIC int 1433 1.143 dyoung cb_reset(struct pccbb_softc *sc) 1434 1.1 haya { 1435 1.117 perry /* 1436 1.117 perry * Reset Assert at least 20 ms 1437 1.22 chopps * Some machines request longer duration. 1438 1.22 chopps */ 1439 1.22 chopps int reset_duration = 1440 1.136 itohy (sc->sc_chipset == CB_RX5C47X ? 400 : 50); 1441 1.213 msaitoh uint32_t bcr = pci_conf_read(sc->sc_pc, sc->sc_tag, 1442 1.210 msaitoh PCI_BRIDGE_CONTROL_REG); 1443 1.153 dyoung aprint_debug("%s: enter bcr %" PRIx32 "\n", __func__, bcr); 1444 1.22 chopps 1445 1.40 haya /* Reset bit Assert (bit 6 at 0x3E) */ 1446 1.214 msaitoh bcr |= PCI_BRIDGE_CONTROL_SECBR; 1447 1.146 dyoung pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BRIDGE_CONTROL_REG, bcr); 1448 1.153 dyoung aprint_debug("%s: wrote bcr %" PRIx32 "\n", __func__, bcr); 1449 1.142 dyoung delay_ms(reset_duration, sc); 1450 1.22 chopps 1451 1.22 chopps if (CBB_CARDEXIST & sc->sc_flags) { /* A card exists. Reset it! */ 1452 1.40 haya /* Reset bit Deassert (bit 6 at 0x3E) */ 1453 1.214 msaitoh bcr &= ~(PCI_BRIDGE_CONTROL_SECBR); 1454 1.153 dyoung pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BRIDGE_CONTROL_REG, 1455 1.153 dyoung bcr); 1456 1.153 dyoung aprint_debug("%s: wrote bcr %" PRIx32 "\n", __func__, bcr); 1457 1.142 dyoung delay_ms(reset_duration, sc); 1458 1.153 dyoung aprint_debug("%s: end of delay\n", __func__); 1459 1.22 chopps } 1460 1.22 chopps /* No card found on the slot. Keep Reset. */ 1461 1.22 chopps return 1; 1462 1.1 haya } 1463 1.1 haya 1464 1.4 haya /* 1465 1.4 haya * STATIC int cb_detect_voltage(struct pccbb_softc *sc) 1466 1.4 haya * This function detect card Voltage. 1467 1.4 haya */ 1468 1.1 haya STATIC int 1469 1.143 dyoung cb_detect_voltage(struct pccbb_softc *sc) 1470 1.1 haya { 1471 1.213 msaitoh uint32_t psr; /* socket present-state reg */ 1472 1.22 chopps bus_space_tag_t iot = sc->sc_base_memt; 1473 1.22 chopps bus_space_handle_t ioh = sc->sc_base_memh; 1474 1.22 chopps int vol = PCCARD_VCC_UKN; /* set 0 */ 1475 1.22 chopps 1476 1.22 chopps psr = bus_space_read_4(iot, ioh, CB_SOCKET_STAT); 1477 1.1 haya 1478 1.213 msaitoh if (0x400u & psr) 1479 1.22 chopps vol |= PCCARD_VCC_5V; 1480 1.213 msaitoh 1481 1.213 msaitoh if (0x800u & psr) 1482 1.22 chopps vol |= PCCARD_VCC_3V; 1483 1.1 haya 1484 1.22 chopps return vol; 1485 1.1 haya } 1486 1.1 haya 1487 1.1 haya STATIC int 1488 1.137 christos cbbprint(void *aux, const char *pcic) 1489 1.1 haya { 1490 1.135 christos #if 0 1491 1.135 christos struct cbslot_attach_args *cba = aux; 1492 1.1 haya 1493 1.213 msaitoh if (cba->cba_slot >= 0) 1494 1.135 christos aprint_normal(" slot %d", cba->cba_slot); 1495 1.135 christos #endif 1496 1.22 chopps return UNCONF; 1497 1.1 haya } 1498 1.1 haya 1499 1.4 haya /* 1500 1.4 haya * STATIC int pccbb_cardenable(struct pccbb_softc *sc, int function) 1501 1.4 haya * This function enables and disables the card 1502 1.4 haya */ 1503 1.1 haya STATIC int 1504 1.143 dyoung pccbb_cardenable(struct pccbb_softc *sc, int function) 1505 1.1 haya { 1506 1.213 msaitoh uint32_t command = 1507 1.22 chopps pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG); 1508 1.1 haya 1509 1.22 chopps DPRINTF(("pccbb_cardenable:")); 1510 1.22 chopps switch (function) { 1511 1.22 chopps case CARDBUS_IO_ENABLE: 1512 1.22 chopps command |= PCI_COMMAND_IO_ENABLE; 1513 1.22 chopps break; 1514 1.22 chopps case CARDBUS_IO_DISABLE: 1515 1.22 chopps command &= ~PCI_COMMAND_IO_ENABLE; 1516 1.22 chopps break; 1517 1.22 chopps case CARDBUS_MEM_ENABLE: 1518 1.22 chopps command |= PCI_COMMAND_MEM_ENABLE; 1519 1.22 chopps break; 1520 1.22 chopps case CARDBUS_MEM_DISABLE: 1521 1.22 chopps command &= ~PCI_COMMAND_MEM_ENABLE; 1522 1.22 chopps break; 1523 1.22 chopps case CARDBUS_BM_ENABLE: 1524 1.22 chopps command |= PCI_COMMAND_MASTER_ENABLE; 1525 1.22 chopps break; 1526 1.22 chopps case CARDBUS_BM_DISABLE: 1527 1.22 chopps command &= ~PCI_COMMAND_MASTER_ENABLE; 1528 1.22 chopps break; 1529 1.22 chopps default: 1530 1.22 chopps return 0; 1531 1.22 chopps } 1532 1.1 haya 1533 1.22 chopps pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, command); 1534 1.22 chopps DPRINTF((" command reg 0x%x\n", command)); 1535 1.22 chopps return 1; 1536 1.1 haya } 1537 1.1 haya 1538 1.1 haya #if !rbus 1539 1.1 haya static int 1540 1.143 dyoung pccbb_io_open(cardbus_chipset_tag_t ct, int win, uint32_t start, uint32_t end) 1541 1.22 chopps { 1542 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)ct; 1543 1.22 chopps int basereg; 1544 1.22 chopps int limitreg; 1545 1.1 haya 1546 1.22 chopps if ((win < 0) || (win > 2)) { 1547 1.1 haya #if defined DIAGNOSTIC 1548 1.22 chopps printf("cardbus_io_open: window out of range %d\n", win); 1549 1.1 haya #endif 1550 1.22 chopps return 0; 1551 1.22 chopps } 1552 1.1 haya 1553 1.161 dyoung basereg = win * 8 + PCI_CB_IOBASE0; 1554 1.161 dyoung limitreg = win * 8 + PCI_CB_IOLIMIT0; 1555 1.1 haya 1556 1.22 chopps DPRINTF(("pccbb_io_open: 0x%x[0x%x] - 0x%x[0x%x]\n", 1557 1.22 chopps start, basereg, end, limitreg)); 1558 1.1 haya 1559 1.22 chopps pci_conf_write(sc->sc_pc, sc->sc_tag, basereg, start); 1560 1.22 chopps pci_conf_write(sc->sc_pc, sc->sc_tag, limitreg, end); 1561 1.22 chopps return 1; 1562 1.1 haya } 1563 1.22 chopps 1564 1.4 haya /* 1565 1.4 haya * int pccbb_io_close(cardbus_chipset_tag_t, int) 1566 1.4 haya */ 1567 1.1 haya static int 1568 1.143 dyoung pccbb_io_close(cardbus_chipset_tag_t ct, int win) 1569 1.1 haya { 1570 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)ct; 1571 1.22 chopps int basereg; 1572 1.22 chopps int limitreg; 1573 1.1 haya 1574 1.22 chopps if ((win < 0) || (win > 2)) { 1575 1.1 haya #if defined DIAGNOSTIC 1576 1.22 chopps printf("cardbus_io_close: window out of range %d\n", win); 1577 1.1 haya #endif 1578 1.22 chopps return 0; 1579 1.22 chopps } 1580 1.1 haya 1581 1.161 dyoung basereg = win * 8 + PCI_CB_IOBASE0; 1582 1.161 dyoung limitreg = win * 8 + PCI_CB_IOLIMIT0; 1583 1.1 haya 1584 1.22 chopps pci_conf_write(sc->sc_pc, sc->sc_tag, basereg, 0); 1585 1.22 chopps pci_conf_write(sc->sc_pc, sc->sc_tag, limitreg, 0); 1586 1.22 chopps return 1; 1587 1.1 haya } 1588 1.1 haya 1589 1.1 haya static int 1590 1.143 dyoung pccbb_mem_open(cardbus_chipset_tag_t ct, int win, uint32_t start, uint32_t end) 1591 1.22 chopps { 1592 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)ct; 1593 1.22 chopps int basereg; 1594 1.22 chopps int limitreg; 1595 1.1 haya 1596 1.22 chopps if ((win < 0) || (win > 2)) { 1597 1.1 haya #if defined DIAGNOSTIC 1598 1.22 chopps printf("cardbus_mem_open: window out of range %d\n", win); 1599 1.1 haya #endif 1600 1.22 chopps return 0; 1601 1.22 chopps } 1602 1.1 haya 1603 1.161 dyoung basereg = win * 8 + PCI_CB_MEMBASE0; 1604 1.161 dyoung limitreg = win * 8 + PCI_CB_MEMLIMIT0; 1605 1.1 haya 1606 1.22 chopps pci_conf_write(sc->sc_pc, sc->sc_tag, basereg, start); 1607 1.22 chopps pci_conf_write(sc->sc_pc, sc->sc_tag, limitreg, end); 1608 1.22 chopps return 1; 1609 1.1 haya } 1610 1.1 haya 1611 1.1 haya static int 1612 1.143 dyoung pccbb_mem_close(cardbus_chipset_tag_t ct, int win) 1613 1.1 haya { 1614 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)ct; 1615 1.22 chopps int basereg; 1616 1.22 chopps int limitreg; 1617 1.1 haya 1618 1.22 chopps if ((win < 0) || (win > 2)) { 1619 1.1 haya #if defined DIAGNOSTIC 1620 1.22 chopps printf("cardbus_mem_close: window out of range %d\n", win); 1621 1.1 haya #endif 1622 1.22 chopps return 0; 1623 1.22 chopps } 1624 1.1 haya 1625 1.161 dyoung basereg = win * 8 + PCI_CB_MEMBASE0; 1626 1.161 dyoung limitreg = win * 8 + PCI_CB_MEMLIMIT0; 1627 1.1 haya 1628 1.22 chopps pci_conf_write(sc->sc_pc, sc->sc_tag, basereg, 0); 1629 1.22 chopps pci_conf_write(sc->sc_pc, sc->sc_tag, limitreg, 0); 1630 1.22 chopps return 1; 1631 1.1 haya } 1632 1.1 haya #endif 1633 1.1 haya 1634 1.21 haya /* 1635 1.26 haya * static void *pccbb_cb_intr_establish(cardbus_chipset_tag_t ct, 1636 1.26 haya * int level, 1637 1.116 perry * int (* func)(void *), 1638 1.26 haya * void *arg) 1639 1.26 haya * 1640 1.26 haya * This function registers an interrupt handler at the bridge, in 1641 1.32 enami * order not to call the interrupt handlers of child devices when 1642 1.32 enami * a card-deletion interrupt occurs. 1643 1.26 haya * 1644 1.203 drochner * The argument level is not used. 1645 1.26 haya */ 1646 1.26 haya static void * 1647 1.203 drochner pccbb_cb_intr_establish(cardbus_chipset_tag_t ct, int level, 1648 1.203 drochner int (*func)(void *), void *arg) 1649 1.26 haya { 1650 1.26 haya struct pccbb_softc *sc = (struct pccbb_softc *)ct; 1651 1.26 haya 1652 1.203 drochner return pccbb_intr_establish(sc, level, func, arg); 1653 1.26 haya } 1654 1.26 haya 1655 1.26 haya 1656 1.26 haya /* 1657 1.26 haya * static void *pccbb_cb_intr_disestablish(cardbus_chipset_tag_t ct, 1658 1.26 haya * void *ih) 1659 1.26 haya * 1660 1.26 haya * This function removes an interrupt handler pointed by ih. 1661 1.26 haya */ 1662 1.26 haya static void 1663 1.143 dyoung pccbb_cb_intr_disestablish(cardbus_chipset_tag_t ct, void *ih) 1664 1.26 haya { 1665 1.26 haya struct pccbb_softc *sc = (struct pccbb_softc *)ct; 1666 1.26 haya 1667 1.26 haya pccbb_intr_disestablish(sc, ih); 1668 1.26 haya } 1669 1.26 haya 1670 1.26 haya 1671 1.65 mcr void 1672 1.143 dyoung pccbb_intr_route(struct pccbb_softc *sc) 1673 1.65 mcr { 1674 1.143 dyoung pcireg_t bcr, cbctrl; 1675 1.65 mcr 1676 1.143 dyoung /* initialize bridge intr routing */ 1677 1.146 dyoung bcr = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BRIDGE_CONTROL_REG); 1678 1.143 dyoung bcr &= ~CB_BCR_INTR_IREQ_ENABLE; 1679 1.146 dyoung pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BRIDGE_CONTROL_REG, bcr); 1680 1.143 dyoung 1681 1.143 dyoung switch (sc->sc_chipset) { 1682 1.143 dyoung case CB_TI113X: 1683 1.143 dyoung cbctrl = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL); 1684 1.143 dyoung /* functional intr enabled */ 1685 1.143 dyoung cbctrl |= PCI113X_CBCTRL_PCI_INTR; 1686 1.143 dyoung pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, cbctrl); 1687 1.143 dyoung break; 1688 1.143 dyoung default: 1689 1.143 dyoung break; 1690 1.143 dyoung } 1691 1.65 mcr } 1692 1.65 mcr 1693 1.26 haya /* 1694 1.26 haya * static void *pccbb_intr_establish(struct pccbb_softc *sc, 1695 1.21 haya * int irq, 1696 1.21 haya * int level, 1697 1.116 perry * int (* func)(void *), 1698 1.21 haya * void *arg) 1699 1.21 haya * 1700 1.21 haya * This function registers an interrupt handler at the bridge, in 1701 1.32 enami * order not to call the interrupt handlers of child devices when 1702 1.32 enami * a card-deletion interrupt occurs. 1703 1.21 haya * 1704 1.21 haya */ 1705 1.1 haya static void * 1706 1.203 drochner pccbb_intr_establish(struct pccbb_softc *sc, int level, 1707 1.203 drochner int (*func)(void *), void *arg) 1708 1.22 chopps { 1709 1.22 chopps struct pccbb_intrhand_list *pil, *newpil; 1710 1.22 chopps 1711 1.81 onoe DPRINTF(("pccbb_intr_establish start. %p\n", LIST_FIRST(&sc->sc_pil))); 1712 1.26 haya 1713 1.213 msaitoh if (LIST_EMPTY(&sc->sc_pil)) 1714 1.80 haya pccbb_intr_route(sc); 1715 1.22 chopps 1716 1.117 perry /* 1717 1.32 enami * Allocate a room for interrupt handler structure. 1718 1.22 chopps */ 1719 1.22 chopps if (NULL == (newpil = 1720 1.22 chopps (struct pccbb_intrhand_list *)malloc(sizeof(struct 1721 1.22 chopps pccbb_intrhand_list), M_DEVBUF, M_WAITOK))) { 1722 1.22 chopps return NULL; 1723 1.22 chopps } 1724 1.21 haya 1725 1.22 chopps newpil->pil_func = func; 1726 1.22 chopps newpil->pil_arg = arg; 1727 1.138 yamt newpil->pil_icookie = makeiplcookie(level); 1728 1.21 haya 1729 1.80 haya if (LIST_EMPTY(&sc->sc_pil)) { 1730 1.80 haya LIST_INSERT_HEAD(&sc->sc_pil, newpil, pil_next); 1731 1.22 chopps } else { 1732 1.80 haya for (pil = LIST_FIRST(&sc->sc_pil); 1733 1.80 haya LIST_NEXT(pil, pil_next) != NULL; 1734 1.80 haya pil = LIST_NEXT(pil, pil_next)); 1735 1.80 haya LIST_INSERT_AFTER(pil, newpil, pil_next); 1736 1.21 haya } 1737 1.1 haya 1738 1.81 onoe DPRINTF(("pccbb_intr_establish add pil. %p\n", 1739 1.81 onoe LIST_FIRST(&sc->sc_pil))); 1740 1.26 haya 1741 1.22 chopps return newpil; 1742 1.1 haya } 1743 1.1 haya 1744 1.21 haya /* 1745 1.26 haya * static void *pccbb_intr_disestablish(struct pccbb_softc *sc, 1746 1.21 haya * void *ih) 1747 1.21 haya * 1748 1.80 haya * This function removes an interrupt handler pointed by ih. ih 1749 1.80 haya * should be the value returned by cardbus_intr_establish() or 1750 1.80 haya * NULL. 1751 1.80 haya * 1752 1.80 haya * When ih is NULL, this function will do nothing. 1753 1.21 haya */ 1754 1.1 haya static void 1755 1.143 dyoung pccbb_intr_disestablish(struct pccbb_softc *sc, void *ih) 1756 1.1 haya { 1757 1.80 haya struct pccbb_intrhand_list *pil; 1758 1.48 haya pcireg_t reg; 1759 1.21 haya 1760 1.81 onoe DPRINTF(("pccbb_intr_disestablish start. %p\n", 1761 1.81 onoe LIST_FIRST(&sc->sc_pil))); 1762 1.26 haya 1763 1.80 haya if (ih == NULL) { 1764 1.80 haya /* intr handler is not set */ 1765 1.80 haya DPRINTF(("pccbb_intr_disestablish: no ih\n")); 1766 1.80 haya return; 1767 1.80 haya } 1768 1.22 chopps 1769 1.80 haya #ifdef DIAGNOSTIC 1770 1.159 dyoung LIST_FOREACH(pil, &sc->sc_pil, pil_next) { 1771 1.83 atatat DPRINTF(("pccbb_intr_disestablish: pil %p\n", pil)); 1772 1.22 chopps if (pil == ih) { 1773 1.26 haya DPRINTF(("pccbb_intr_disestablish frees one pil\n")); 1774 1.22 chopps break; 1775 1.22 chopps } 1776 1.21 haya } 1777 1.80 haya if (pil == NULL) { 1778 1.80 haya panic("pccbb_intr_disestablish: %s cannot find pil %p", 1779 1.172 drochner device_xname(sc->sc_dev), ih); 1780 1.80 haya } 1781 1.80 haya #endif 1782 1.80 haya 1783 1.80 haya pil = (struct pccbb_intrhand_list *)ih; 1784 1.80 haya LIST_REMOVE(pil, pil_next); 1785 1.80 haya free(pil, M_DEVBUF); 1786 1.80 haya DPRINTF(("pccbb_intr_disestablish frees one pil\n")); 1787 1.21 haya 1788 1.80 haya if (LIST_EMPTY(&sc->sc_pil)) { 1789 1.22 chopps /* No interrupt handlers */ 1790 1.21 haya 1791 1.26 haya DPRINTF(("pccbb_intr_disestablish: no interrupt handler\n")); 1792 1.26 haya 1793 1.48 haya /* stop routing PCI intr */ 1794 1.210 msaitoh reg = pci_conf_read(sc->sc_pc, sc->sc_tag, 1795 1.210 msaitoh PCI_BRIDGE_CONTROL_REG); 1796 1.48 haya reg |= CB_BCR_INTR_IREQ_ENABLE; 1797 1.210 msaitoh pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BRIDGE_CONTROL_REG, 1798 1.210 msaitoh reg); 1799 1.48 haya 1800 1.22 chopps switch (sc->sc_chipset) { 1801 1.22 chopps case CB_TI113X: 1802 1.48 haya reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL); 1803 1.48 haya /* functional intr disabled */ 1804 1.48 haya reg &= ~PCI113X_CBCTRL_PCI_INTR; 1805 1.48 haya pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, reg); 1806 1.48 haya break; 1807 1.22 chopps default: 1808 1.22 chopps break; 1809 1.22 chopps } 1810 1.21 haya } 1811 1.1 haya } 1812 1.1 haya 1813 1.1 haya #if defined SHOW_REGS 1814 1.1 haya static void 1815 1.143 dyoung cb_show_regs(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt, 1816 1.143 dyoung bus_space_handle_t memh) 1817 1.22 chopps { 1818 1.22 chopps int i; 1819 1.22 chopps printf("PCI config regs:"); 1820 1.22 chopps for (i = 0; i < 0x50; i += 4) { 1821 1.143 dyoung if (i % 16 == 0) 1822 1.22 chopps printf("\n 0x%02x:", i); 1823 1.22 chopps printf(" %08x", pci_conf_read(pc, tag, i)); 1824 1.22 chopps } 1825 1.22 chopps for (i = 0x80; i < 0xb0; i += 4) { 1826 1.143 dyoung if (i % 16 == 0) 1827 1.22 chopps printf("\n 0x%02x:", i); 1828 1.22 chopps printf(" %08x", pci_conf_read(pc, tag, i)); 1829 1.22 chopps } 1830 1.1 haya 1831 1.22 chopps if (memh == 0) { 1832 1.22 chopps printf("\n"); 1833 1.22 chopps return; 1834 1.22 chopps } 1835 1.1 haya 1836 1.22 chopps printf("\nsocket regs:"); 1837 1.143 dyoung for (i = 0; i <= 0x10; i += 0x04) 1838 1.22 chopps printf(" %08x", bus_space_read_4(memt, memh, i)); 1839 1.22 chopps printf("\nExCA regs:"); 1840 1.143 dyoung for (i = 0; i < 0x08; ++i) 1841 1.22 chopps printf(" %02x", bus_space_read_1(memt, memh, 0x800 + i)); 1842 1.22 chopps printf("\n"); 1843 1.22 chopps return; 1844 1.1 haya } 1845 1.1 haya #endif 1846 1.1 haya 1847 1.4 haya /* 1848 1.195 dyoung * static pcitag_t pccbb_make_tag(cardbus_chipset_tag_t cc, 1849 1.125 drochner * int busno, int function) 1850 1.4 haya * This is the function to make a tag to access config space of 1851 1.4 haya * a CardBus Card. It works same as pci_conf_read. 1852 1.4 haya */ 1853 1.195 dyoung static pcitag_t 1854 1.143 dyoung pccbb_make_tag(cardbus_chipset_tag_t cc, int busno, int function) 1855 1.1 haya { 1856 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)cc; 1857 1.1 haya 1858 1.125 drochner return pci_make_tag(sc->sc_pc, busno, 0, function); 1859 1.1 haya } 1860 1.1 haya 1861 1.4 haya /* 1862 1.143 dyoung * pccbb_conf_read 1863 1.143 dyoung * 1864 1.143 dyoung * This is the function to read the config space of a CardBus card. 1865 1.143 dyoung * It works the same as pci_conf_read(9). 1866 1.4 haya */ 1867 1.195 dyoung static pcireg_t 1868 1.195 dyoung pccbb_conf_read(cardbus_chipset_tag_t cc, pcitag_t tag, int offset) 1869 1.1 haya { 1870 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)cc; 1871 1.178 drochner pcitag_t brtag = sc->sc_tag; 1872 1.195 dyoung pcireg_t reg; 1873 1.1 haya 1874 1.178 drochner /* 1875 1.178 drochner * clear cardbus master abort status; it is OK to write without 1876 1.178 drochner * reading before because all bits are r/o or w1tc 1877 1.178 drochner */ 1878 1.178 drochner pci_conf_write(sc->sc_pc, brtag, PCI_CBB_SECSTATUS, 1879 1.178 drochner CBB_SECSTATUS_CBMABORT); 1880 1.178 drochner reg = pci_conf_read(sc->sc_pc, tag, offset); 1881 1.178 drochner /* check cardbus master abort status */ 1882 1.178 drochner if (pci_conf_read(sc->sc_pc, brtag, PCI_CBB_SECSTATUS) 1883 1.178 drochner & CBB_SECSTATUS_CBMABORT) 1884 1.213 msaitoh return 0xffffffff; 1885 1.178 drochner return reg; 1886 1.1 haya } 1887 1.1 haya 1888 1.4 haya /* 1889 1.143 dyoung * pccbb_conf_write 1890 1.143 dyoung * 1891 1.143 dyoung * This is the function to write the config space of a CardBus 1892 1.143 dyoung * card. It works the same as pci_conf_write(9). 1893 1.4 haya */ 1894 1.1 haya static void 1895 1.195 dyoung pccbb_conf_write(cardbus_chipset_tag_t cc, pcitag_t tag, int reg, pcireg_t val) 1896 1.1 haya { 1897 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)cc; 1898 1.1 haya 1899 1.22 chopps pci_conf_write(sc->sc_pc, tag, reg, val); 1900 1.1 haya } 1901 1.1 haya 1902 1.1 haya #if 0 1903 1.1 haya STATIC int 1904 1.1 haya pccbb_new_pcmcia_io_alloc(pcmcia_chipset_handle_t pch, 1905 1.22 chopps bus_addr_t start, bus_size_t size, bus_size_t align, bus_addr_t mask, 1906 1.22 chopps int speed, int flags, 1907 1.22 chopps bus_space_handle_t * iohp) 1908 1.1 haya #endif 1909 1.4 haya /* 1910 1.4 haya * STATIC int pccbb_pcmcia_io_alloc(pcmcia_chipset_handle_t pch, 1911 1.4 haya * bus_addr_t start, bus_size_t size, 1912 1.4 haya * bus_size_t align, 1913 1.4 haya * struct pcmcia_io_handle *pcihp 1914 1.4 haya * 1915 1.4 haya * This function only allocates I/O region for pccard. This function 1916 1.32 enami * never maps the allocated region to pccard I/O area. 1917 1.4 haya * 1918 1.4 haya * XXX: The interface of this function is not very good, I believe. 1919 1.4 haya */ 1920 1.22 chopps STATIC int 1921 1.143 dyoung pccbb_pcmcia_io_alloc(pcmcia_chipset_handle_t pch, bus_addr_t start, 1922 1.143 dyoung bus_size_t size, bus_size_t align, struct pcmcia_io_handle *pcihp) 1923 1.22 chopps { 1924 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 1925 1.22 chopps bus_addr_t ioaddr; 1926 1.22 chopps int flags = 0; 1927 1.22 chopps bus_space_tag_t iot; 1928 1.22 chopps bus_space_handle_t ioh; 1929 1.57 haya bus_addr_t mask; 1930 1.1 haya #if rbus 1931 1.22 chopps rbus_tag_t rb; 1932 1.1 haya #endif 1933 1.213 msaitoh if (align == 0) 1934 1.22 chopps align = size; /* XXX: funny??? */ 1935 1.1 haya 1936 1.57 haya if (start != 0) { 1937 1.57 haya /* XXX: assume all card decode lower 10 bits by its hardware */ 1938 1.57 haya mask = 0x3ff; 1939 1.75 haya /* enforce to use only masked address */ 1940 1.75 haya start &= mask; 1941 1.57 haya } else { 1942 1.57 haya /* 1943 1.57 haya * calculate mask: 1944 1.57 haya * 1. get the most significant bit of size (call it msb). 1945 1.57 haya * 2. compare msb with the value of size. 1946 1.57 haya * 3. if size is larger, shift msb left once. 1947 1.57 haya * 4. obtain mask value to decrement msb. 1948 1.57 haya */ 1949 1.57 haya bus_size_t size_tmp = size; 1950 1.57 haya int shifts = 0; 1951 1.57 haya 1952 1.57 haya mask = 1; 1953 1.57 haya while (size_tmp) { 1954 1.57 haya ++shifts; 1955 1.57 haya size_tmp >>= 1; 1956 1.57 haya } 1957 1.57 haya mask = (1 << shifts); 1958 1.57 haya if (mask < size) { 1959 1.57 haya mask <<= 1; 1960 1.57 haya } 1961 1.57 haya --mask; 1962 1.57 haya } 1963 1.57 haya 1964 1.117 perry /* 1965 1.22 chopps * Allocate some arbitrary I/O space. 1966 1.22 chopps */ 1967 1.1 haya 1968 1.177 drochner iot = sc->sc_iot; 1969 1.1 haya 1970 1.1 haya #if rbus 1971 1.177 drochner rb = sc->sc_rbus_iot; 1972 1.57 haya if (rbus_space_alloc(rb, start, size, mask, align, 0, &ioaddr, &ioh)) { 1973 1.22 chopps return 1; 1974 1.22 chopps } 1975 1.95 christos DPRINTF(("pccbb_pcmcia_io_alloc alloc port 0x%lx+0x%lx\n", 1976 1.81 onoe (u_long) ioaddr, (u_long) size)); 1977 1.22 chopps #else 1978 1.22 chopps if (start) { 1979 1.22 chopps ioaddr = start; 1980 1.22 chopps if (bus_space_map(iot, start, size, 0, &ioh)) { 1981 1.22 chopps return 1; 1982 1.22 chopps } 1983 1.95 christos DPRINTF(("pccbb_pcmcia_io_alloc map port 0x%lx+0x%lx\n", 1984 1.22 chopps (u_long) ioaddr, (u_long) size)); 1985 1.22 chopps } else { 1986 1.22 chopps flags |= PCMCIA_IO_ALLOCATED; 1987 1.22 chopps if (bus_space_alloc(iot, 0x700 /* ph->sc->sc_iobase */ , 1988 1.22 chopps 0x800, /* ph->sc->sc_iobase + ph->sc->sc_iosize */ 1989 1.22 chopps size, align, 0, 0, &ioaddr, &ioh)) { 1990 1.22 chopps /* No room be able to be get. */ 1991 1.22 chopps return 1; 1992 1.22 chopps } 1993 1.22 chopps DPRINTF(("pccbb_pcmmcia_io_alloc alloc port 0x%lx+0x%lx\n", 1994 1.22 chopps (u_long) ioaddr, (u_long) size)); 1995 1.22 chopps } 1996 1.1 haya #endif 1997 1.1 haya 1998 1.22 chopps pcihp->iot = iot; 1999 1.22 chopps pcihp->ioh = ioh; 2000 1.22 chopps pcihp->addr = ioaddr; 2001 1.22 chopps pcihp->size = size; 2002 1.22 chopps pcihp->flags = flags; 2003 1.1 haya 2004 1.22 chopps return 0; 2005 1.1 haya } 2006 1.1 haya 2007 1.4 haya /* 2008 1.4 haya * STATIC int pccbb_pcmcia_io_free(pcmcia_chipset_handle_t pch, 2009 1.4 haya * struct pcmcia_io_handle *pcihp) 2010 1.4 haya * 2011 1.4 haya * This function only frees I/O region for pccard. 2012 1.4 haya * 2013 1.4 haya * XXX: The interface of this function is not very good, I believe. 2014 1.4 haya */ 2015 1.22 chopps void 2016 1.143 dyoung pccbb_pcmcia_io_free(pcmcia_chipset_handle_t pch, 2017 1.143 dyoung struct pcmcia_io_handle *pcihp) 2018 1.1 haya { 2019 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2020 1.1 haya #if !rbus 2021 1.22 chopps bus_space_tag_t iot = pcihp->iot; 2022 1.1 haya #endif 2023 1.22 chopps bus_space_handle_t ioh = pcihp->ioh; 2024 1.22 chopps bus_size_t size = pcihp->size; 2025 1.1 haya 2026 1.1 haya #if rbus 2027 1.22 chopps rbus_tag_t rb = sc->sc_rbus_iot; 2028 1.1 haya 2029 1.22 chopps rbus_space_free(rb, ioh, size, NULL); 2030 1.1 haya #else 2031 1.22 chopps if (pcihp->flags & PCMCIA_IO_ALLOCATED) 2032 1.22 chopps bus_space_free(iot, ioh, size); 2033 1.22 chopps else 2034 1.22 chopps bus_space_unmap(iot, ioh, size); 2035 1.1 haya #endif 2036 1.1 haya } 2037 1.1 haya 2038 1.4 haya /* 2039 1.4 haya * STATIC int pccbb_pcmcia_io_map(pcmcia_chipset_handle_t pch, int width, 2040 1.4 haya * bus_addr_t offset, bus_size_t size, 2041 1.4 haya * struct pcmcia_io_handle *pcihp, 2042 1.4 haya * int *windowp) 2043 1.4 haya * 2044 1.4 haya * This function maps the allocated I/O region to pccard. This function 2045 1.4 haya * never allocates any I/O region for pccard I/O area. I don't 2046 1.4 haya * understand why the original authors of pcmciabus separated alloc and 2047 1.4 haya * map. I believe the two must be unite. 2048 1.4 haya * 2049 1.4 haya * XXX: no wait timing control? 2050 1.4 haya */ 2051 1.22 chopps int 2052 1.143 dyoung pccbb_pcmcia_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset, 2053 1.143 dyoung bus_size_t size, struct pcmcia_io_handle *pcihp, int *windowp) 2054 1.22 chopps { 2055 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2056 1.177 drochner struct pcic_handle *ph = &sc->sc_pcmcia_h; 2057 1.22 chopps bus_addr_t ioaddr = pcihp->addr + offset; 2058 1.22 chopps int i, win; 2059 1.1 haya #if defined CBB_DEBUG 2060 1.121 sekiya static const char *width_names[] = { "dynamic", "io8", "io16" }; 2061 1.1 haya #endif 2062 1.1 haya 2063 1.22 chopps /* Sanity check I/O handle. */ 2064 1.1 haya 2065 1.213 msaitoh if (!bus_space_is_equal(sc->sc_iot, pcihp->iot)) 2066 1.22 chopps panic("pccbb_pcmcia_io_map iot is bogus"); 2067 1.1 haya 2068 1.22 chopps /* XXX Sanity check offset/size. */ 2069 1.1 haya 2070 1.22 chopps win = -1; 2071 1.22 chopps for (i = 0; i < PCIC_IO_WINS; i++) { 2072 1.22 chopps if ((ph->ioalloc & (1 << i)) == 0) { 2073 1.22 chopps win = i; 2074 1.22 chopps ph->ioalloc |= (1 << i); 2075 1.22 chopps break; 2076 1.22 chopps } 2077 1.22 chopps } 2078 1.1 haya 2079 1.213 msaitoh if (win == -1) 2080 1.22 chopps return 1; 2081 1.1 haya 2082 1.22 chopps *windowp = win; 2083 1.1 haya 2084 1.22 chopps /* XXX this is pretty gross */ 2085 1.1 haya 2086 1.22 chopps DPRINTF(("pccbb_pcmcia_io_map window %d %s port %lx+%lx\n", 2087 1.22 chopps win, width_names[width], (u_long) ioaddr, (u_long) size)); 2088 1.1 haya 2089 1.22 chopps /* XXX wtf is this doing here? */ 2090 1.1 haya 2091 1.1 haya #if 0 2092 1.22 chopps printf(" port 0x%lx", (u_long) ioaddr); 2093 1.213 msaitoh if (size > 1) 2094 1.22 chopps printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1); 2095 1.1 haya #endif 2096 1.1 haya 2097 1.22 chopps ph->io[win].addr = ioaddr; 2098 1.22 chopps ph->io[win].size = size; 2099 1.22 chopps ph->io[win].width = width; 2100 1.1 haya 2101 1.22 chopps /* actual dirty register-value changing in the function below. */ 2102 1.176 drochner pccbb_pcmcia_do_io_map(sc, win); 2103 1.1 haya 2104 1.22 chopps return 0; 2105 1.1 haya } 2106 1.1 haya 2107 1.4 haya /* 2108 1.4 haya * STATIC void pccbb_pcmcia_do_io_map(struct pcic_handle *h, int win) 2109 1.4 haya * 2110 1.4 haya * This function changes register-value to map I/O region for pccard. 2111 1.4 haya */ 2112 1.22 chopps static void 2113 1.176 drochner pccbb_pcmcia_do_io_map(struct pccbb_softc *sc, int win) 2114 1.1 haya { 2115 1.213 msaitoh static uint8_t pcic_iowidth[3] = { 2116 1.22 chopps PCIC_IOCTL_IO0_IOCS16SRC_CARD, 2117 1.22 chopps PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | 2118 1.22 chopps PCIC_IOCTL_IO0_DATASIZE_8BIT, 2119 1.22 chopps PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE | 2120 1.22 chopps PCIC_IOCTL_IO0_DATASIZE_16BIT, 2121 1.22 chopps }; 2122 1.1 haya 2123 1.1 haya #define PCIC_SIA_START_LOW 0 2124 1.1 haya #define PCIC_SIA_START_HIGH 1 2125 1.1 haya #define PCIC_SIA_STOP_LOW 2 2126 1.1 haya #define PCIC_SIA_STOP_HIGH 3 2127 1.1 haya 2128 1.22 chopps int regbase_win = 0x8 + win * 0x04; 2129 1.213 msaitoh uint8_t ioctl, enable; 2130 1.176 drochner struct pcic_handle *ph = &sc->sc_pcmcia_h; 2131 1.1 haya 2132 1.95 christos DPRINTF(("pccbb_pcmcia_do_io_map win %d addr 0x%lx size 0x%lx " 2133 1.95 christos "width %d\n", win, (unsigned long)ph->io[win].addr, 2134 1.95 christos (unsigned long)ph->io[win].size, ph->io[win].width * 8)); 2135 1.22 chopps 2136 1.177 drochner Pcic_write(sc, regbase_win + PCIC_SIA_START_LOW, 2137 1.22 chopps ph->io[win].addr & 0xff); 2138 1.177 drochner Pcic_write(sc, regbase_win + PCIC_SIA_START_HIGH, 2139 1.22 chopps (ph->io[win].addr >> 8) & 0xff); 2140 1.22 chopps 2141 1.177 drochner Pcic_write(sc, regbase_win + PCIC_SIA_STOP_LOW, 2142 1.22 chopps (ph->io[win].addr + ph->io[win].size - 1) & 0xff); 2143 1.177 drochner Pcic_write(sc, regbase_win + PCIC_SIA_STOP_HIGH, 2144 1.22 chopps ((ph->io[win].addr + ph->io[win].size - 1) >> 8) & 0xff); 2145 1.22 chopps 2146 1.177 drochner ioctl = Pcic_read(sc, PCIC_IOCTL); 2147 1.177 drochner enable = Pcic_read(sc, PCIC_ADDRWIN_ENABLE); 2148 1.22 chopps switch (win) { 2149 1.22 chopps case 0: 2150 1.22 chopps ioctl &= ~(PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT | 2151 1.22 chopps PCIC_IOCTL_IO0_IOCS16SRC_MASK | 2152 1.22 chopps PCIC_IOCTL_IO0_DATASIZE_MASK); 2153 1.22 chopps ioctl |= pcic_iowidth[ph->io[win].width]; 2154 1.22 chopps enable |= PCIC_ADDRWIN_ENABLE_IO0; 2155 1.22 chopps break; 2156 1.22 chopps case 1: 2157 1.22 chopps ioctl &= ~(PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT | 2158 1.22 chopps PCIC_IOCTL_IO1_IOCS16SRC_MASK | 2159 1.22 chopps PCIC_IOCTL_IO1_DATASIZE_MASK); 2160 1.22 chopps ioctl |= (pcic_iowidth[ph->io[win].width] << 4); 2161 1.22 chopps enable |= PCIC_ADDRWIN_ENABLE_IO1; 2162 1.22 chopps break; 2163 1.22 chopps } 2164 1.177 drochner Pcic_write(sc, PCIC_IOCTL, ioctl); 2165 1.177 drochner Pcic_write(sc, PCIC_ADDRWIN_ENABLE, enable); 2166 1.133 christos #if defined(CBB_DEBUG) 2167 1.22 chopps { 2168 1.213 msaitoh uint8_t start_low = 2169 1.177 drochner Pcic_read(sc, regbase_win + PCIC_SIA_START_LOW); 2170 1.213 msaitoh uint8_t start_high = 2171 1.177 drochner Pcic_read(sc, regbase_win + PCIC_SIA_START_HIGH); 2172 1.213 msaitoh uint8_t stop_low = 2173 1.177 drochner Pcic_read(sc, regbase_win + PCIC_SIA_STOP_LOW); 2174 1.213 msaitoh uint8_t stop_high = 2175 1.177 drochner Pcic_read(sc, regbase_win + PCIC_SIA_STOP_HIGH); 2176 1.133 christos printf("pccbb_pcmcia_do_io_map start %02x %02x, " 2177 1.133 christos "stop %02x %02x, ioctl %02x enable %02x\n", 2178 1.22 chopps start_low, start_high, stop_low, stop_high, ioctl, enable); 2179 1.22 chopps } 2180 1.1 haya #endif 2181 1.1 haya } 2182 1.1 haya 2183 1.4 haya /* 2184 1.4 haya * STATIC void pccbb_pcmcia_io_unmap(pcmcia_chipset_handle_t *h, int win) 2185 1.4 haya * 2186 1.32 enami * This function unmaps I/O region. No return value. 2187 1.4 haya */ 2188 1.22 chopps STATIC void 2189 1.143 dyoung pccbb_pcmcia_io_unmap(pcmcia_chipset_handle_t pch, int win) 2190 1.1 haya { 2191 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2192 1.177 drochner struct pcic_handle *ph = &sc->sc_pcmcia_h; 2193 1.22 chopps int reg; 2194 1.1 haya 2195 1.213 msaitoh if (win >= PCIC_IO_WINS || win < 0) 2196 1.22 chopps panic("pccbb_pcmcia_io_unmap: window out of range"); 2197 1.1 haya 2198 1.177 drochner reg = Pcic_read(sc, PCIC_ADDRWIN_ENABLE); 2199 1.22 chopps switch (win) { 2200 1.22 chopps case 0: 2201 1.22 chopps reg &= ~PCIC_ADDRWIN_ENABLE_IO0; 2202 1.22 chopps break; 2203 1.22 chopps case 1: 2204 1.22 chopps reg &= ~PCIC_ADDRWIN_ENABLE_IO1; 2205 1.22 chopps break; 2206 1.22 chopps } 2207 1.177 drochner Pcic_write(sc, PCIC_ADDRWIN_ENABLE, reg); 2208 1.1 haya 2209 1.22 chopps ph->ioalloc &= ~(1 << win); 2210 1.1 haya } 2211 1.1 haya 2212 1.91 briggs static int 2213 1.176 drochner pccbb_pcmcia_wait_ready(struct pccbb_softc *sc) 2214 1.1 haya { 2215 1.213 msaitoh uint8_t stat; 2216 1.22 chopps int i; 2217 1.1 haya 2218 1.104 mycroft /* wait an initial 10ms for quick cards */ 2219 1.177 drochner stat = Pcic_read(sc, PCIC_IF_STATUS); 2220 1.104 mycroft if (stat & PCIC_IF_STATUS_READY) 2221 1.213 msaitoh return 0; 2222 1.176 drochner pccbb_pcmcia_delay(sc, 10, "pccwr0"); 2223 1.104 mycroft for (i = 0; i < 50; i++) { 2224 1.177 drochner stat = Pcic_read(sc, PCIC_IF_STATUS); 2225 1.91 briggs if (stat & PCIC_IF_STATUS_READY) 2226 1.213 msaitoh return 0; 2227 1.91 briggs if ((stat & PCIC_IF_STATUS_CARDDETECT_MASK) != 2228 1.91 briggs PCIC_IF_STATUS_CARDDETECT_PRESENT) 2229 1.213 msaitoh return ENXIO; 2230 1.104 mycroft /* wait .1s (100ms) each iteration now */ 2231 1.176 drochner pccbb_pcmcia_delay(sc, 100, "pccwr1"); 2232 1.22 chopps } 2233 1.1 haya 2234 1.210 msaitoh printf("pccbb_pcmcia_wait_ready: ready never happened, status=%02x\n", 2235 1.210 msaitoh stat); 2236 1.213 msaitoh return EWOULDBLOCK; 2237 1.104 mycroft } 2238 1.104 mycroft 2239 1.104 mycroft /* 2240 1.143 dyoung * Perform long (msec order) delay. timo is in milliseconds. 2241 1.104 mycroft */ 2242 1.104 mycroft static void 2243 1.176 drochner pccbb_pcmcia_delay(struct pccbb_softc *sc, int timo, const char *wmesg) 2244 1.104 mycroft { 2245 1.1 haya #ifdef DIAGNOSTIC 2246 1.104 mycroft if (timo <= 0) 2247 1.104 mycroft panic("pccbb_pcmcia_delay: called with timeout %d", timo); 2248 1.104 mycroft if (!curlwp) 2249 1.104 mycroft panic("pccbb_pcmcia_delay: called in interrupt context"); 2250 1.1 haya #endif 2251 1.175 drochner DPRINTF(("pccbb_pcmcia_delay: \"%s\", sleep %d ms\n", wmesg, timo)); 2252 1.212 riastrad kpause(wmesg, false, uimax(mstohz(timo), 1), NULL); 2253 1.1 haya } 2254 1.1 haya 2255 1.4 haya /* 2256 1.4 haya * STATIC void pccbb_pcmcia_socket_enable(pcmcia_chipset_handle_t pch) 2257 1.4 haya * 2258 1.4 haya * This function enables the card. All information is stored in 2259 1.4 haya * the first argument, pcmcia_chipset_handle_t. 2260 1.4 haya */ 2261 1.1 haya STATIC void 2262 1.143 dyoung pccbb_pcmcia_socket_enable(pcmcia_chipset_handle_t pch) 2263 1.1 haya { 2264 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2265 1.177 drochner struct pcic_handle *ph = &sc->sc_pcmcia_h; 2266 1.104 mycroft pcireg_t spsr; 2267 1.104 mycroft int voltage; 2268 1.101 mycroft int win; 2269 1.213 msaitoh uint8_t power, intr; 2270 1.104 mycroft #ifdef DIAGNOSTIC 2271 1.104 mycroft int reg; 2272 1.104 mycroft #endif 2273 1.1 haya 2274 1.22 chopps /* this bit is mostly stolen from pcic_attach_card */ 2275 1.1 haya 2276 1.22 chopps DPRINTF(("pccbb_pcmcia_socket_enable: ")); 2277 1.1 haya 2278 1.22 chopps /* get card Vcc info */ 2279 1.22 chopps spsr = 2280 1.22 chopps bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh, 2281 1.22 chopps CB_SOCKET_STAT); 2282 1.22 chopps if (spsr & CB_SOCKET_STAT_5VCARD) { 2283 1.22 chopps DPRINTF(("5V card\n")); 2284 1.22 chopps voltage = CARDBUS_VCC_5V | CARDBUS_VPP_VCC; 2285 1.22 chopps } else if (spsr & CB_SOCKET_STAT_3VCARD) { 2286 1.22 chopps DPRINTF(("3V card\n")); 2287 1.22 chopps voltage = CARDBUS_VCC_3V | CARDBUS_VPP_VCC; 2288 1.22 chopps } else { 2289 1.133 christos DPRINTF(("?V card, 0x%x\n", spsr)); /* XXX */ 2290 1.22 chopps return; 2291 1.22 chopps } 2292 1.1 haya 2293 1.108 mycroft /* disable interrupts; assert RESET */ 2294 1.177 drochner intr = Pcic_read(sc, PCIC_INTR); 2295 1.109 mycroft intr &= PCIC_INTR_ENABLE; 2296 1.177 drochner Pcic_write(sc, PCIC_INTR, intr); 2297 1.104 mycroft 2298 1.104 mycroft /* zero out the address windows */ 2299 1.177 drochner Pcic_write(sc, PCIC_ADDRWIN_ENABLE, 0); 2300 1.100 mycroft 2301 1.104 mycroft /* power down the socket to reset it, clear the card reset pin */ 2302 1.104 mycroft pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V); 2303 1.1 haya 2304 1.108 mycroft /* power off; assert output enable bit */ 2305 1.108 mycroft power = PCIC_PWRCTL_OE; 2306 1.177 drochner Pcic_write(sc, PCIC_PWRCTL, power); 2307 1.1 haya 2308 1.106 mycroft /* power up the socket */ 2309 1.104 mycroft if (pccbb_power(sc, voltage) == 0) 2310 1.104 mycroft return; 2311 1.104 mycroft 2312 1.112 mycroft /* 2313 1.112 mycroft * Table 4-18 and figure 4-6 of the PC Card specifiction say: 2314 1.112 mycroft * Vcc Rising Time (Tpr) = 100ms (handled in pccbb_power() above) 2315 1.112 mycroft * RESET Width (Th (Hi-z RESET)) = 1ms 2316 1.112 mycroft * RESET Width (Tw (RESET)) = 10us 2317 1.190 blymn * 2318 1.132 christos * some machines require some more time to be settled 2319 1.132 christos * for example old toshiba topic bridges! 2320 1.132 christos * (100ms is added here). 2321 1.190 blymn */ 2322 1.176 drochner pccbb_pcmcia_delay(sc, 200 + 1, "pccen1"); 2323 1.112 mycroft 2324 1.108 mycroft /* negate RESET */ 2325 1.22 chopps intr |= PCIC_INTR_RESET; 2326 1.177 drochner Pcic_write(sc, PCIC_INTR, intr); 2327 1.1 haya 2328 1.108 mycroft /* 2329 1.108 mycroft * RESET Setup Time (Tsu (RESET)) = 20ms 2330 1.108 mycroft */ 2331 1.176 drochner pccbb_pcmcia_delay(sc, 20, "pccen2"); 2332 1.1 haya 2333 1.104 mycroft #ifdef DIAGNOSTIC 2334 1.177 drochner reg = Pcic_read(sc, PCIC_IF_STATUS); 2335 1.104 mycroft if ((reg & PCIC_IF_STATUS_POWERACTIVE) == 0) 2336 1.210 msaitoh printf("pccbb_pcmcia_socket_enable: no power, status=%x\n", 2337 1.210 msaitoh reg); 2338 1.56 itohy #endif 2339 1.1 haya 2340 1.22 chopps /* wait for the chip to finish initializing */ 2341 1.176 drochner if (pccbb_pcmcia_wait_ready(sc)) { 2342 1.133 christos #ifdef DIAGNOSTIC 2343 1.133 christos printf("pccbb_pcmcia_socket_enable: never became ready\n"); 2344 1.133 christos #endif 2345 1.104 mycroft /* XXX return a failure status?? */ 2346 1.91 briggs pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V); 2347 1.177 drochner Pcic_write(sc, PCIC_PWRCTL, 0); 2348 1.91 briggs return; 2349 1.91 briggs } 2350 1.1 haya 2351 1.22 chopps /* reinstall all the memory and io mappings */ 2352 1.104 mycroft for (win = 0; win < PCIC_MEM_WINS; ++win) 2353 1.104 mycroft if (ph->memalloc & (1 << win)) 2354 1.176 drochner pccbb_pcmcia_do_mem_map(sc, win); 2355 1.104 mycroft for (win = 0; win < PCIC_IO_WINS; ++win) 2356 1.104 mycroft if (ph->ioalloc & (1 << win)) 2357 1.176 drochner pccbb_pcmcia_do_io_map(sc, win); 2358 1.1 haya } 2359 1.1 haya 2360 1.4 haya /* 2361 1.4 haya * STATIC void pccbb_pcmcia_socket_disable(pcmcia_chipset_handle_t *ph) 2362 1.4 haya * 2363 1.4 haya * This function disables the card. All information is stored in 2364 1.4 haya * the first argument, pcmcia_chipset_handle_t. 2365 1.4 haya */ 2366 1.1 haya STATIC void 2367 1.143 dyoung pccbb_pcmcia_socket_disable(pcmcia_chipset_handle_t pch) 2368 1.1 haya { 2369 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2370 1.213 msaitoh uint8_t intr; 2371 1.22 chopps 2372 1.22 chopps DPRINTF(("pccbb_pcmcia_socket_disable\n")); 2373 1.22 chopps 2374 1.108 mycroft /* disable interrupts; assert RESET */ 2375 1.177 drochner intr = Pcic_read(sc, PCIC_INTR); 2376 1.109 mycroft intr &= PCIC_INTR_ENABLE; 2377 1.177 drochner Pcic_write(sc, PCIC_INTR, intr); 2378 1.102 mycroft 2379 1.102 mycroft /* zero out the address windows */ 2380 1.177 drochner Pcic_write(sc, PCIC_ADDRWIN_ENABLE, 0); 2381 1.22 chopps 2382 1.108 mycroft /* power down the socket to reset it, clear the card reset pin */ 2383 1.108 mycroft pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V); 2384 1.108 mycroft 2385 1.104 mycroft /* disable socket: negate output enable bit and power off */ 2386 1.177 drochner Pcic_write(sc, PCIC_PWRCTL, 0); 2387 1.104 mycroft 2388 1.108 mycroft /* 2389 1.108 mycroft * Vcc Falling Time (Tpf) = 300ms 2390 1.108 mycroft */ 2391 1.176 drochner pccbb_pcmcia_delay(sc, 300, "pccwr1"); 2392 1.101 mycroft } 2393 1.101 mycroft 2394 1.101 mycroft STATIC void 2395 1.143 dyoung pccbb_pcmcia_socket_settype(pcmcia_chipset_handle_t pch, int type) 2396 1.101 mycroft { 2397 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2398 1.213 msaitoh uint8_t intr; 2399 1.101 mycroft 2400 1.101 mycroft /* set the card type */ 2401 1.100 mycroft 2402 1.177 drochner intr = Pcic_read(sc, PCIC_INTR); 2403 1.102 mycroft intr &= ~(PCIC_INTR_IRQ_MASK | PCIC_INTR_CARDTYPE_MASK); 2404 1.101 mycroft if (type == PCMCIA_IFTYPE_IO) 2405 1.101 mycroft intr |= PCIC_INTR_CARDTYPE_IO; 2406 1.101 mycroft else 2407 1.101 mycroft intr |= PCIC_INTR_CARDTYPE_MEM; 2408 1.177 drochner Pcic_write(sc, PCIC_INTR, intr); 2409 1.101 mycroft 2410 1.175 drochner DPRINTF(("%s: pccbb_pcmcia_socket_settype type %s %02x\n", 2411 1.177 drochner device_xname(sc->sc_dev), 2412 1.175 drochner ((type == PCMCIA_IFTYPE_IO) ? "io" : "mem"), intr)); 2413 1.1 haya } 2414 1.1 haya 2415 1.4 haya /* 2416 1.1 haya * STATIC int pccbb_pcmcia_card_detect(pcmcia_chipset_handle_t *ph) 2417 1.1 haya * 2418 1.1 haya * This function detects whether a card is in the slot or not. 2419 1.1 haya * If a card is inserted, return 1. Otherwise, return 0. 2420 1.4 haya */ 2421 1.1 haya STATIC int 2422 1.143 dyoung pccbb_pcmcia_card_detect(pcmcia_chipset_handle_t pch) 2423 1.1 haya { 2424 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2425 1.22 chopps 2426 1.22 chopps DPRINTF(("pccbb_pcmcia_card_detect\n")); 2427 1.22 chopps return pccbb_detect_card(sc) == 1 ? 1 : 0; 2428 1.1 haya } 2429 1.1 haya 2430 1.1 haya #if 0 2431 1.1 haya STATIC int 2432 1.1 haya pccbb_new_pcmcia_mem_alloc(pcmcia_chipset_handle_t pch, 2433 1.22 chopps bus_addr_t start, bus_size_t size, bus_size_t align, int speed, int flags, 2434 1.22 chopps bus_space_tag_t * memtp bus_space_handle_t * memhp) 2435 1.1 haya #endif 2436 1.4 haya /* 2437 1.4 haya * STATIC int pccbb_pcmcia_mem_alloc(pcmcia_chipset_handle_t pch, 2438 1.4 haya * bus_size_t size, 2439 1.4 haya * struct pcmcia_mem_handle *pcmhp) 2440 1.4 haya * 2441 1.4 haya * This function only allocates memory region for pccard. This 2442 1.32 enami * function never maps the allocated region to pccard memory area. 2443 1.4 haya * 2444 1.4 haya * XXX: Why the argument of start address is not in? 2445 1.4 haya */ 2446 1.22 chopps STATIC int 2447 1.143 dyoung pccbb_pcmcia_mem_alloc(pcmcia_chipset_handle_t pch, bus_size_t size, 2448 1.143 dyoung struct pcmcia_mem_handle *pcmhp) 2449 1.22 chopps { 2450 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2451 1.22 chopps bus_space_handle_t memh; 2452 1.22 chopps bus_addr_t addr; 2453 1.22 chopps bus_size_t sizepg; 2454 1.1 haya #if rbus 2455 1.22 chopps rbus_tag_t rb; 2456 1.1 haya #endif 2457 1.1 haya 2458 1.91 briggs /* Check that the card is still there. */ 2459 1.177 drochner if ((Pcic_read(sc, PCIC_IF_STATUS) & PCIC_IF_STATUS_CARDDETECT_MASK) != 2460 1.91 briggs PCIC_IF_STATUS_CARDDETECT_PRESENT) 2461 1.91 briggs return 1; 2462 1.91 briggs 2463 1.22 chopps /* out of sc->memh, allocate as many pages as necessary */ 2464 1.1 haya 2465 1.22 chopps /* convert size to PCIC pages */ 2466 1.117 perry /* 2467 1.22 chopps * This is not enough; when the requested region is on the page 2468 1.22 chopps * boundaries, this may calculate wrong result. 2469 1.22 chopps */ 2470 1.22 chopps sizepg = (size + (PCIC_MEM_PAGESIZE - 1)) / PCIC_MEM_PAGESIZE; 2471 1.1 haya #if 0 2472 1.213 msaitoh if (sizepg > PCIC_MAX_MEM_PAGES) 2473 1.22 chopps return 1; 2474 1.1 haya #endif 2475 1.1 haya 2476 1.213 msaitoh if (!(sc->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32)) 2477 1.22 chopps return 1; 2478 1.1 haya 2479 1.22 chopps addr = 0; /* XXX gcc -Wuninitialized */ 2480 1.1 haya 2481 1.1 haya #if rbus 2482 1.22 chopps rb = sc->sc_rbus_memt; 2483 1.22 chopps if (rbus_space_alloc(rb, 0, sizepg * PCIC_MEM_PAGESIZE, 2484 1.22 chopps sizepg * PCIC_MEM_PAGESIZE - 1, PCIC_MEM_PAGESIZE, 0, 2485 1.22 chopps &addr, &memh)) { 2486 1.22 chopps return 1; 2487 1.22 chopps } 2488 1.1 haya #else 2489 1.22 chopps if (bus_space_alloc(sc->sc_memt, sc->sc_mem_start, sc->sc_mem_end, 2490 1.22 chopps sizepg * PCIC_MEM_PAGESIZE, PCIC_MEM_PAGESIZE, 2491 1.22 chopps 0, /* boundary */ 2492 1.22 chopps 0, /* flags */ 2493 1.22 chopps &addr, &memh)) { 2494 1.22 chopps return 1; 2495 1.22 chopps } 2496 1.1 haya #endif 2497 1.1 haya 2498 1.95 christos DPRINTF(("pccbb_pcmcia_alloc_mem: addr 0x%lx size 0x%lx, " 2499 1.95 christos "realsize 0x%lx\n", (unsigned long)addr, (unsigned long)size, 2500 1.95 christos (unsigned long)sizepg * PCIC_MEM_PAGESIZE)); 2501 1.22 chopps 2502 1.22 chopps pcmhp->memt = sc->sc_memt; 2503 1.22 chopps pcmhp->memh = memh; 2504 1.22 chopps pcmhp->addr = addr; 2505 1.22 chopps pcmhp->size = size; 2506 1.22 chopps pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE; 2507 1.22 chopps /* What is mhandle? I feel it is very dirty and it must go trush. */ 2508 1.22 chopps pcmhp->mhandle = 0; 2509 1.22 chopps /* No offset??? Funny. */ 2510 1.1 haya 2511 1.22 chopps return 0; 2512 1.1 haya } 2513 1.1 haya 2514 1.4 haya /* 2515 1.4 haya * STATIC void pccbb_pcmcia_mem_free(pcmcia_chipset_handle_t pch, 2516 1.4 haya * struct pcmcia_mem_handle *pcmhp) 2517 1.4 haya * 2518 1.32 enami * This function release the memory space allocated by the function 2519 1.4 haya * pccbb_pcmcia_mem_alloc(). 2520 1.4 haya */ 2521 1.22 chopps STATIC void 2522 1.143 dyoung pccbb_pcmcia_mem_free(pcmcia_chipset_handle_t pch, 2523 1.143 dyoung struct pcmcia_mem_handle *pcmhp) 2524 1.1 haya { 2525 1.1 haya #if rbus 2526 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2527 1.1 haya 2528 1.22 chopps rbus_space_free(sc->sc_rbus_memt, pcmhp->memh, pcmhp->realsize, NULL); 2529 1.1 haya #else 2530 1.22 chopps bus_space_free(pcmhp->memt, pcmhp->memh, pcmhp->realsize); 2531 1.1 haya #endif 2532 1.1 haya } 2533 1.1 haya 2534 1.4 haya /* 2535 1.4 haya * STATIC void pccbb_pcmcia_do_mem_map(struct pcic_handle *ph, int win) 2536 1.4 haya * 2537 1.32 enami * This function release the memory space allocated by the function 2538 1.4 haya * pccbb_pcmcia_mem_alloc(). 2539 1.4 haya */ 2540 1.22 chopps STATIC void 2541 1.176 drochner pccbb_pcmcia_do_mem_map(struct pccbb_softc *sc, int win) 2542 1.1 haya { 2543 1.22 chopps int regbase_win; 2544 1.22 chopps bus_addr_t phys_addr; 2545 1.22 chopps bus_addr_t phys_end; 2546 1.176 drochner struct pcic_handle *ph = &sc->sc_pcmcia_h; 2547 1.1 haya 2548 1.1 haya #define PCIC_SMM_START_LOW 0 2549 1.1 haya #define PCIC_SMM_START_HIGH 1 2550 1.1 haya #define PCIC_SMM_STOP_LOW 2 2551 1.1 haya #define PCIC_SMM_STOP_HIGH 3 2552 1.1 haya #define PCIC_CMA_LOW 4 2553 1.1 haya #define PCIC_CMA_HIGH 5 2554 1.1 haya 2555 1.213 msaitoh uint8_t start_low, start_high = 0; 2556 1.213 msaitoh uint8_t stop_low, stop_high; 2557 1.213 msaitoh uint8_t off_low, off_high; 2558 1.213 msaitoh uint8_t mem_window; 2559 1.22 chopps int reg; 2560 1.22 chopps 2561 1.22 chopps int kind = ph->mem[win].kind & ~PCMCIA_WIDTH_MEM_MASK; 2562 1.22 chopps int mem8 = 2563 1.24 thorpej (ph->mem[win].kind & PCMCIA_WIDTH_MEM_MASK) == PCMCIA_WIDTH_MEM8 2564 1.24 thorpej || (kind == PCMCIA_MEM_ATTR); 2565 1.12 joda 2566 1.22 chopps regbase_win = 0x10 + win * 0x08; 2567 1.1 haya 2568 1.22 chopps phys_addr = ph->mem[win].addr; 2569 1.22 chopps phys_end = phys_addr + ph->mem[win].size; 2570 1.1 haya 2571 1.22 chopps DPRINTF(("pccbb_pcmcia_do_mem_map: start 0x%lx end 0x%lx off 0x%lx\n", 2572 1.95 christos (unsigned long)phys_addr, (unsigned long)phys_end, 2573 1.95 christos (unsigned long)ph->mem[win].offset)); 2574 1.1 haya 2575 1.1 haya #define PCIC_MEMREG_LSB_SHIFT PCIC_SYSMEM_ADDRX_SHIFT 2576 1.1 haya #define PCIC_MEMREG_MSB_SHIFT (PCIC_SYSMEM_ADDRX_SHIFT + 8) 2577 1.1 haya #define PCIC_MEMREG_WIN_SHIFT (PCIC_SYSMEM_ADDRX_SHIFT + 12) 2578 1.1 haya 2579 1.22 chopps /* bit 19:12 */ 2580 1.22 chopps start_low = (phys_addr >> PCIC_MEMREG_LSB_SHIFT) & 0xff; 2581 1.22 chopps /* bit 23:20 and bit 7 on */ 2582 1.22 chopps start_high = ((phys_addr >> PCIC_MEMREG_MSB_SHIFT) & 0x0f) 2583 1.22 chopps |(mem8 ? 0 : PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT); 2584 1.22 chopps /* bit 31:24, for 32-bit address */ 2585 1.22 chopps mem_window = (phys_addr >> PCIC_MEMREG_WIN_SHIFT) & 0xff; 2586 1.22 chopps 2587 1.177 drochner Pcic_write(sc, regbase_win + PCIC_SMM_START_LOW, start_low); 2588 1.177 drochner Pcic_write(sc, regbase_win + PCIC_SMM_START_HIGH, start_high); 2589 1.22 chopps 2590 1.177 drochner if (sc->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) { 2591 1.177 drochner Pcic_write(sc, 0x40 + win, mem_window); 2592 1.22 chopps } 2593 1.1 haya 2594 1.22 chopps stop_low = (phys_end >> PCIC_MEMREG_LSB_SHIFT) & 0xff; 2595 1.22 chopps stop_high = ((phys_end >> PCIC_MEMREG_MSB_SHIFT) & 0x0f) 2596 1.22 chopps | PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2; /* wait 2 cycles */ 2597 1.22 chopps /* XXX Geee, WAIT2!! Crazy!! I must rewrite this routine. */ 2598 1.22 chopps 2599 1.177 drochner Pcic_write(sc, regbase_win + PCIC_SMM_STOP_LOW, stop_low); 2600 1.177 drochner Pcic_write(sc, regbase_win + PCIC_SMM_STOP_HIGH, stop_high); 2601 1.22 chopps 2602 1.22 chopps off_low = (ph->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff; 2603 1.22 chopps off_high = ((ph->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) 2604 1.22 chopps & PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) 2605 1.22 chopps | ((kind == PCMCIA_MEM_ATTR) ? 2606 1.22 chopps PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0); 2607 1.22 chopps 2608 1.177 drochner Pcic_write(sc, regbase_win + PCIC_CMA_LOW, off_low); 2609 1.177 drochner Pcic_write(sc, regbase_win + PCIC_CMA_HIGH, off_high); 2610 1.22 chopps 2611 1.177 drochner reg = Pcic_read(sc, PCIC_ADDRWIN_ENABLE); 2612 1.22 chopps reg |= ((1 << win) | PCIC_ADDRWIN_ENABLE_MEMCS16); 2613 1.177 drochner Pcic_write(sc, PCIC_ADDRWIN_ENABLE, reg); 2614 1.1 haya 2615 1.133 christos #if defined(CBB_DEBUG) 2616 1.22 chopps { 2617 1.22 chopps int r1, r2, r3, r4, r5, r6, r7 = 0; 2618 1.1 haya 2619 1.177 drochner r1 = Pcic_read(sc, regbase_win + PCIC_SMM_START_LOW); 2620 1.177 drochner r2 = Pcic_read(sc, regbase_win + PCIC_SMM_START_HIGH); 2621 1.177 drochner r3 = Pcic_read(sc, regbase_win + PCIC_SMM_STOP_LOW); 2622 1.177 drochner r4 = Pcic_read(sc, regbase_win + PCIC_SMM_STOP_HIGH); 2623 1.177 drochner r5 = Pcic_read(sc, regbase_win + PCIC_CMA_LOW); 2624 1.177 drochner r6 = Pcic_read(sc, regbase_win + PCIC_CMA_HIGH); 2625 1.177 drochner if (sc->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) { 2626 1.177 drochner r7 = Pcic_read(sc, 0x40 + win); 2627 1.22 chopps } 2628 1.22 chopps 2629 1.133 christos printf("pccbb_pcmcia_do_mem_map window %d: %02x%02x %02x%02x " 2630 1.133 christos "%02x%02x", win, r1, r2, r3, r4, r5, r6); 2631 1.177 drochner if (sc->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) { 2632 1.133 christos printf(" %02x", r7); 2633 1.22 chopps } 2634 1.133 christos printf("\n"); 2635 1.22 chopps } 2636 1.1 haya #endif 2637 1.1 haya } 2638 1.1 haya 2639 1.4 haya /* 2640 1.4 haya * STATIC int pccbb_pcmcia_mem_map(pcmcia_chipset_handle_t pch, int kind, 2641 1.4 haya * bus_addr_t card_addr, bus_size_t size, 2642 1.4 haya * struct pcmcia_mem_handle *pcmhp, 2643 1.4 haya * bus_addr_t *offsetp, int *windowp) 2644 1.4 haya * 2645 1.32 enami * This function maps memory space allocated by the function 2646 1.4 haya * pccbb_pcmcia_mem_alloc(). 2647 1.4 haya */ 2648 1.22 chopps STATIC int 2649 1.143 dyoung pccbb_pcmcia_mem_map(pcmcia_chipset_handle_t pch, int kind, 2650 1.143 dyoung bus_addr_t card_addr, bus_size_t size, struct pcmcia_mem_handle *pcmhp, 2651 1.183 bouyer bus_size_t *offsetp, int *windowp) 2652 1.22 chopps { 2653 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2654 1.177 drochner struct pcic_handle *ph = &sc->sc_pcmcia_h; 2655 1.22 chopps bus_addr_t busaddr; 2656 1.22 chopps long card_offset; 2657 1.22 chopps int win; 2658 1.91 briggs 2659 1.91 briggs /* Check that the card is still there. */ 2660 1.177 drochner if ((Pcic_read(sc, PCIC_IF_STATUS) & PCIC_IF_STATUS_CARDDETECT_MASK) != 2661 1.91 briggs PCIC_IF_STATUS_CARDDETECT_PRESENT) 2662 1.91 briggs return 1; 2663 1.22 chopps 2664 1.22 chopps for (win = 0; win < PCIC_MEM_WINS; ++win) { 2665 1.22 chopps if ((ph->memalloc & (1 << win)) == 0) { 2666 1.22 chopps ph->memalloc |= (1 << win); 2667 1.22 chopps break; 2668 1.22 chopps } 2669 1.22 chopps } 2670 1.1 haya 2671 1.213 msaitoh if (win == PCIC_MEM_WINS) 2672 1.22 chopps return 1; 2673 1.1 haya 2674 1.22 chopps *windowp = win; 2675 1.1 haya 2676 1.22 chopps /* XXX this is pretty gross */ 2677 1.1 haya 2678 1.198 dyoung if (!bus_space_is_equal(sc->sc_memt, pcmhp->memt)) { 2679 1.22 chopps panic("pccbb_pcmcia_mem_map memt is bogus"); 2680 1.22 chopps } 2681 1.1 haya 2682 1.22 chopps busaddr = pcmhp->addr; 2683 1.1 haya 2684 1.117 perry /* 2685 1.22 chopps * compute the address offset to the pcmcia address space for the 2686 1.22 chopps * pcic. this is intentionally signed. The masks and shifts below 2687 1.22 chopps * will cause TRT to happen in the pcic registers. Deal with making 2688 1.22 chopps * sure the address is aligned, and return the alignment offset. 2689 1.22 chopps */ 2690 1.22 chopps 2691 1.22 chopps *offsetp = card_addr % PCIC_MEM_PAGESIZE; 2692 1.22 chopps card_addr -= *offsetp; 2693 1.22 chopps 2694 1.22 chopps DPRINTF(("pccbb_pcmcia_mem_map window %d bus %lx+%lx+%lx at card addr " 2695 1.22 chopps "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size, 2696 1.22 chopps (u_long) card_addr)); 2697 1.22 chopps 2698 1.117 perry /* 2699 1.22 chopps * include the offset in the size, and decrement size by one, since 2700 1.22 chopps * the hw wants start/stop 2701 1.22 chopps */ 2702 1.22 chopps size += *offsetp - 1; 2703 1.22 chopps 2704 1.22 chopps card_offset = (((long)card_addr) - ((long)busaddr)); 2705 1.22 chopps 2706 1.22 chopps ph->mem[win].addr = busaddr; 2707 1.22 chopps ph->mem[win].size = size; 2708 1.22 chopps ph->mem[win].offset = card_offset; 2709 1.22 chopps ph->mem[win].kind = kind; 2710 1.1 haya 2711 1.176 drochner pccbb_pcmcia_do_mem_map(sc, win); 2712 1.1 haya 2713 1.22 chopps return 0; 2714 1.1 haya } 2715 1.1 haya 2716 1.4 haya /* 2717 1.4 haya * STATIC int pccbb_pcmcia_mem_unmap(pcmcia_chipset_handle_t pch, 2718 1.4 haya * int window) 2719 1.4 haya * 2720 1.32 enami * This function unmaps memory space which mapped by the function 2721 1.4 haya * pccbb_pcmcia_mem_map(). 2722 1.4 haya */ 2723 1.22 chopps STATIC void 2724 1.143 dyoung pccbb_pcmcia_mem_unmap(pcmcia_chipset_handle_t pch, int window) 2725 1.1 haya { 2726 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2727 1.177 drochner struct pcic_handle *ph = &sc->sc_pcmcia_h; 2728 1.22 chopps int reg; 2729 1.1 haya 2730 1.213 msaitoh if (window >= PCIC_MEM_WINS) 2731 1.22 chopps panic("pccbb_pcmcia_mem_unmap: window out of range"); 2732 1.1 haya 2733 1.177 drochner reg = Pcic_read(sc, PCIC_ADDRWIN_ENABLE); 2734 1.22 chopps reg &= ~(1 << window); 2735 1.177 drochner Pcic_write(sc, PCIC_ADDRWIN_ENABLE, reg); 2736 1.1 haya 2737 1.22 chopps ph->memalloc &= ~(1 << window); 2738 1.1 haya } 2739 1.1 haya 2740 1.4 haya /* 2741 1.4 haya * STATIC void *pccbb_pcmcia_intr_establish(pcmcia_chipset_handle_t pch, 2742 1.4 haya * struct pcmcia_function *pf, 2743 1.4 haya * int ipl, 2744 1.4 haya * int (*func)(void *), 2745 1.4 haya * void *arg); 2746 1.4 haya * 2747 1.4 haya * This function enables PC-Card interrupt. PCCBB uses PCI interrupt line. 2748 1.4 haya */ 2749 1.1 haya STATIC void * 2750 1.143 dyoung pccbb_pcmcia_intr_establish(pcmcia_chipset_handle_t pch, 2751 1.143 dyoung struct pcmcia_function *pf, int ipl, int (*func)(void *), void *arg) 2752 1.22 chopps { 2753 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2754 1.22 chopps 2755 1.209 christos if (!(pf->cfe->flags & (PCMCIA_CFE_IRQLEVEL|PCMCIA_CFE_IRQPULSE))) { 2756 1.117 perry /* 2757 1.22 chopps * XXX Noooooo! The interrupt flag must set properly!! 2758 1.22 chopps * dumb pcmcia driver!! 2759 1.22 chopps */ 2760 1.209 christos DPRINTF(("%s does not provide edge nor pulse interrupt\n", 2761 1.209 christos device_xname(sc->sc_dev))); 2762 1.209 christos return NULL; 2763 1.22 chopps } 2764 1.1 haya 2765 1.203 drochner return pccbb_intr_establish(sc, ipl, func, arg); 2766 1.1 haya } 2767 1.1 haya 2768 1.4 haya /* 2769 1.4 haya * STATIC void pccbb_pcmcia_intr_disestablish(pcmcia_chipset_handle_t pch, 2770 1.4 haya * void *ih) 2771 1.4 haya * 2772 1.4 haya * This function disables PC-Card interrupt. 2773 1.4 haya */ 2774 1.1 haya STATIC void 2775 1.143 dyoung pccbb_pcmcia_intr_disestablish(pcmcia_chipset_handle_t pch, void *ih) 2776 1.1 haya { 2777 1.177 drochner struct pccbb_softc *sc = (struct pccbb_softc *)pch; 2778 1.1 haya 2779 1.26 haya pccbb_intr_disestablish(sc, ih); 2780 1.1 haya } 2781 1.1 haya 2782 1.1 haya #if rbus 2783 1.4 haya /* 2784 1.4 haya * static int 2785 1.4 haya * pccbb_rbus_cb_space_alloc(cardbus_chipset_tag_t ct, rbus_tag_t rb, 2786 1.4 haya * bus_addr_t addr, bus_size_t size, 2787 1.4 haya * bus_addr_t mask, bus_size_t align, 2788 1.4 haya * int flags, bus_addr_t *addrp; 2789 1.4 haya * bus_space_handle_t *bshp) 2790 1.4 haya * 2791 1.4 haya * This function allocates a portion of memory or io space for 2792 1.4 haya * clients. This function is called from CardBus card drivers. 2793 1.4 haya */ 2794 1.1 haya static int 2795 1.143 dyoung pccbb_rbus_cb_space_alloc(cardbus_chipset_tag_t ct, rbus_tag_t rb, 2796 1.143 dyoung bus_addr_t addr, bus_size_t size, bus_addr_t mask, bus_size_t align, 2797 1.143 dyoung int flags, bus_addr_t *addrp, bus_space_handle_t *bshp) 2798 1.22 chopps { 2799 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)ct; 2800 1.22 chopps 2801 1.95 christos DPRINTF(("pccbb_rbus_cb_space_alloc: addr 0x%lx, size 0x%lx, " 2802 1.95 christos "mask 0x%lx, align 0x%lx\n", (unsigned long)addr, 2803 1.95 christos (unsigned long)size, (unsigned long)mask, (unsigned long)align)); 2804 1.1 haya 2805 1.213 msaitoh if (align == 0) 2806 1.22 chopps align = size; 2807 1.1 haya 2808 1.198 dyoung if (bus_space_is_equal(rb->rb_bt, sc->sc_memt)) { 2809 1.22 chopps if (align < 16) { 2810 1.22 chopps return 1; 2811 1.68 yamt } 2812 1.76 haya /* 2813 1.76 haya * XXX: align more than 0x1000 to avoid overwrapping 2814 1.76 haya * memory windows for two or more devices. 0x1000 2815 1.76 haya * means memory window's granularity. 2816 1.76 haya * 2817 1.76 haya * Two or more devices should be able to share same 2818 1.76 haya * memory window region. However, overrapping memory 2819 1.76 haya * window is not good because some devices, such as 2820 1.76 haya * 3Com 3C575[BC], have a broken address decoder and 2821 1.76 haya * intrude other's memory region. 2822 1.76 haya */ 2823 1.68 yamt if (align < 0x1000) { 2824 1.68 yamt align = 0x1000; 2825 1.22 chopps } 2826 1.198 dyoung } else if (bus_space_is_equal(rb->rb_bt, sc->sc_iot)) { 2827 1.22 chopps if (align < 4) { 2828 1.22 chopps return 1; 2829 1.22 chopps } 2830 1.36 haya /* XXX: hack for avoiding ISA image */ 2831 1.36 haya if (mask < 0x0100) { 2832 1.36 haya mask = 0x3ff; 2833 1.36 haya addr = 0x300; 2834 1.36 haya } 2835 1.36 haya 2836 1.22 chopps } else { 2837 1.95 christos DPRINTF(("pccbb_rbus_cb_space_alloc: Bus space tag 0x%lx is " 2838 1.95 christos "NOT used. io: 0x%lx, mem: 0x%lx\n", 2839 1.95 christos (unsigned long)rb->rb_bt, (unsigned long)sc->sc_iot, 2840 1.95 christos (unsigned long)sc->sc_memt)); 2841 1.22 chopps return 1; 2842 1.22 chopps /* XXX: panic here? */ 2843 1.22 chopps } 2844 1.1 haya 2845 1.22 chopps if (rbus_space_alloc(rb, addr, size, mask, align, flags, addrp, bshp)) { 2846 1.172 drochner aprint_normal_dev(sc->sc_dev, "<rbus> no bus space\n"); 2847 1.22 chopps return 1; 2848 1.22 chopps } 2849 1.1 haya 2850 1.22 chopps pccbb_open_win(sc, rb->rb_bt, *addrp, size, *bshp, 0); 2851 1.1 haya 2852 1.22 chopps return 0; 2853 1.1 haya } 2854 1.1 haya 2855 1.4 haya /* 2856 1.4 haya * static int 2857 1.4 haya * pccbb_rbus_cb_space_free(cardbus_chipset_tag_t *ct, rbus_tag_t rb, 2858 1.4 haya * bus_space_handle_t *bshp, bus_size_t size); 2859 1.4 haya * 2860 1.4 haya * This function is called from CardBus card drivers. 2861 1.4 haya */ 2862 1.1 haya static int 2863 1.143 dyoung pccbb_rbus_cb_space_free(cardbus_chipset_tag_t ct, rbus_tag_t rb, 2864 1.143 dyoung bus_space_handle_t bsh, bus_size_t size) 2865 1.22 chopps { 2866 1.22 chopps struct pccbb_softc *sc = (struct pccbb_softc *)ct; 2867 1.22 chopps bus_space_tag_t bt = rb->rb_bt; 2868 1.22 chopps 2869 1.22 chopps pccbb_close_win(sc, bt, bsh, size); 2870 1.22 chopps 2871 1.198 dyoung if (bus_space_is_equal(bt, sc->sc_memt)) { 2872 1.198 dyoung } else if (bus_space_is_equal(bt, sc->sc_iot)) { 2873 1.22 chopps } else { 2874 1.22 chopps return 1; 2875 1.22 chopps /* XXX: panic here? */ 2876 1.22 chopps } 2877 1.1 haya 2878 1.22 chopps return rbus_space_free(rb, bsh, size, NULL); 2879 1.1 haya } 2880 1.1 haya #endif /* rbus */ 2881 1.1 haya 2882 1.1 haya #if rbus 2883 1.1 haya 2884 1.1 haya static int 2885 1.143 dyoung pccbb_open_win(struct pccbb_softc *sc, bus_space_tag_t bst, bus_addr_t addr, 2886 1.143 dyoung bus_size_t size, bus_space_handle_t bsh, int flags) 2887 1.22 chopps { 2888 1.27 thorpej struct pccbb_win_chain_head *head; 2889 1.22 chopps bus_addr_t align; 2890 1.22 chopps 2891 1.27 thorpej head = &sc->sc_iowindow; 2892 1.22 chopps align = 0x04; 2893 1.198 dyoung if (bus_space_is_equal(sc->sc_memt, bst)) { 2894 1.27 thorpej head = &sc->sc_memwindow; 2895 1.22 chopps align = 0x1000; 2896 1.95 christos DPRINTF(("using memory window, 0x%lx 0x%lx 0x%lx\n\n", 2897 1.95 christos (unsigned long)sc->sc_iot, (unsigned long)sc->sc_memt, 2898 1.95 christos (unsigned long)bst)); 2899 1.22 chopps } 2900 1.1 haya 2901 1.27 thorpej if (pccbb_winlist_insert(head, addr, size, bsh, flags)) { 2902 1.172 drochner aprint_error_dev(sc->sc_dev, 2903 1.164 dyoung "pccbb_open_win: %s winlist insert failed\n", 2904 1.27 thorpej (head == &sc->sc_memwindow) ? "mem" : "io"); 2905 1.22 chopps } 2906 1.22 chopps pccbb_winset(align, sc, bst); 2907 1.1 haya 2908 1.22 chopps return 0; 2909 1.1 haya } 2910 1.1 haya 2911 1.1 haya static int 2912 1.143 dyoung pccbb_close_win(struct pccbb_softc *sc, bus_space_tag_t bst, 2913 1.143 dyoung bus_space_handle_t bsh, bus_size_t size) 2914 1.22 chopps { 2915 1.27 thorpej struct pccbb_win_chain_head *head; 2916 1.22 chopps bus_addr_t align; 2917 1.22 chopps 2918 1.27 thorpej head = &sc->sc_iowindow; 2919 1.22 chopps align = 0x04; 2920 1.198 dyoung if (bus_space_is_equal(sc->sc_memt, bst)) { 2921 1.27 thorpej head = &sc->sc_memwindow; 2922 1.22 chopps align = 0x1000; 2923 1.22 chopps } 2924 1.1 haya 2925 1.27 thorpej if (pccbb_winlist_delete(head, bsh, size)) { 2926 1.172 drochner aprint_error_dev(sc->sc_dev, 2927 1.164 dyoung "pccbb_close_win: %s winlist delete failed\n", 2928 1.27 thorpej (head == &sc->sc_memwindow) ? "mem" : "io"); 2929 1.22 chopps } 2930 1.22 chopps pccbb_winset(align, sc, bst); 2931 1.1 haya 2932 1.22 chopps return 0; 2933 1.1 haya } 2934 1.1 haya 2935 1.1 haya static int 2936 1.143 dyoung pccbb_winlist_insert(struct pccbb_win_chain_head *head, bus_addr_t start, 2937 1.143 dyoung bus_size_t size, bus_space_handle_t bsh, int flags) 2938 1.22 chopps { 2939 1.27 thorpej struct pccbb_win_chain *chainp, *elem; 2940 1.22 chopps 2941 1.215 chs elem = malloc(sizeof(struct pccbb_win_chain), M_DEVBUF, 2942 1.215 chs M_WAITOK); 2943 1.27 thorpej elem->wc_start = start; 2944 1.27 thorpej elem->wc_end = start + (size - 1); 2945 1.27 thorpej elem->wc_handle = bsh; 2946 1.27 thorpej elem->wc_flags = flags; 2947 1.1 haya 2948 1.154 dyoung TAILQ_FOREACH(chainp, head, wc_list) { 2949 1.154 dyoung if (chainp->wc_end >= start) 2950 1.154 dyoung break; 2951 1.154 dyoung } 2952 1.154 dyoung if (chainp != NULL) 2953 1.27 thorpej TAILQ_INSERT_AFTER(head, chainp, elem, wc_list); 2954 1.154 dyoung else 2955 1.154 dyoung TAILQ_INSERT_TAIL(head, elem, wc_list); 2956 1.213 msaitoh return 0; 2957 1.1 haya } 2958 1.1 haya 2959 1.1 haya static int 2960 1.143 dyoung pccbb_winlist_delete(struct pccbb_win_chain_head *head, bus_space_handle_t bsh, 2961 1.143 dyoung bus_size_t size) 2962 1.1 haya { 2963 1.27 thorpej struct pccbb_win_chain *chainp; 2964 1.1 haya 2965 1.154 dyoung TAILQ_FOREACH(chainp, head, wc_list) { 2966 1.154 dyoung if (memcmp(&chainp->wc_handle, &bsh, sizeof(bsh)) == 0) 2967 1.154 dyoung break; 2968 1.154 dyoung } 2969 1.154 dyoung if (chainp == NULL) 2970 1.154 dyoung return 1; /* fail: no candidate to remove */ 2971 1.1 haya 2972 1.154 dyoung if ((chainp->wc_end - chainp->wc_start) != (size - 1)) { 2973 1.154 dyoung printf("pccbb_winlist_delete: window 0x%lx size " 2974 1.154 dyoung "inconsistent: 0x%lx, 0x%lx\n", 2975 1.154 dyoung (unsigned long)chainp->wc_start, 2976 1.154 dyoung (unsigned long)(chainp->wc_end - chainp->wc_start), 2977 1.154 dyoung (unsigned long)(size - 1)); 2978 1.154 dyoung return 1; 2979 1.154 dyoung } 2980 1.1 haya 2981 1.154 dyoung TAILQ_REMOVE(head, chainp, wc_list); 2982 1.154 dyoung free(chainp, M_DEVBUF); 2983 1.1 haya 2984 1.154 dyoung return 0; 2985 1.1 haya } 2986 1.1 haya 2987 1.1 haya static void 2988 1.143 dyoung pccbb_winset(bus_addr_t align, struct pccbb_softc *sc, bus_space_tag_t bst) 2989 1.22 chopps { 2990 1.22 chopps pci_chipset_tag_t pc; 2991 1.22 chopps pcitag_t tag; 2992 1.22 chopps bus_addr_t mask = ~(align - 1); 2993 1.22 chopps struct { 2994 1.195 dyoung pcireg_t win_start; 2995 1.195 dyoung pcireg_t win_limit; 2996 1.22 chopps int win_flags; 2997 1.22 chopps } win[2]; 2998 1.22 chopps struct pccbb_win_chain *chainp; 2999 1.22 chopps int offs; 3000 1.22 chopps 3001 1.61 enami win[0].win_start = win[1].win_start = 0xffffffff; 3002 1.61 enami win[0].win_limit = win[1].win_limit = 0; 3003 1.61 enami win[0].win_flags = win[1].win_flags = 0; 3004 1.22 chopps 3005 1.27 thorpej chainp = TAILQ_FIRST(&sc->sc_iowindow); 3006 1.161 dyoung offs = PCI_CB_IOBASE0; 3007 1.198 dyoung if (bus_space_is_equal(sc->sc_memt, bst)) { 3008 1.27 thorpej chainp = TAILQ_FIRST(&sc->sc_memwindow); 3009 1.161 dyoung offs = PCI_CB_MEMBASE0; 3010 1.22 chopps } 3011 1.1 haya 3012 1.27 thorpej if (chainp != NULL) { 3013 1.22 chopps win[0].win_start = chainp->wc_start & mask; 3014 1.22 chopps win[0].win_limit = chainp->wc_end & mask; 3015 1.22 chopps win[0].win_flags = chainp->wc_flags; 3016 1.27 thorpej chainp = TAILQ_NEXT(chainp, wc_list); 3017 1.1 haya } 3018 1.1 haya 3019 1.27 thorpej for (; chainp != NULL; chainp = TAILQ_NEXT(chainp, wc_list)) { 3020 1.22 chopps if (win[1].win_start == 0xffffffff) { 3021 1.22 chopps /* window 1 is not used */ 3022 1.22 chopps if ((win[0].win_flags == chainp->wc_flags) && 3023 1.22 chopps (win[0].win_limit + align >= 3024 1.22 chopps (chainp->wc_start & mask))) { 3025 1.27 thorpej /* concatenate */ 3026 1.22 chopps win[0].win_limit = chainp->wc_end & mask; 3027 1.22 chopps } else { 3028 1.22 chopps /* make new window */ 3029 1.22 chopps win[1].win_start = chainp->wc_start & mask; 3030 1.22 chopps win[1].win_limit = chainp->wc_end & mask; 3031 1.22 chopps win[1].win_flags = chainp->wc_flags; 3032 1.22 chopps } 3033 1.22 chopps continue; 3034 1.22 chopps } 3035 1.22 chopps 3036 1.32 enami /* Both windows are engaged. */ 3037 1.22 chopps if (win[0].win_flags == win[1].win_flags) { 3038 1.22 chopps /* same flags */ 3039 1.22 chopps if (win[0].win_flags == chainp->wc_flags) { 3040 1.22 chopps if (win[1].win_start - (win[0].win_limit + 3041 1.22 chopps align) < 3042 1.22 chopps (chainp->wc_start & mask) - 3043 1.22 chopps ((chainp->wc_end & mask) + align)) { 3044 1.22 chopps /* 3045 1.22 chopps * merge window 0 and 1, and set win1 3046 1.22 chopps * to chainp 3047 1.22 chopps */ 3048 1.22 chopps win[0].win_limit = win[1].win_limit; 3049 1.22 chopps win[1].win_start = 3050 1.22 chopps chainp->wc_start & mask; 3051 1.22 chopps win[1].win_limit = 3052 1.22 chopps chainp->wc_end & mask; 3053 1.22 chopps } else { 3054 1.22 chopps win[1].win_limit = 3055 1.22 chopps chainp->wc_end & mask; 3056 1.22 chopps } 3057 1.22 chopps } else { 3058 1.22 chopps /* different flags */ 3059 1.22 chopps 3060 1.27 thorpej /* concatenate win0 and win1 */ 3061 1.22 chopps win[0].win_limit = win[1].win_limit; 3062 1.22 chopps /* allocate win[1] to new space */ 3063 1.22 chopps win[1].win_start = chainp->wc_start & mask; 3064 1.22 chopps win[1].win_limit = chainp->wc_end & mask; 3065 1.22 chopps win[1].win_flags = chainp->wc_flags; 3066 1.22 chopps } 3067 1.22 chopps } else { 3068 1.22 chopps /* the flags of win[0] and win[1] is different */ 3069 1.22 chopps if (win[0].win_flags == chainp->wc_flags) { 3070 1.22 chopps win[0].win_limit = chainp->wc_end & mask; 3071 1.22 chopps /* 3072 1.22 chopps * XXX this creates overlapping windows, so 3073 1.22 chopps * what should the poor bridge do if one is 3074 1.22 chopps * cachable, and the other is not? 3075 1.22 chopps */ 3076 1.172 drochner aprint_error_dev(sc->sc_dev, 3077 1.164 dyoung "overlapping windows\n"); 3078 1.22 chopps } else { 3079 1.22 chopps win[1].win_limit = chainp->wc_end & mask; 3080 1.22 chopps } 3081 1.22 chopps } 3082 1.22 chopps } 3083 1.1 haya 3084 1.22 chopps pc = sc->sc_pc; 3085 1.22 chopps tag = sc->sc_tag; 3086 1.22 chopps pci_conf_write(pc, tag, offs, win[0].win_start); 3087 1.22 chopps pci_conf_write(pc, tag, offs + 4, win[0].win_limit); 3088 1.22 chopps pci_conf_write(pc, tag, offs + 8, win[1].win_start); 3089 1.22 chopps pci_conf_write(pc, tag, offs + 12, win[1].win_limit); 3090 1.95 christos DPRINTF(("--pccbb_winset: win0 [0x%lx, 0x%lx), win1 [0x%lx, 0x%lx)\n", 3091 1.95 christos (unsigned long)pci_conf_read(pc, tag, offs), 3092 1.95 christos (unsigned long)pci_conf_read(pc, tag, offs + 4) + align, 3093 1.95 christos (unsigned long)pci_conf_read(pc, tag, offs + 8), 3094 1.95 christos (unsigned long)pci_conf_read(pc, tag, offs + 12) + align)); 3095 1.22 chopps 3096 1.198 dyoung if (bus_space_is_equal(bst, sc->sc_memt)) { 3097 1.146 dyoung pcireg_t bcr = pci_conf_read(pc, tag, PCI_BRIDGE_CONTROL_REG); 3098 1.61 enami 3099 1.61 enami bcr &= ~(CB_BCR_PREFETCH_MEMWIN0 | CB_BCR_PREFETCH_MEMWIN1); 3100 1.61 enami if (win[0].win_flags & PCCBB_MEM_CACHABLE) 3101 1.22 chopps bcr |= CB_BCR_PREFETCH_MEMWIN0; 3102 1.61 enami if (win[1].win_flags & PCCBB_MEM_CACHABLE) 3103 1.22 chopps bcr |= CB_BCR_PREFETCH_MEMWIN1; 3104 1.146 dyoung pci_conf_write(pc, tag, PCI_BRIDGE_CONTROL_REG, bcr); 3105 1.22 chopps } 3106 1.1 haya } 3107 1.1 haya 3108 1.1 haya #endif /* rbus */ 3109 1.25 enami 3110 1.156 jmcneill static bool 3111 1.194 dyoung pccbb_suspend(device_t dv, const pmf_qual_t *qual) 3112 1.25 enami { 3113 1.156 jmcneill struct pccbb_softc *sc = device_private(dv); 3114 1.213 msaitoh bus_space_tag_t base_memt = sc->sc_base_memt; /* socket regs memory */ 3115 1.25 enami bus_space_handle_t base_memh = sc->sc_base_memh; 3116 1.156 jmcneill pcireg_t reg; 3117 1.25 enami 3118 1.156 jmcneill if (sc->sc_pil_intr_enable) 3119 1.156 jmcneill (void)pccbbintr_function(sc); 3120 1.199 dyoung sc->sc_pil_intr_enable = false; 3121 1.25 enami 3122 1.156 jmcneill reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK); 3123 1.156 jmcneill /* Disable interrupts. */ 3124 1.156 jmcneill reg &= ~(CB_SOCKET_MASK_CSTS | CB_SOCKET_MASK_CD | CB_SOCKET_MASK_POWER); 3125 1.156 jmcneill bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, reg); 3126 1.156 jmcneill /* XXX joerg Disable power to the socket? */ 3127 1.38 haya 3128 1.165 dyoung /* XXX flush PCI write */ 3129 1.165 dyoung bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT); 3130 1.165 dyoung 3131 1.165 dyoung /* reset interrupt */ 3132 1.165 dyoung bus_space_write_4(base_memt, base_memh, CB_SOCKET_EVENT, 3133 1.165 dyoung bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT)); 3134 1.165 dyoung /* XXX flush PCI write */ 3135 1.165 dyoung bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT); 3136 1.165 dyoung 3137 1.165 dyoung if (sc->sc_ih != NULL) { 3138 1.165 dyoung pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 3139 1.165 dyoung sc->sc_ih = NULL; 3140 1.165 dyoung } 3141 1.165 dyoung 3142 1.156 jmcneill return true; 3143 1.156 jmcneill } 3144 1.129 jmcneill 3145 1.156 jmcneill static bool 3146 1.194 dyoung pccbb_resume(device_t dv, const pmf_qual_t *qual) 3147 1.156 jmcneill { 3148 1.156 jmcneill struct pccbb_softc *sc = device_private(dv); 3149 1.213 msaitoh bus_space_tag_t base_memt = sc->sc_base_memt; /* socket regs memory */ 3150 1.156 jmcneill bus_space_handle_t base_memh = sc->sc_base_memh; 3151 1.156 jmcneill pcireg_t reg; 3152 1.38 haya 3153 1.156 jmcneill pccbb_chipinit(sc); 3154 1.165 dyoung pccbb_intrinit(sc); 3155 1.156 jmcneill /* setup memory and io space window for CB */ 3156 1.156 jmcneill pccbb_winset(0x1000, sc, sc->sc_memt); 3157 1.156 jmcneill pccbb_winset(0x04, sc, sc->sc_iot); 3158 1.156 jmcneill 3159 1.156 jmcneill /* CSC Interrupt: Card detect interrupt on */ 3160 1.156 jmcneill reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK); 3161 1.156 jmcneill /* Card detect intr is turned on. */ 3162 1.165 dyoung reg |= CB_SOCKET_MASK_CSTS | CB_SOCKET_MASK_CD | CB_SOCKET_MASK_POWER; 3163 1.156 jmcneill bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, reg); 3164 1.156 jmcneill /* reset interrupt */ 3165 1.156 jmcneill reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT); 3166 1.156 jmcneill bus_space_write_4(base_memt, base_memh, CB_SOCKET_EVENT, reg); 3167 1.70 haya 3168 1.156 jmcneill /* 3169 1.156 jmcneill * check for card insertion or removal during suspend period. 3170 1.156 jmcneill * XXX: the code can't cope with card swap (remove then 3171 1.156 jmcneill * insert). how can we detect such situation? 3172 1.156 jmcneill */ 3173 1.156 jmcneill (void)pccbbintr(sc); 3174 1.129 jmcneill 3175 1.199 dyoung sc->sc_pil_intr_enable = true; 3176 1.25 enami 3177 1.156 jmcneill return true; 3178 1.25 enami } 3179