1104445Smdodd/*
2104445Smdodd */
3104445Smdodd
4119418Sobrien#include <sys/cdefs.h>
5119418Sobrien__FBSDID("$FreeBSD$");
6119418Sobrien
7104445Smdodd#include <sys/param.h>
8104445Smdodd#include <sys/systm.h>
9104445Smdodd#include <sys/kernel.h>
10104445Smdodd#include <sys/module.h>
11104445Smdodd#include <sys/conf.h>
12104445Smdodd#include <sys/fcntl.h>
13104445Smdodd#include <sys/bio.h>
14104445Smdodd#include <sys/cdio.h>
15104445Smdodd#include <sys/bus.h>
16104445Smdodd
17104547Sbde#include <sys/lock.h>
18104445Smdodd#include <sys/mutex.h>
19104445Smdodd
20104445Smdodd#include <machine/bus.h>
21104445Smdodd#include <machine/resource.h>
22104445Smdodd#include <sys/rman.h>
23104445Smdodd
24104445Smdodd#include <isa/isavar.h>
25104445Smdodd
26104445Smdodd#include <dev/mcd/mcdreg.h>
27104445Smdodd#include <dev/mcd/mcdvar.h>
28104445Smdodd
29104445Smdoddstatic int	mcd_isa_probe	(device_t);
30104445Smdoddstatic int	mcd_isa_attach	(device_t);
31104445Smdoddstatic int	mcd_isa_detach	(device_t);
32104445Smdodd
33104445Smdoddstatic int	mcd_alloc_resources	(device_t);
34104445Smdoddstatic void	mcd_release_resources	(device_t);
35104445Smdodd
36104445Smdoddstatic int
37104445Smdoddmcd_isa_probe (device_t dev)
38104445Smdodd{
39104445Smdodd	struct mcd_softc *	sc;
40104445Smdodd	int			error;
41104445Smdodd
42104445Smdodd	/* No pnp support */
43104445Smdodd	if (isa_get_vendorid(dev))
44104445Smdodd		return (ENXIO);
45104445Smdodd
46104445Smdodd	/* IO port must be configured. */
47104445Smdodd	if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0)
48104445Smdodd		return (ENXIO);
49104445Smdodd
50104445Smdodd	sc = device_get_softc(dev);
51104445Smdodd	sc->dev = dev;
52104445Smdodd	sc->port_rid = 0;
53104445Smdodd	sc->port_type = SYS_RES_IOPORT;
54104445Smdodd	error = mcd_alloc_resources(dev);
55104445Smdodd	if (error)
56104445Smdodd		goto fail;
57104445Smdodd
58104445Smdodd	error = mcd_probe(sc);
59104445Smdodd	if (error) {
60104445Smdodd		device_printf(dev, "Probe failed.\n");
61104445Smdodd		goto fail;
62104445Smdodd	}
63104445Smdodd
64104445Smdodd	device_set_desc(dev, sc->data.name);
65104445Smdodd
66104445Smdoddfail:
67104445Smdodd	mcd_release_resources(dev);
68104445Smdodd	return (error);
69104445Smdodd}
70104445Smdodd
71104445Smdoddstatic int
72104445Smdoddmcd_isa_attach (device_t dev)
73104445Smdodd{
74104445Smdodd	struct mcd_softc *	sc;
75104445Smdodd	int			error;
76104445Smdodd
77104445Smdodd	sc = device_get_softc(dev);
78104445Smdodd	error = 0;
79104445Smdodd
80104445Smdodd	sc->dev = dev;
81104445Smdodd	sc->port_rid = 0;
82104445Smdodd	sc->port_type = SYS_RES_IOPORT;
83104445Smdodd	error = mcd_alloc_resources(dev);
84104445Smdodd	if (error)
85104445Smdodd		goto fail;
86104445Smdodd
87104445Smdodd	error = mcd_probe(sc);
88104445Smdodd	if (error) {
89104445Smdodd		device_printf(dev, "Re-Probe failed.\n");
90104445Smdodd		goto fail;
91104445Smdodd	}
92104445Smdodd
93104445Smdodd	error = mcd_attach(sc);
94104445Smdodd	if (error) {
95104445Smdodd		device_printf(dev, "Attach failed.\n");
96104445Smdodd		goto fail;
97104445Smdodd	}
98104445Smdodd
99104445Smdodd	return (0);
100104445Smdoddfail:
101104445Smdodd	mcd_release_resources(dev);
102104445Smdodd	return (error);
103104445Smdodd}
104104445Smdodd
105104445Smdoddstatic int
106104445Smdoddmcd_isa_detach (device_t dev)
107104445Smdodd{
108104445Smdodd	struct mcd_softc *	sc;
109104445Smdodd	int			error;
110104445Smdodd
111104445Smdodd	sc = device_get_softc(dev);
112104445Smdodd	error = 0;
113104445Smdodd
114104545Smdodd	destroy_dev(sc->mcd_dev_t);
115104445Smdodd
116104445Smdodd	mcd_release_resources(dev);
117104445Smdodd
118104445Smdodd	return (error);
119104445Smdodd}
120104445Smdodd
121104445Smdoddstatic int
122104445Smdoddmcd_alloc_resources (device_t dev)
123104445Smdodd{
124104445Smdodd	struct mcd_softc *	sc;
125104445Smdodd	int			error;
126104445Smdodd
127104445Smdodd	sc = device_get_softc(dev);
128104445Smdodd	error = 0;
129104445Smdodd
130104445Smdodd	if (sc->port_type) {
131127135Snjl		sc->port = bus_alloc_resource_any(dev, sc->port_type,
132127135Snjl				&sc->port_rid, RF_ACTIVE);
133104445Smdodd		if (sc->port == NULL) {
134104445Smdodd			device_printf(dev, "Unable to allocate PORT resource.\n");
135104445Smdodd			error = ENOMEM;
136104445Smdodd			goto bad;
137104445Smdodd		}
138104445Smdodd		sc->port_bst = rman_get_bustag(sc->port);
139104445Smdodd		sc->port_bsh = rman_get_bushandle(sc->port);
140104445Smdodd	}
141104445Smdodd
142104445Smdodd	if (sc->irq_type) {
143127135Snjl		sc->irq = bus_alloc_resource_any(dev, sc->irq_type,
144127135Snjl				&sc->irq_rid, RF_ACTIVE);
145104445Smdodd		if (sc->irq == NULL) {
146104445Smdodd			device_printf(dev, "Unable to allocate IRQ resource.\n");
147104445Smdodd			error = ENOMEM;
148104445Smdodd			goto bad;
149104445Smdodd		}
150104445Smdodd	}
151104445Smdodd
152104445Smdodd	if (sc->drq_type) {
153127135Snjl		sc->drq = bus_alloc_resource_any(dev, sc->drq_type,
154127135Snjl				&sc->drq_rid, RF_ACTIVE);
155104445Smdodd		if (sc->drq == NULL) {
156104445Smdodd			device_printf(dev, "Unable to allocate DRQ resource.\n");
157104445Smdodd			error = ENOMEM;
158104445Smdodd			goto bad;
159104445Smdodd		}
160104445Smdodd	}
161104445Smdodd
162104445Smdodd	mtx_init(&sc->mtx, device_get_nameunit(dev),
163104445Smdodd		"Interrupt lock", MTX_DEF | MTX_RECURSE);
164104445Smdodd
165104445Smdoddbad:
166104445Smdodd	return (error);
167104445Smdodd}
168104445Smdodd
169105215Sphkstatic void
170104445Smdoddmcd_release_resources (device_t dev)
171104445Smdodd{
172104445Smdodd	struct mcd_softc *	sc;
173104445Smdodd
174104445Smdodd	sc = device_get_softc(dev);
175104445Smdodd
176104445Smdodd	if (sc->irq_ih)
177104445Smdodd		bus_teardown_intr(dev, sc->irq, sc->irq_ih);
178104445Smdodd	if (sc->port) {
179104445Smdodd		bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port);
180104445Smdodd		sc->port_bst = 0;
181104445Smdodd		sc->port_bsh = 0;
182104445Smdodd	}
183104445Smdodd	if (sc->irq)
184104445Smdodd		bus_release_resource(dev, sc->irq_type, sc->irq_rid, sc->irq);
185104445Smdodd	if (sc->drq)
186104445Smdodd		bus_release_resource(dev, sc->drq_type, sc->drq_rid, sc->drq);
187104445Smdodd
188104445Smdodd	if (mtx_initialized(&sc->mtx) != 0)
189104445Smdodd		mtx_destroy(&sc->mtx);
190104445Smdodd
191104445Smdodd	return;
192104445Smdodd}
193104445Smdodd
194104445Smdoddstatic device_method_t mcd_isa_methods[] = {
195104445Smdodd	DEVMETHOD(device_probe,         mcd_isa_probe),
196104445Smdodd	DEVMETHOD(device_attach,        mcd_isa_attach),
197104445Smdodd	DEVMETHOD(device_detach,        mcd_isa_detach),
198104445Smdodd
199104445Smdodd	{ 0, 0 }
200104445Smdodd};
201104445Smdodd
202104445Smdoddstatic driver_t mcd_isa_driver = {
203104445Smdodd	"mcd",
204104445Smdodd	mcd_isa_methods,
205104445Smdodd	sizeof(struct mcd_softc)
206104445Smdodd};
207104445Smdodd
208104445Smdoddstatic devclass_t	mcd_devclass;
209104445Smdodd
210104445SmdoddDRIVER_MODULE(mcd, isa, mcd_isa_driver, mcd_devclass, NULL, 0);
211