aic_pccard.c revision 129764
1185029Spjd/*- 2185029Spjd * Copyright (c) 1999 Luoqi Chen. 3185029Spjd * All rights reserved. 4185029Spjd * 5185029Spjd * Redistribution and use in source and binary forms, with or without 6185029Spjd * modification, are permitted provided that the following conditions 7185029Spjd * are met: 8185029Spjd * 1. Redistributions of source code must retain the above copyright 9185029Spjd * notice, this list of conditions and the following disclaimer. 10185029Spjd * 2. Redistributions in binary form must reproduce the above copyright 11185029Spjd * notice, this list of conditions and the following disclaimer in the 12185029Spjd * documentation and/or other materials provided with the distribution. 13185029Spjd * 14185029Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15185029Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16185029Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17185029Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18185029Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19185029Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20185029Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21185029Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22219089Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23247265Smm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24185029Spjd * SUCH DAMAGE. 25185029Spjd */ 26185029Spjd 27185029Spjd#include <sys/cdefs.h> 28185029Spjd__FBSDID("$FreeBSD: head/sys/dev/aic/aic_pccard.c 129764 2004-05-27 03:49:45Z imp $"); 29185029Spjd 30185029Spjd#include <sys/param.h> 31185029Spjd#include <sys/kernel.h> 32185029Spjd#include <sys/module.h> 33185029Spjd#include <sys/bus.h> 34185029Spjd 35185029Spjd#include <machine/bus_pio.h> 36185029Spjd#include <machine/bus.h> 37185029Spjd#include <machine/resource.h> 38185029Spjd#include <sys/rman.h> 39185029Spjd 40185029Spjd#include <dev/aic/aicvar.h> 41185029Spjd#include <dev/pccard/pccardvar.h> 42185029Spjd 43185029Spjd#include "card_if.h" 44185029Spjd#include "pccarddevs.h" 45185029Spjd 46185029Spjdstruct aic_pccard_softc { 47185029Spjd struct aic_softc sc_aic; 48185029Spjd struct resource *sc_port; 49185029Spjd struct resource *sc_irq; 50185029Spjd void *sc_ih; 51185029Spjd}; 52185029Spjd 53185029Spjdstatic int aic_pccard_alloc_resources(device_t); 54185029Spjdstatic void aic_pccard_release_resources(device_t); 55185029Spjdstatic int aic_pccard_match(device_t); 56185029Spjdstatic int aic_pccard_probe(device_t); 57185029Spjdstatic int aic_pccard_attach(device_t); 58185029Spjd 59185029Spjdconst struct pccard_product aic_pccard_products[] = { 60185029Spjd PCMCIA_CARD(ADAPTEC, APA1460, 0), 61185029Spjd PCMCIA_CARD(ADAPTEC, APA1460A, 0), 62185029Spjd PCMCIA_CARD(NEWMEDIA, BUSTOASTER, 0), 63185029Spjd PCMCIA_CARD(NEWMEDIA, BUSTOASTER2, 0), 64185029Spjd PCMCIA_CARD(NEWMEDIA, BUSTOASTER3, 0), 65185029Spjd { NULL } 66185029Spjd}; 67185029Spjd 68219089Spjd#define AIC_PCCARD_PORTSIZE 0x20 69219089Spjd 70219089Spjdstatic int 71219089Spjdaic_pccard_alloc_resources(device_t dev) 72219089Spjd{ 73219089Spjd struct aic_pccard_softc *sc = device_get_softc(dev); 74219089Spjd int rid; 75219089Spjd 76219089Spjd sc->sc_port = sc->sc_irq = 0; 77219089Spjd 78219089Spjd rid = 0; 79219089Spjd sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 80185029Spjd 0ul, ~0ul, AIC_PCCARD_PORTSIZE, RF_ACTIVE); 81185029Spjd if (!sc->sc_port) 82185029Spjd return (ENOMEM); 83185029Spjd 84185029Spjd rid = 0; 85185029Spjd sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 86185029Spjd if (!sc->sc_irq) { 87219089Spjd aic_pccard_release_resources(dev); 88185029Spjd return (ENOMEM); 89185029Spjd } 90185029Spjd 91185029Spjd sc->sc_aic.unit = device_get_unit(dev); 92219089Spjd sc->sc_aic.tag = rman_get_bustag(sc->sc_port); 93185029Spjd sc->sc_aic.bsh = rman_get_bushandle(sc->sc_port); 94219089Spjd return (0); 95219089Spjd} 96185029Spjd 97185029Spjdstatic void 98185029Spjdaic_pccard_release_resources(device_t dev) 99185029Spjd{ 100185029Spjd struct aic_pccard_softc *sc = device_get_softc(dev); 101185029Spjd 102185029Spjd if (sc->sc_port) 103185029Spjd bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port); 104185029Spjd if (sc->sc_irq) 105185029Spjd bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq); 106185029Spjd sc->sc_port = sc->sc_irq = 0; 107185029Spjd} 108185029Spjd 109185029Spjdstatic int 110185029Spjdaic_pccard_match(device_t dev) 111185029Spjd{ 112185029Spjd const struct pccard_product *pp; 113185029Spjd 114185029Spjd if ((pp = pccard_product_lookup(dev, aic_pccard_products, 115185029Spjd sizeof(aic_pccard_products[0]), NULL)) != NULL) { 116185029Spjd if (pp->pp_name != NULL) 117185029Spjd device_set_desc(dev, pp->pp_name); 118185029Spjd return 0; 119185029Spjd } 120185029Spjd return EIO; 121185029Spjd} 122185029Spjd 123185029Spjdstatic int 124185029Spjdaic_pccard_probe(device_t dev) 125185029Spjd{ 126185029Spjd struct aic_pccard_softc *sc = device_get_softc(dev); 127185029Spjd struct aic_softc *aic = &sc->sc_aic; 128185029Spjd 129185029Spjd if (aic_pccard_alloc_resources(dev)) 130185029Spjd return (ENXIO); 131185029Spjd if (aic_probe(aic)) { 132185029Spjd aic_pccard_release_resources(dev); 133185029Spjd return (ENXIO); 134185029Spjd } 135185029Spjd aic_pccard_release_resources(dev); 136185029Spjd 137185029Spjd device_set_desc(dev, "Adaptec 6260/6360 SCSI controller"); 138185029Spjd return (0); 139185029Spjd} 140185029Spjd 141185029Spjdstatic int 142185029Spjdaic_pccard_attach(device_t dev) 143185029Spjd{ 144185029Spjd struct aic_pccard_softc *sc = device_get_softc(dev); 145185029Spjd struct aic_softc *aic = &sc->sc_aic; 146185029Spjd int error; 147185029Spjd 148185029Spjd error = aic_pccard_alloc_resources(dev); 149185029Spjd if (error) { 150185029Spjd device_printf(dev, "resource allocation failed\n"); 151185029Spjd return (error); 152185029Spjd } 153185029Spjd 154185029Spjd error = aic_attach(aic); 155185029Spjd if (error) { 156185029Spjd device_printf(dev, "attach failed\n"); 157185029Spjd aic_pccard_release_resources(dev); 158185029Spjd return (error); 159185029Spjd } 160185029Spjd 161219089Spjd error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_CAM|INTR_ENTROPY, 162219089Spjd aic_intr, aic, &sc->sc_ih); 163185029Spjd if (error) { 164185029Spjd device_printf(dev, "failed to register interrupt handler\n"); 165185029Spjd aic_pccard_release_resources(dev); 166185029Spjd return (error); 167185029Spjd } 168185029Spjd return (0); 169185029Spjd} 170185029Spjd 171219089Spjdstatic int 172185029Spjdaic_pccard_detach(device_t dev) 173185029Spjd{ 174185029Spjd struct aic_pccard_softc *sc = device_get_softc(dev); 175185029Spjd struct aic_softc *aic = &sc->sc_aic; 176185029Spjd int error; 177185029Spjd 178185029Spjd error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih); 179185029Spjd if (error) { 180185029Spjd device_printf(dev, "failed to unregister interrupt handler\n"); 181185029Spjd } 182185029Spjd 183185029Spjd error = aic_detach(aic); 184185029Spjd if (error) { 185185029Spjd device_printf(dev, "detach failed\n"); 186185029Spjd return (error); 187185029Spjd } 188185029Spjd 189185029Spjd aic_pccard_release_resources(dev); 190185029Spjd return (0); 191185029Spjd} 192185029Spjd 193185029Spjdstatic device_method_t aic_pccard_methods[] = { 194185029Spjd /* Device interface */ 195185029Spjd DEVMETHOD(device_probe, pccard_compat_probe), 196185029Spjd DEVMETHOD(device_attach, pccard_compat_attach), 197185029Spjd DEVMETHOD(device_detach, aic_pccard_detach), 198185029Spjd 199185029Spjd /* Card interface */ 200185029Spjd DEVMETHOD(card_compat_match, aic_pccard_match), 201185029Spjd DEVMETHOD(card_compat_probe, aic_pccard_probe), 202185029Spjd DEVMETHOD(card_compat_attach, aic_pccard_attach), 203185029Spjd 204185029Spjd { 0, 0 } 205185029Spjd}; 206185029Spjd 207185029Spjdstatic driver_t aic_pccard_driver = { 208185029Spjd "aic", 209185029Spjd aic_pccard_methods, sizeof(struct aic_pccard_softc), 210185029Spjd}; 211185029Spjd 212185029Spjdextern devclass_t aic_devclass; 213185029Spjd 214185029SpjdMODULE_DEPEND(aic, cam, 1,1,1); 215185029SpjdDRIVER_MODULE(aic, pccard, aic_pccard_driver, aic_devclass, 0, 0); 216185029Spjd