scd_isa.c revision 113581
1/*
2 * $FreeBSD: head/sys/dev/scd/scd_isa.c 113581 2003-04-16 20:57:35Z phk $
3 */
4
5#include <sys/param.h>
6#include <sys/systm.h>
7#include <sys/kernel.h>
8#include <sys/module.h>
9#include <sys/conf.h>
10#include <sys/fcntl.h>
11#include <sys/bio.h>
12#include <sys/cdio.h>
13#include <sys/bus.h>
14
15#include <sys/mutex.h>
16
17#include <machine/bus_pio.h>
18#include <machine/bus.h>
19#include <machine/resource.h>
20#include <sys/rman.h>
21
22#include <isa/isavar.h>
23
24#include <dev/scd/scdreg.h>
25#include <dev/scd/scdvar.h>
26
27static int	scd_isa_probe	(device_t);
28static int	scd_isa_attach	(device_t);
29static int	scd_isa_detach	(device_t);
30
31static int	scd_alloc_resources	(device_t);
32static void	scd_release_resources	(device_t);
33
34static int
35scd_isa_probe (device_t dev)
36{
37	struct scd_softc *	sc;
38	int			error;
39
40	/* No pnp support */
41	if (isa_get_vendorid(dev))
42		return (ENXIO);
43
44	/* IO port must be configured. */
45	if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0)
46		return (ENXIO);
47
48	sc = device_get_softc(dev);
49	sc->dev = dev;
50	sc->port_rid = 0;
51	sc->port_type = SYS_RES_IOPORT;
52	error = scd_alloc_resources(dev);
53	if (error)
54		goto fail;
55
56	error = scd_probe(sc);
57	if (error) {
58		device_printf(dev, "Probe failed.\n");
59		goto fail;
60	}
61
62	device_set_desc(dev, sc->data.name);
63
64fail:
65	scd_release_resources(dev);
66	return (error);
67}
68
69static int
70scd_isa_attach (device_t dev)
71{
72	struct scd_softc *	sc;
73	int			error;
74
75	sc = device_get_softc(dev);
76	error = 0;
77
78	sc->dev = dev;
79	sc->port_rid = 0;
80	sc->port_type = SYS_RES_IOPORT;
81	error = scd_alloc_resources(dev);
82	if (error)
83		goto fail;
84
85	error = scd_probe(sc);
86	if (error) {
87		device_printf(dev, "Re-Probe failed.\n");
88		goto fail;
89	}
90
91	error = scd_attach(sc);
92	if (error) {
93		device_printf(dev, "Attach failed.\n");
94		goto fail;
95	}
96
97	return (0);
98fail:
99	scd_release_resources(dev);
100	return (error);
101}
102
103static int
104scd_isa_detach (device_t dev)
105{
106	struct scd_softc *	sc;
107	int			error;
108
109	sc = device_get_softc(dev);
110	error = 0;
111
112	destroy_dev(sc->scd_dev_t);
113
114	scd_release_resources(dev);
115
116	return (error);
117}
118
119static int
120scd_alloc_resources (device_t dev)
121{
122	struct scd_softc *	sc;
123	int			error;
124
125	sc = device_get_softc(dev);
126	error = 0;
127
128	if (sc->port_type) {
129		sc->port = bus_alloc_resource(dev, sc->port_type, &sc->port_rid,
130				0, ~0, 1, RF_ACTIVE);
131		if (sc->port == NULL) {
132			device_printf(dev, "Unable to allocate PORT resource.\n");
133			error = ENOMEM;
134			goto bad;
135		}
136		sc->port_bst = rman_get_bustag(sc->port);
137		sc->port_bsh = rman_get_bushandle(sc->port);
138	}
139
140	mtx_init(&sc->mtx, device_get_nameunit(dev),
141		"Interrupt lock", MTX_DEF | MTX_RECURSE);
142
143bad:
144	return (error);
145}
146
147void
148scd_release_resources (device_t dev)
149{
150	struct scd_softc *	sc;
151
152	sc = device_get_softc(dev);
153
154	if (sc->port) {
155		bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port);
156		sc->port_bst = 0;
157		sc->port_bsh = 0;
158	}
159
160	if (mtx_initialized(&sc->mtx) != 0)
161		mtx_destroy(&sc->mtx);
162
163	return;
164}
165
166static device_method_t scd_isa_methods[] = {
167	DEVMETHOD(device_probe,         scd_isa_probe),
168	DEVMETHOD(device_attach,        scd_isa_attach),
169	DEVMETHOD(device_detach,        scd_isa_detach),
170
171	{ 0, 0 }
172};
173
174static driver_t scd_isa_driver = {
175	"scd",
176	scd_isa_methods,
177	sizeof(struct scd_softc)
178};
179
180static devclass_t	scd_devclass;
181
182DRIVER_MODULE(scd, isa, scd_isa_driver, scd_devclass, NULL, 0);
183