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 27119418Sobrien#include <sys/cdefs.h> 28119418Sobrien__FBSDID("$FreeBSD$"); 29119418Sobrien 3055997Simp#include <sys/param.h> 31241591Sjhb#include <sys/callout.h> 3255997Simp#include <sys/kernel.h> 33241591Sjhb#include <sys/lock.h> 3455997Simp#include <sys/module.h> 35241591Sjhb#include <sys/mutex.h> 3655997Simp#include <sys/bus.h> 3755997Simp 3855997Simp#include <machine/bus.h> 3955997Simp#include <machine/resource.h> 4055997Simp#include <sys/rman.h> 4155997Simp 4255997Simp#include <dev/aic/aicvar.h> 4370782Simp#include <dev/pccard/pccardvar.h> 4455997Simp 4570782Simp#include "card_if.h" 46129764Simp#include "pccarddevs.h" 4770782Simp 4855997Simpstruct aic_pccard_softc { 4955997Simp struct aic_softc sc_aic; 5055997Simp struct resource *sc_port; 5155997Simp struct resource *sc_irq; 5255997Simp void *sc_ih; 5355997Simp}; 5455997Simp 5570782Simpstatic int aic_pccard_alloc_resources(device_t); 5670782Simpstatic void aic_pccard_release_resources(device_t); 5770782Simpstatic int aic_pccard_probe(device_t); 5870782Simpstatic int aic_pccard_attach(device_t); 5955997Simp 60162979Simpstatic const struct pccard_product aic_pccard_products[] = { 61147580Simp PCMCIA_CARD(ADAPTEC, APA1460), 62147580Simp PCMCIA_CARD(ADAPTEC, APA1460A), 63147580Simp PCMCIA_CARD(NEWMEDIA, BUSTOASTER), 64147580Simp PCMCIA_CARD(NEWMEDIA, BUSTOASTER2), 65147580Simp PCMCIA_CARD(NEWMEDIA, BUSTOASTER3), 6670782Simp { NULL } 6770782Simp}; 6870782Simp 6955997Simp#define AIC_PCCARD_PORTSIZE 0x20 7055997Simp 7155997Simpstatic int 7255997Simpaic_pccard_alloc_resources(device_t dev) 7355997Simp{ 7455997Simp struct aic_pccard_softc *sc = device_get_softc(dev); 7555997Simp int rid; 7655997Simp 77241591Sjhb sc->sc_port = sc->sc_irq = NULL; 7855997Simp 7955997Simp rid = 0; 8055997Simp sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 8155997Simp 0ul, ~0ul, AIC_PCCARD_PORTSIZE, RF_ACTIVE); 8255997Simp if (!sc->sc_port) 8355997Simp return (ENOMEM); 8455997Simp 8555997Simp rid = 0; 86127135Snjl sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); 8755997Simp if (!sc->sc_irq) { 8855997Simp aic_pccard_release_resources(dev); 8955997Simp return (ENOMEM); 9055997Simp } 9155997Simp 92170872Sscottl sc->sc_aic.dev = dev; 93241591Sjhb sc->sc_aic.res = sc->sc_port; 94241591Sjhb mtx_init(&sc->sc_aic.lock, "aic", NULL, MTX_DEF); 9555997Simp return (0); 9655997Simp} 9755997Simp 9855997Simpstatic void 9955997Simpaic_pccard_release_resources(device_t dev) 10055997Simp{ 10155997Simp struct aic_pccard_softc *sc = device_get_softc(dev); 10255997Simp 10355997Simp if (sc->sc_port) 10455997Simp bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port); 10555997Simp if (sc->sc_irq) 10655997Simp bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq); 107241591Sjhb sc->sc_port = sc->sc_irq = NULL; 108241591Sjhb mtx_destroy(&sc->sc_aic.lock); 10955997Simp} 11055997Simp 11155997Simpstatic int 112150392Simpaic_pccard_probe(device_t dev) 11370782Simp{ 11470782Simp const struct pccard_product *pp; 11570782Simp 11670782Simp if ((pp = pccard_product_lookup(dev, aic_pccard_products, 11770782Simp sizeof(aic_pccard_products[0]), NULL)) != NULL) { 118113315Simp if (pp->pp_name != NULL) 119113315Simp device_set_desc(dev, pp->pp_name); 120241591Sjhb else 121241591Sjhb device_set_desc(dev, 122241591Sjhb "Adaptec 6260/6360 SCSI controller"); 123241591Sjhb return (BUS_PROBE_DEFAULT); 12470782Simp } 125241591Sjhb return (ENXIO); 12670782Simp} 12770782Simp 12870782Simpstatic int 129150392Simpaic_pccard_attach(device_t dev) 13055997Simp{ 13155997Simp struct aic_pccard_softc *sc = device_get_softc(dev); 13255997Simp struct aic_softc *aic = &sc->sc_aic; 133150392Simp int error; 13455997Simp 13555997Simp if (aic_pccard_alloc_resources(dev)) 13655997Simp return (ENXIO); 13755997Simp if (aic_probe(aic)) { 13855997Simp aic_pccard_release_resources(dev); 13955997Simp return (ENXIO); 14055997Simp } 14155997Simp 14255997Simp error = aic_attach(aic); 14355997Simp if (error) { 14455997Simp device_printf(dev, "attach failed\n"); 14555997Simp aic_pccard_release_resources(dev); 14655997Simp return (error); 14755997Simp } 14855997Simp 149241591Sjhb error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_CAM | INTR_ENTROPY | 150241591Sjhb INTR_MPSAFE, NULL, aic_intr, aic, &sc->sc_ih); 15155997Simp if (error) { 15255997Simp device_printf(dev, "failed to register interrupt handler\n"); 15355997Simp aic_pccard_release_resources(dev); 15455997Simp return (error); 15555997Simp } 15655997Simp return (0); 15755997Simp} 15855997Simp 15955997Simpstatic int 16055997Simpaic_pccard_detach(device_t dev) 16155997Simp{ 16255997Simp struct aic_pccard_softc *sc = device_get_softc(dev); 16355997Simp struct aic_softc *aic = &sc->sc_aic; 16455997Simp int error; 16555997Simp 16655997Simp error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_ih); 16755997Simp if (error) { 16855997Simp device_printf(dev, "failed to unregister interrupt handler\n"); 16955997Simp } 17055997Simp 17155997Simp error = aic_detach(aic); 17255997Simp if (error) { 17355997Simp device_printf(dev, "detach failed\n"); 17455997Simp return (error); 17555997Simp } 17655997Simp 17755997Simp aic_pccard_release_resources(dev); 17855997Simp return (0); 17955997Simp} 18055997Simp 18155997Simpstatic device_method_t aic_pccard_methods[] = { 18255997Simp /* Device interface */ 183150392Simp DEVMETHOD(device_probe, aic_pccard_probe), 184150392Simp DEVMETHOD(device_attach, aic_pccard_attach), 18555997Simp DEVMETHOD(device_detach, aic_pccard_detach), 18670782Simp 18755997Simp { 0, 0 } 18855997Simp}; 18955997Simp 19055997Simpstatic driver_t aic_pccard_driver = { 19155997Simp "aic", 19255997Simp aic_pccard_methods, sizeof(struct aic_pccard_softc), 19355997Simp}; 19455997Simp 19555997Simpextern devclass_t aic_devclass; 19655997Simp 19769960SimpMODULE_DEPEND(aic, cam, 1,1,1); 19855997SimpDRIVER_MODULE(aic, pccard, aic_pccard_driver, aic_devclass, 0, 0); 199