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