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