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