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