pccbb_isa.c revision 261790
1139749Simp/*- 2133553Simp * Copyright (c) 2002-2004 M. Warner Losh. 3133553Simp * All rights reserved. 4133553Simp * 5133553Simp * Redistribution and use in source and binary forms, with or without 6133553Simp * modification, are permitted provided that the following conditions 7133553Simp * are met: 8133553Simp * 1. Redistributions of source code must retain the above copyright 9140035Simp * notice, this list of conditions and the following disclaimer. 10133553Simp * 2. Redistributions in binary form must reproduce the above copyright 11140035Simp * notice, this list of conditions and the following disclaimer in the 12140035Simp * documentation and/or other materials provided with the distribution. 13133553Simp * 14133553Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15133553Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16133553Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17140035Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18140035Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19133553Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20133553Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21133553Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22133553Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23133553Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24133553Simp * SUCH DAMAGE. 25133553Simp */ 26133553Simp 27133553Simp/* 28133553Simp * Driver for ISA to PCMCIA bridges compliant with the Intel ExCA 29133553Simp * specification. 30133553Simp */ 31133553Simp 32133553Simp#include <sys/cdefs.h> 33133553Simp__FBSDID("$FreeBSD: head/sys/dev/pccbb/pccbb_isa.c 261790 2014-02-12 04:30:37Z jhb $"); 34133553Simp 35133553Simp#include <sys/param.h> 36133553Simp#include <sys/systm.h> 37133553Simp#include <sys/proc.h> 38133553Simp#include <sys/condvar.h> 39133553Simp#include <sys/errno.h> 40133553Simp#include <sys/kernel.h> 41133553Simp#include <sys/lock.h> 42133553Simp#include <sys/malloc.h> 43133553Simp#include <sys/module.h> 44133553Simp#include <sys/mutex.h> 45133553Simp#include <sys/sysctl.h> 46133553Simp#include <sys/kthread.h> 47133553Simp#include <sys/bus.h> 48133553Simp#include <machine/bus.h> 49133553Simp#include <sys/rman.h> 50133553Simp#include <machine/resource.h> 51133553Simp 52133553Simp#include <isa/isavar.h> 53133553Simp 54261790Sjhb#include <dev/pci/pcivar.h> 55261790Sjhb#include <dev/pci/pcib_private.h> 56261790Sjhb 57133553Simp#include <dev/pccard/pccardreg.h> 58133553Simp#include <dev/pccard/pccardvar.h> 59133553Simp 60133553Simp#include <dev/exca/excareg.h> 61133553Simp#include <dev/exca/excavar.h> 62133553Simp 63133553Simp#include <dev/pccbb/pccbbreg.h> 64133553Simp#include <dev/pccbb/pccbbvar.h> 65133553Simp 66133553Simp#include "power_if.h" 67133553Simp#include "card_if.h" 68133553Simp 69133553Simp/***************************************************************************** 70133553Simp * Configurable parameters. 71133553Simp *****************************************************************************/ 72133553Simp 73133553Simp/* sysctl vars */ 74227309Sedstatic SYSCTL_NODE(_hw, OID_AUTO, pcic, CTLFLAG_RD, 0, "PCIC parameters"); 75133553Simp 76133553Simpstatic int isa_intr_mask = EXCA_INT_MASK_ALLOWED; 77133553SimpTUNABLE_INT("hw.cbb.intr_mask", &isa_intr_mask); 78133553SimpSYSCTL_INT(_hw_pcic, OID_AUTO, intr_mask, CTLFLAG_RD, &isa_intr_mask, 0, 79133553Simp "Mask of allowable interrupts for this laptop. The default is generally\n\ 80133553Simpcorrect, but some laptops do not route all the IRQ pins to the bridge to\n\ 81133553Simpsave wires. Sometimes you need a more restrictive mask because some of the\n\ 82133553Simphardware in your laptop may not have a driver so its IRQ might not be\n\ 83133553Simpallocated."); 84133553Simp 85151308Simp/* 86151308Simp * CL-PD6722's VSENSE method 87151308Simp * 0: NO VSENSE (assume a 5.0V card always) 88151308Simp * 1: 6710's method (default) 89151308Simp * 2: 6729's method 90151308Simp */ 91151308Simpint pcic_pd6722_vsense = 1; 92151308SimpTUNABLE_INT("hw.pcic.pd6722_vsense", &pcic_pd6722_vsense); 93151308SimpSYSCTL_INT(_hw_pcic, OID_AUTO, pd6722_vsense, CTLFLAG_RDTUN, 94151308Simp &pcic_pd6722_vsense, 1, 95151308Simp "Select CL-PD6722's VSENSE method. VSENSE is used to determine the\n\ 96151308Simpvolatage of inserted cards. The CL-PD6722 has two methods to determine the\n\ 97151308Simpvoltage of the card. 0 means assume a 5.0V card and do not check. 1 means\n\ 98151308Simpuse the same method that the CL-PD6710 uses (default). 2 means use the\n\ 99151308Simpsame method as the CL-PD6729. 2 is documented in the datasheet as being\n\ 100151308Simpthe correct way, but 1 seems to give better results on more laptops."); 101151308Simp 102133553Simp/***************************************************************************** 103133553Simp * End of configurable parameters. 104133553Simp *****************************************************************************/ 105133553Simp 106133553Simp#define DPRINTF(x) do { if (cbb_debug) printf x; } while (0) 107133553Simp#define DEVPRINTF(x) do { if (cbb_debug) device_printf x; } while (0) 108133553Simp 109151308Simp/* XXX Not sure that PNP0E03 should be claimed, except maybe on pc98 */ 110133553Simpstatic struct isa_pnp_id pcic_ids[] = { 111133553Simp {EXCA_PNP_ACTIONTEC, NULL}, /* AEI0218 */ 112133553Simp {EXCA_PNP_IBM3765, NULL}, /* IBM3765 */ 113133553Simp {EXCA_PNP_82365, NULL}, /* PNP0E00 */ 114133553Simp {EXCA_PNP_CL_PD6720, NULL}, /* PNP0E01 */ 115133553Simp {EXCA_PNP_VLSI_82C146, NULL}, /* PNP0E02 */ 116133553Simp {EXCA_PNP_82365_CARDBUS, NULL}, /* PNP0E03 */ 117133553Simp {EXCA_PNP_SCM_SWAPBOX, NULL}, /* SCM0469 */ 118151308Simp {EXCA_NEC_PC9801_102, NULL}, /* NEC8091 */ 119151308Simp {EXCA_NEC_PC9821RA_E01, NULL}, /* NEC8121 */ 120133553Simp {0} 121133553Simp}; 122133553Simp 123133553Simp/************************************************************************/ 124133553Simp/* Probe/Attach */ 125133553Simp/************************************************************************/ 126133553Simp 127151308Simpstatic int 128151308Simpcbb_isa_activate(device_t dev) 129151308Simp{ 130151308Simp struct cbb_softc *sc = device_get_softc(dev); 131133553Simp struct resource *res; 132133553Simp int rid; 133133553Simp int i; 134133553Simp 135133553Simp /* A little bogus, but go ahead and get the irq for CSC events */ 136133553Simp rid = 0; 137133553Simp res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 138133553Simp if (res == NULL) { 139133553Simp /* 140133553Simp * No IRQ specified, find one. This can be due to the PnP 141133553Simp * data not specifying any IRQ, or the default kernel not 142133553Simp * assinging an IRQ. 143133553Simp */ 144151308Simp for (i = 0; i < 16 && res == NULL; i++) { 145133553Simp if (((1 << i) & isa_intr_mask) == 0) 146133553Simp continue; 147133553Simp res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, i, i, 148133553Simp 1, RF_ACTIVE); 149133553Simp } 150133553Simp } 151151308Simp if (res == NULL) 152151308Simp return (ENXIO); 153151308Simp sc->irq_res = res; 154151308Simp rid = 0; 155151308Simp res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); 156133553Simp if (res == NULL) { 157151308Simp bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); 158151308Simp sc->irq_res = NULL; 159151308Simp device_printf(dev, "Cannot allocate I/O\n"); 160133553Simp return (ENOMEM); 161133553Simp } 162151457Simp sc->bst = rman_get_bustag(res); 163151457Simp sc->bsh = rman_get_bushandle(res); 164151308Simp sc->base_res = res; 165151308Simp return (0); 166133553Simp} 167133553Simp 168133553Simpstatic void 169133553Simpcbb_isa_deactivate(device_t dev) 170133553Simp{ 171151308Simp struct cbb_softc *sc = device_get_softc(dev); 172151308Simp 173151308Simp if (sc->irq_res) 174151308Simp bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res); 175151308Simp sc->irq_res = NULL; 176151308Simp if (sc->base_res) 177151308Simp bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->base_res); 178151308Simp sc->base_res = NULL; 179133553Simp} 180133553Simp 181133553Simpstatic int 182133553Simpcbb_isa_probe(device_t dev) 183133553Simp{ 184133553Simp int error; 185133553Simp struct cbb_softc *sc = device_get_softc(dev); 186133553Simp 187133553Simp /* Check isapnp ids */ 188133553Simp error = ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids); 189133553Simp if (error != 0 && error != ENOENT) 190133553Simp return (error); 191133553Simp 192133553Simp error = cbb_isa_activate(dev); 193133553Simp if (error != 0) 194133553Simp return (error); 195133553Simp 196133553Simp /* Check to make sure that we have actual hardware */ 197133553Simp error = exca_probe_slots(dev, &sc->exca[0], sc->bst, sc->bsh); 198133553Simp cbb_isa_deactivate(dev); 199133553Simp return (error); 200133553Simp} 201133553Simp 202133553Simpstatic int 203133553Simpcbb_isa_attach(device_t dev) 204133553Simp{ 205133553Simp return (ENOMEM); 206133553Simp} 207133553Simp 208133553Simpstatic device_method_t cbb_methods[] = { 209133553Simp /* Device interface */ 210133553Simp DEVMETHOD(device_probe, cbb_isa_probe), 211133553Simp DEVMETHOD(device_attach, cbb_isa_attach), 212133553Simp DEVMETHOD(device_detach, cbb_detach), 213133553Simp DEVMETHOD(device_suspend, cbb_suspend), 214133553Simp DEVMETHOD(device_resume, cbb_resume), 215133553Simp 216133553Simp /* bus methods */ 217133553Simp DEVMETHOD(bus_read_ivar, cbb_read_ivar), 218133553Simp DEVMETHOD(bus_write_ivar, cbb_write_ivar), 219133553Simp DEVMETHOD(bus_alloc_resource, cbb_alloc_resource), 220133553Simp DEVMETHOD(bus_release_resource, cbb_release_resource), 221133553Simp DEVMETHOD(bus_activate_resource, cbb_activate_resource), 222133553Simp DEVMETHOD(bus_deactivate_resource, cbb_deactivate_resource), 223133553Simp DEVMETHOD(bus_driver_added, cbb_driver_added), 224133553Simp DEVMETHOD(bus_child_detached, cbb_child_detached), 225133553Simp DEVMETHOD(bus_setup_intr, cbb_setup_intr), 226133553Simp DEVMETHOD(bus_teardown_intr, cbb_teardown_intr), 227133553Simp DEVMETHOD(bus_child_present, cbb_child_present), 228133553Simp 229133553Simp /* 16-bit card interface */ 230133553Simp DEVMETHOD(card_set_res_flags, cbb_pcic_set_res_flags), 231133553Simp DEVMETHOD(card_set_memory_offset, cbb_pcic_set_memory_offset), 232133553Simp 233133553Simp /* power interface */ 234133553Simp DEVMETHOD(power_enable_socket, cbb_power_enable_socket), 235133553Simp DEVMETHOD(power_disable_socket, cbb_power_disable_socket), 236133553Simp 237227843Smarius DEVMETHOD_END 238133553Simp}; 239133553Simp 240133553Simpstatic driver_t cbb_isa_driver = { 241133553Simp "cbb", 242133553Simp cbb_methods, 243133553Simp sizeof(struct cbb_softc) 244133553Simp}; 245133553Simp 246133553SimpDRIVER_MODULE(cbb, isa, cbb_isa_driver, cbb_devclass, 0, 0); 247133553SimpMODULE_DEPEND(cbb, exca, 1, 1, 1); 248