aic_pccard.c revision 113315
155997Simp/*- 255997Simp * Copyright (c) 1999 Luoqi Chen. 355997Simp * All rights reserved. 455997Simp * 555997Simp * Redistribution and use in source and binary forms, with or without 655997Simp * modification, are permitted provided that the following conditions 755997Simp * are met: 855997Simp * 1. Redistributions of source code must retain the above copyright 955997Simp * notice, this list of conditions and the following disclaimer. 1055997Simp * 2. Redistributions in binary form must reproduce the above copyright 1155997Simp * notice, this list of conditions and the following disclaimer in the 1255997Simp * documentation and/or other materials provided with the distribution. 1355997Simp * 1455997Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1555997Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1655997Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1755997Simp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1855997Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1955997Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2055997Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2155997Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2255997Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2355997Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2455997Simp * SUCH DAMAGE. 2555997Simp * 2655997Simp * $FreeBSD: head/sys/dev/aic/aic_pccard.c 113315 2003-04-10 04:36:02Z imp $ 2755997Simp */ 2855997Simp 2955997Simp#include <sys/param.h> 3055997Simp#include <sys/kernel.h> 3155997Simp#include <sys/module.h> 3255997Simp#include <sys/bus.h> 3355997Simp 3455997Simp#include <machine/bus_pio.h> 3555997Simp#include <machine/bus.h> 3655997Simp#include <machine/resource.h> 3755997Simp#include <sys/rman.h> 3855997Simp 3955997Simp#include <dev/aic/aicvar.h> 4070782Simp#include <dev/pccard/pccardvar.h> 4170782Simp#include <dev/pccard/pccarddevs.h> 4255997Simp 4370782Simp#include "card_if.h" 4470782Simp 4555997Simpstruct aic_pccard_softc { 4655997Simp struct aic_softc sc_aic; 4755997Simp struct resource *sc_port; 4855997Simp struct resource *sc_irq; 4955997Simp void *sc_ih; 5055997Simp}; 5155997Simp 5270782Simpstatic int aic_pccard_alloc_resources(device_t); 5370782Simpstatic void aic_pccard_release_resources(device_t); 5470782Simpstatic int aic_pccard_match(device_t); 5570782Simpstatic int aic_pccard_probe(device_t); 5670782Simpstatic int aic_pccard_attach(device_t); 5755997Simp 5870782Simpconst struct pccard_product aic_pccard_products[] = { 5986394Simp PCMCIA_CARD(ADAPTEC, APA1460, 0), 6086394Simp PCMCIA_CARD(ADAPTEC, APA1460A, 0), 6186394Simp PCMCIA_CARD(NEWMEDIA, BUSTOASTER, 0), 62106893Simp PCMCIA_CARD(NEWMEDIA, BUSTOASTER2, 0), 63106893Simp PCMCIA_CARD(NEWMEDIA, BUSTOASTER3, 0), 6470782Simp { NULL } 6570782Simp}; 6670782Simp 6755997Simp#define AIC_PCCARD_PORTSIZE 0x20 6855997Simp 6955997Simpstatic int 7055997Simpaic_pccard_alloc_resources(device_t dev) 7155997Simp{ 7255997Simp struct aic_pccard_softc *sc = device_get_softc(dev); 7355997Simp int rid; 7455997Simp 7555997Simp sc->sc_port = sc->sc_irq = 0; 7655997Simp 7755997Simp rid = 0; 7855997Simp sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 7955997Simp 0ul, ~0ul, AIC_PCCARD_PORTSIZE, RF_ACTIVE); 8055997Simp if (!sc->sc_port) 8155997Simp return (ENOMEM); 8255997Simp 8355997Simp rid = 0; 8455997Simp sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 8555997Simp 0ul, ~0ul, 1, RF_ACTIVE); 8655997Simp if (!sc->sc_irq) { 8755997Simp aic_pccard_release_resources(dev); 8855997Simp return (ENOMEM); 8955997Simp } 9055997Simp 9155997Simp sc->sc_aic.unit = device_get_unit(dev); 9255997Simp sc->sc_aic.tag = rman_get_bustag(sc->sc_port); 9355997Simp sc->sc_aic.bsh = rman_get_bushandle(sc->sc_port); 9455997Simp return (0); 9555997Simp} 9655997Simp 9755997Simpstatic void 9855997Simpaic_pccard_release_resources(device_t dev) 9955997Simp{ 10055997Simp struct aic_pccard_softc *sc = device_get_softc(dev); 10155997Simp 10255997Simp if (sc->sc_port) 10355997Simp bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port); 10455997Simp if (sc->sc_irq) 10555997Simp bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq); 10655997Simp sc->sc_port = sc->sc_irq = 0; 10755997Simp} 10855997Simp 10955997Simpstatic int 11070782Simpaic_pccard_match(device_t dev) 11170782Simp{ 11270782Simp const struct pccard_product *pp; 11370782Simp 11470782Simp if ((pp = pccard_product_lookup(dev, aic_pccard_products, 11570782Simp sizeof(aic_pccard_products[0]), NULL)) != NULL) { 116113315Simp if (pp->pp_name != NULL) 117113315Simp device_set_desc(dev, pp->pp_name); 11870782Simp return 0; 11970782Simp } 12070782Simp return EIO; 12170782Simp} 12270782Simp 12370782Simpstatic int 12455997Simpaic_pccard_probe(device_t dev) 12555997Simp{ 12655997Simp struct aic_pccard_softc *sc = device_get_softc(dev); 12755997Simp struct aic_softc *aic = &sc->sc_aic; 12855997Simp 12955997Simp if (aic_pccard_alloc_resources(dev)) 13055997Simp return (ENXIO); 13155997Simp if (aic_probe(aic)) { 13255997Simp aic_pccard_release_resources(dev); 13355997Simp return (ENXIO); 13455997Simp } 13555997Simp aic_pccard_release_resources(dev); 13655997Simp 13755997Simp device_set_desc(dev, "Adaptec 6260/6360 SCSI controller"); 13855997Simp return (0); 13955997Simp} 14055997Simp 14155997Simpstatic int 14255997Simpaic_pccard_attach(device_t dev) 14355997Simp{ 14455997Simp struct aic_pccard_softc *sc = device_get_softc(dev); 14555997Simp struct aic_softc *aic = &sc->sc_aic; 14655997Simp int error; 14755997Simp 14855997Simp error = aic_pccard_alloc_resources(dev); 14955997Simp if (error) { 15055997Simp device_printf(dev, "resource allocation failed\n"); 15155997Simp return (error); 15255997Simp } 15355997Simp 15455997Simp error = aic_attach(aic); 15555997Simp if (error) { 15655997Simp device_printf(dev, "attach failed\n"); 15755997Simp aic_pccard_release_resources(dev); 15855997Simp return (error); 15955997Simp } 16055997Simp 16173280Smarkm error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_CAM|INTR_ENTROPY, 16273280Smarkm aic_intr, aic, &sc->sc_ih); 16355997Simp if (error) { 16455997Simp device_printf(dev, "failed to register interrupt handler\n"); 16555997Simp aic_pccard_release_resources(dev); 16655997Simp return (error); 16755997Simp } 16855997Simp return (0); 16955997Simp} 17055997Simp 17155997Simpstatic int 17255997Simpaic_pccard_detach(device_t dev) 17355997Simp{ 17455997Simp struct aic_pccard_softc *sc = device_get_softc(dev); 17555997Simp struct aic_softc *aic = &sc->sc_aic; 17655997Simp int error; 17755997Simp 17855997Simp error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih); 17955997Simp if (error) { 18055997Simp device_printf(dev, "failed to unregister interrupt handler\n"); 18155997Simp } 18255997Simp 18355997Simp error = aic_detach(aic); 18455997Simp if (error) { 18555997Simp device_printf(dev, "detach failed\n"); 18655997Simp return (error); 18755997Simp } 18855997Simp 18955997Simp aic_pccard_release_resources(dev); 19055997Simp return (0); 19155997Simp} 19255997Simp 19355997Simpstatic device_method_t aic_pccard_methods[] = { 19455997Simp /* Device interface */ 19570782Simp DEVMETHOD(device_probe, pccard_compat_probe), 19670782Simp DEVMETHOD(device_attach, pccard_compat_attach), 19755997Simp DEVMETHOD(device_detach, aic_pccard_detach), 19870782Simp 19970782Simp /* Card interface */ 20070782Simp DEVMETHOD(card_compat_match, aic_pccard_match), 20170782Simp DEVMETHOD(card_compat_probe, aic_pccard_probe), 20270782Simp DEVMETHOD(card_compat_attach, aic_pccard_attach), 20370782Simp 20455997Simp { 0, 0 } 20555997Simp}; 20655997Simp 20755997Simpstatic driver_t aic_pccard_driver = { 20855997Simp "aic", 20955997Simp aic_pccard_methods, sizeof(struct aic_pccard_softc), 21055997Simp}; 21155997Simp 21255997Simpextern devclass_t aic_devclass; 21355997Simp 21469960SimpMODULE_DEPEND(aic, cam, 1,1,1); 21555997SimpDRIVER_MODULE(aic, pccard, aic_pccard_driver, aic_devclass, 0, 0); 216