aic_pccard.c revision 73280
1272343Sngie/*- 2272343Sngie * Copyright (c) 1999 Luoqi Chen. 3272343Sngie * All rights reserved. 4272343Sngie * 5272343Sngie * Redistribution and use in source and binary forms, with or without 6272343Sngie * modification, are permitted provided that the following conditions 7272343Sngie * are met: 8272343Sngie * 1. Redistributions of source code must retain the above copyright 9272343Sngie * notice, this list of conditions and the following disclaimer. 10272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer in the 12272343Sngie * documentation and/or other materials provided with the distribution. 13272343Sngie * 14272343Sngie * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15272343Sngie * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16272343Sngie * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17272343Sngie * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18272343Sngie * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20272343Sngie * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21272343Sngie * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22272343Sngie * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23272343Sngie * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24272343Sngie * SUCH DAMAGE. 25272343Sngie * 26272343Sngie * $FreeBSD: head/sys/dev/aic/aic_pccard.c 73280 2001-03-01 17:09:09Z markm $ 27272343Sngie */ 28272343Sngie 29272343Sngie#include <sys/param.h> 30272343Sngie#include <sys/kernel.h> 31272343Sngie#include <sys/module.h> 32272343Sngie#include <sys/bus.h> 33272343Sngie 34272343Sngie#include <machine/bus_pio.h> 35272343Sngie#include <machine/bus.h> 36272343Sngie#include <machine/resource.h> 37272343Sngie#include <sys/rman.h> 38272343Sngie 39272343Sngie#include <dev/aic/aicvar.h> 40272343Sngie#include <dev/pccard/pccardvar.h> 41272343Sngie#include <dev/pccard/pccarddevs.h> 42272343Sngie 43272343Sngie#include "card_if.h" 44272343Sngie 45272343Sngiestruct aic_pccard_softc { 46272343Sngie struct aic_softc sc_aic; 47272343Sngie struct resource *sc_port; 48272343Sngie struct resource *sc_irq; 49272343Sngie void *sc_ih; 50272343Sngie}; 51272343Sngie 52272343Sngiestatic int aic_pccard_alloc_resources(device_t); 53272343Sngiestatic void aic_pccard_release_resources(device_t); 54272343Sngiestatic int aic_pccard_match(device_t); 55272343Sngiestatic int aic_pccard_probe(device_t); 56272343Sngiestatic int aic_pccard_attach(device_t); 57272343Sngie 58272343Sngieconst struct pccard_product aic_pccard_products[] = { 59272343Sngie { PCCARD_STR_ADAPTEC_APA1460, PCCARD_VENDOR_ADAPTEC, 60272343Sngie PCCARD_PRODUCT_ADAPTEC_APA1460, 0, 61272343Sngie PCCARD_CIS_ADAPTEC_APA1460 }, 62272343Sngie { PCCARD_STR_ADAPTEC_APA1460A, PCCARD_VENDOR_ADAPTEC, 63272343Sngie PCCARD_PRODUCT_ADAPTEC_APA1460A, 0, 64272343Sngie PCCARD_CIS_ADAPTEC_APA1460A }, 65272343Sngie { PCCARD_STR_NEWMEDIA_BUSTOASTER, PCCARD_VENDOR_NEWMEDIA, 66272343Sngie PCCARD_PRODUCT_NEWMEDIA_BUSTOASTER, 0, 67272343Sngie PCCARD_CIS_NEWMEDIA_BUSTOASTER }, 68272343Sngie { NULL } 69272343Sngie}; 70272343Sngie 71272343Sngie#define AIC_PCCARD_PORTSIZE 0x20 72272343Sngie 73272343Sngiestatic int 74272343Sngieaic_pccard_alloc_resources(device_t dev) 75272343Sngie{ 76272343Sngie struct aic_pccard_softc *sc = device_get_softc(dev); 77272343Sngie int rid; 78272343Sngie 79272343Sngie sc->sc_port = sc->sc_irq = 0; 80272343Sngie 81272343Sngie rid = 0; 82272343Sngie sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 83272343Sngie 0ul, ~0ul, AIC_PCCARD_PORTSIZE, RF_ACTIVE); 84272343Sngie if (!sc->sc_port) 85272343Sngie return (ENOMEM); 86272343Sngie 87272343Sngie rid = 0; 88272343Sngie sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 89272343Sngie 0ul, ~0ul, 1, RF_ACTIVE); 90272343Sngie if (!sc->sc_irq) { 91272343Sngie aic_pccard_release_resources(dev); 92272343Sngie return (ENOMEM); 93272343Sngie } 94272343Sngie 95272343Sngie sc->sc_aic.unit = device_get_unit(dev); 96272343Sngie sc->sc_aic.tag = rman_get_bustag(sc->sc_port); 97272343Sngie sc->sc_aic.bsh = rman_get_bushandle(sc->sc_port); 98272343Sngie return (0); 99272343Sngie} 100272343Sngie 101272343Sngiestatic void 102272343Sngieaic_pccard_release_resources(device_t dev) 103272343Sngie{ 104272343Sngie struct aic_pccard_softc *sc = device_get_softc(dev); 105272343Sngie 106272343Sngie if (sc->sc_port) 107272343Sngie bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port); 108272343Sngie if (sc->sc_irq) 109272343Sngie bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq); 110272343Sngie sc->sc_port = sc->sc_irq = 0; 111272343Sngie} 112272343Sngie 113272343Sngiestatic int 114272343Sngieaic_pccard_match(device_t dev) 115272343Sngie{ 116272343Sngie const struct pccard_product *pp; 117272343Sngie 118272343Sngie if ((pp = pccard_product_lookup(dev, aic_pccard_products, 119272343Sngie sizeof(aic_pccard_products[0]), NULL)) != NULL) { 120272343Sngie device_set_desc(dev, pp->pp_name); 121272343Sngie return 0; 122272343Sngie } 123272343Sngie return EIO; 124272343Sngie} 125272343Sngie 126272343Sngiestatic int 127272343Sngieaic_pccard_probe(device_t dev) 128272343Sngie{ 129272343Sngie struct aic_pccard_softc *sc = device_get_softc(dev); 130272343Sngie struct aic_softc *aic = &sc->sc_aic; 131272343Sngie 132272343Sngie if (aic_pccard_alloc_resources(dev)) 133272343Sngie return (ENXIO); 134272343Sngie if (aic_probe(aic)) { 135272343Sngie aic_pccard_release_resources(dev); 136272343Sngie return (ENXIO); 137272343Sngie } 138272343Sngie aic_pccard_release_resources(dev); 139272343Sngie 140272343Sngie device_set_desc(dev, "Adaptec 6260/6360 SCSI controller"); 141272343Sngie return (0); 142272343Sngie} 143272343Sngie 144272343Sngiestatic int 145272343Sngieaic_pccard_attach(device_t dev) 146272343Sngie{ 147272343Sngie struct aic_pccard_softc *sc = device_get_softc(dev); 148272343Sngie struct aic_softc *aic = &sc->sc_aic; 149272343Sngie int error; 150272343Sngie 151272343Sngie error = aic_pccard_alloc_resources(dev); 152272343Sngie if (error) { 153272343Sngie device_printf(dev, "resource allocation failed\n"); 154272343Sngie return (error); 155272343Sngie } 156272343Sngie 157272343Sngie error = aic_attach(aic); 158272343Sngie if (error) { 159272343Sngie device_printf(dev, "attach failed\n"); 160272343Sngie aic_pccard_release_resources(dev); 161272343Sngie return (error); 162272343Sngie } 163272343Sngie 164272343Sngie error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_CAM|INTR_ENTROPY, 165272343Sngie aic_intr, aic, &sc->sc_ih); 166272343Sngie if (error) { 167272343Sngie device_printf(dev, "failed to register interrupt handler\n"); 168272343Sngie aic_pccard_release_resources(dev); 169272343Sngie return (error); 170272343Sngie } 171272343Sngie return (0); 172272343Sngie} 173272343Sngie 174272343Sngiestatic int 175272343Sngieaic_pccard_detach(device_t dev) 176272343Sngie{ 177272343Sngie struct aic_pccard_softc *sc = device_get_softc(dev); 178272343Sngie struct aic_softc *aic = &sc->sc_aic; 179272343Sngie int error; 180272343Sngie 181272343Sngie error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih); 182272343Sngie if (error) { 183272343Sngie device_printf(dev, "failed to unregister interrupt handler\n"); 184272343Sngie } 185272343Sngie 186272343Sngie error = aic_detach(aic); 187272343Sngie if (error) { 188272343Sngie device_printf(dev, "detach failed\n"); 189272343Sngie return (error); 190272343Sngie } 191272343Sngie 192272343Sngie aic_pccard_release_resources(dev); 193272343Sngie return (0); 194272343Sngie} 195272343Sngie 196272343Sngiestatic device_method_t aic_pccard_methods[] = { 197272343Sngie /* Device interface */ 198272343Sngie DEVMETHOD(device_probe, pccard_compat_probe), 199272343Sngie DEVMETHOD(device_attach, pccard_compat_attach), 200272343Sngie DEVMETHOD(device_detach, aic_pccard_detach), 201272343Sngie 202272343Sngie /* Card interface */ 203272343Sngie DEVMETHOD(card_compat_match, aic_pccard_match), 204272343Sngie DEVMETHOD(card_compat_probe, aic_pccard_probe), 205272343Sngie DEVMETHOD(card_compat_attach, aic_pccard_attach), 206272343Sngie 207272343Sngie { 0, 0 } 208272343Sngie}; 209272343Sngie 210272343Sngiestatic driver_t aic_pccard_driver = { 211272343Sngie "aic", 212272343Sngie aic_pccard_methods, sizeof(struct aic_pccard_softc), 213272343Sngie}; 214272343Sngie 215272343Sngieextern devclass_t aic_devclass; 216272343Sngie 217272343SngieMODULE_DEPEND(aic, cam, 1,1,1); 218272343SngieDRIVER_MODULE(aic, pccard, aic_pccard_driver, aic_devclass, 0, 0); 219272343Sngie