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