1106449Smdodd/*
2106449Smdodd */
3106449Smdodd
4119419Sobrien#include <sys/cdefs.h>
5119419Sobrien__FBSDID("$FreeBSD$");
6119419Sobrien
7106449Smdodd#include <sys/param.h>
8106449Smdodd#include <sys/systm.h>
9106449Smdodd#include <sys/kernel.h>
10106449Smdodd#include <sys/module.h>
11106449Smdodd#include <sys/conf.h>
12106449Smdodd#include <sys/fcntl.h>
13106449Smdodd#include <sys/bio.h>
14106449Smdodd#include <sys/cdio.h>
15106449Smdodd#include <sys/bus.h>
16106449Smdodd
17106449Smdodd#include <sys/mutex.h>
18106449Smdodd
19106449Smdodd#include <machine/bus.h>
20106449Smdodd#include <machine/resource.h>
21106449Smdodd#include <sys/rman.h>
22106449Smdodd
23106449Smdodd#include <isa/isavar.h>
24106449Smdodd
25106449Smdodd#include <dev/scd/scdreg.h>
26106449Smdodd#include <dev/scd/scdvar.h>
27106449Smdodd
28106449Smdoddstatic int	scd_isa_probe	(device_t);
29106449Smdoddstatic int	scd_isa_attach	(device_t);
30106449Smdoddstatic int	scd_isa_detach	(device_t);
31106449Smdodd
32106449Smdoddstatic int	scd_alloc_resources	(device_t);
33106449Smdoddstatic void	scd_release_resources	(device_t);
34106449Smdodd
35106449Smdoddstatic int
36106449Smdoddscd_isa_probe (device_t dev)
37106449Smdodd{
38106449Smdodd	struct scd_softc *	sc;
39106449Smdodd	int			error;
40106449Smdodd
41106449Smdodd	/* No pnp support */
42106449Smdodd	if (isa_get_vendorid(dev))
43106449Smdodd		return (ENXIO);
44106449Smdodd
45106449Smdodd	/* IO port must be configured. */
46106449Smdodd	if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0)
47106449Smdodd		return (ENXIO);
48106449Smdodd
49106449Smdodd	sc = device_get_softc(dev);
50106449Smdodd	sc->dev = dev;
51106449Smdodd	sc->port_rid = 0;
52106449Smdodd	sc->port_type = SYS_RES_IOPORT;
53106449Smdodd	error = scd_alloc_resources(dev);
54106449Smdodd	if (error)
55106449Smdodd		goto fail;
56106449Smdodd
57106449Smdodd	error = scd_probe(sc);
58106449Smdodd	if (error) {
59106449Smdodd		device_printf(dev, "Probe failed.\n");
60106449Smdodd		goto fail;
61106449Smdodd	}
62106449Smdodd
63106449Smdodd	device_set_desc(dev, sc->data.name);
64106449Smdodd
65106449Smdoddfail:
66106449Smdodd	scd_release_resources(dev);
67106449Smdodd	return (error);
68106449Smdodd}
69106449Smdodd
70106449Smdoddstatic int
71106449Smdoddscd_isa_attach (device_t dev)
72106449Smdodd{
73106449Smdodd	struct scd_softc *	sc;
74106449Smdodd	int			error;
75106449Smdodd
76106449Smdodd	sc = device_get_softc(dev);
77106449Smdodd	error = 0;
78106449Smdodd
79106449Smdodd	sc->dev = dev;
80106449Smdodd	sc->port_rid = 0;
81106449Smdodd	sc->port_type = SYS_RES_IOPORT;
82106449Smdodd	error = scd_alloc_resources(dev);
83106449Smdodd	if (error)
84106449Smdodd		goto fail;
85106449Smdodd
86106449Smdodd	error = scd_probe(sc);
87106449Smdodd	if (error) {
88106449Smdodd		device_printf(dev, "Re-Probe failed.\n");
89106449Smdodd		goto fail;
90106449Smdodd	}
91106449Smdodd
92106449Smdodd	error = scd_attach(sc);
93106449Smdodd	if (error) {
94106449Smdodd		device_printf(dev, "Attach failed.\n");
95106449Smdodd		goto fail;
96106449Smdodd	}
97106449Smdodd
98106449Smdodd	return (0);
99106449Smdoddfail:
100106449Smdodd	scd_release_resources(dev);
101106449Smdodd	return (error);
102106449Smdodd}
103106449Smdodd
104106449Smdoddstatic int
105106449Smdoddscd_isa_detach (device_t dev)
106106449Smdodd{
107106449Smdodd	struct scd_softc *	sc;
108106449Smdodd	int			error;
109106449Smdodd
110106449Smdodd	sc = device_get_softc(dev);
111106449Smdodd	error = 0;
112106449Smdodd
113106449Smdodd	destroy_dev(sc->scd_dev_t);
114106449Smdodd
115106449Smdodd	scd_release_resources(dev);
116106449Smdodd
117106449Smdodd	return (error);
118106449Smdodd}
119106449Smdodd
120106449Smdoddstatic int
121106449Smdoddscd_alloc_resources (device_t dev)
122106449Smdodd{
123106449Smdodd	struct scd_softc *	sc;
124106449Smdodd	int			error;
125106449Smdodd
126106449Smdodd	sc = device_get_softc(dev);
127106449Smdodd	error = 0;
128106449Smdodd
129106449Smdodd	if (sc->port_type) {
130127135Snjl		sc->port = bus_alloc_resource_any(dev, sc->port_type,
131127135Snjl				&sc->port_rid, RF_ACTIVE);
132106449Smdodd		if (sc->port == NULL) {
133106449Smdodd			device_printf(dev, "Unable to allocate PORT resource.\n");
134106449Smdodd			error = ENOMEM;
135106449Smdodd			goto bad;
136106449Smdodd		}
137106449Smdodd		sc->port_bst = rman_get_bustag(sc->port);
138106449Smdodd		sc->port_bsh = rman_get_bushandle(sc->port);
139106449Smdodd	}
140106449Smdodd
141106449Smdodd	mtx_init(&sc->mtx, device_get_nameunit(dev),
142106449Smdodd		"Interrupt lock", MTX_DEF | MTX_RECURSE);
143106449Smdodd
144106449Smdoddbad:
145106449Smdodd	return (error);
146106449Smdodd}
147106449Smdodd
148106449Smdoddvoid
149106449Smdoddscd_release_resources (device_t dev)
150106449Smdodd{
151106449Smdodd	struct scd_softc *	sc;
152106449Smdodd
153106449Smdodd	sc = device_get_softc(dev);
154106449Smdodd
155106449Smdodd	if (sc->port) {
156106449Smdodd		bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port);
157106449Smdodd		sc->port_bst = 0;
158106449Smdodd		sc->port_bsh = 0;
159106449Smdodd	}
160106449Smdodd
161106449Smdodd	if (mtx_initialized(&sc->mtx) != 0)
162106449Smdodd		mtx_destroy(&sc->mtx);
163106449Smdodd
164106449Smdodd	return;
165106449Smdodd}
166106449Smdodd
167106449Smdoddstatic device_method_t scd_isa_methods[] = {
168106449Smdodd	DEVMETHOD(device_probe,         scd_isa_probe),
169106449Smdodd	DEVMETHOD(device_attach,        scd_isa_attach),
170106449Smdodd	DEVMETHOD(device_detach,        scd_isa_detach),
171106449Smdodd
172106449Smdodd	{ 0, 0 }
173106449Smdodd};
174106449Smdodd
175106449Smdoddstatic driver_t scd_isa_driver = {
176106449Smdodd	"scd",
177106449Smdodd	scd_isa_methods,
178106449Smdodd	sizeof(struct scd_softc)
179106449Smdodd};
180106449Smdodd
181106449Smdoddstatic devclass_t	scd_devclass;
182106449Smdodd
183106449SmdoddDRIVER_MODULE(scd, isa, scd_isa_driver, scd_devclass, NULL, 0);
184