xref: /NextBSD/sys/dev/mcd/mcd_isa.c (revision 4bf303e5af1834cdd3092175eeca7676420229c4)
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/lock.h>
18 #include <sys/mutex.h>
19 
20 #include <machine/bus.h>
21 #include <machine/resource.h>
22 #include <sys/rman.h>
23 
24 #include <isa/isavar.h>
25 
26 #include <dev/mcd/mcdreg.h>
27 #include <dev/mcd/mcdvar.h>
28 
29 static int	mcd_isa_probe	(device_t);
30 static int	mcd_isa_attach	(device_t);
31 static int	mcd_isa_detach	(device_t);
32 
33 static int	mcd_alloc_resources	(device_t);
34 static void	mcd_release_resources	(device_t);
35 
36 static int
mcd_isa_probe(device_t dev)37 mcd_isa_probe (device_t dev)
38 {
39 	struct mcd_softc *	sc;
40 	int			error;
41 
42 	/* No pnp support */
43 	if (isa_get_vendorid(dev))
44 		return (ENXIO);
45 
46 	/* IO port must be configured. */
47 	if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0)
48 		return (ENXIO);
49 
50 	sc = device_get_softc(dev);
51 	sc->dev = dev;
52 	sc->port_rid = 0;
53 	sc->port_type = SYS_RES_IOPORT;
54 	error = mcd_alloc_resources(dev);
55 	if (error)
56 		goto fail;
57 
58 	error = mcd_probe(sc);
59 	if (error) {
60 		device_printf(dev, "Probe failed.\n");
61 		goto fail;
62 	}
63 
64 	device_set_desc(dev, sc->data.name);
65 
66 fail:
67 	mcd_release_resources(dev);
68 	return (error);
69 }
70 
71 static int
mcd_isa_attach(device_t dev)72 mcd_isa_attach (device_t dev)
73 {
74 	struct mcd_softc *	sc;
75 	int			error;
76 
77 	sc = device_get_softc(dev);
78 	error = 0;
79 
80 	sc->dev = dev;
81 	sc->port_rid = 0;
82 	sc->port_type = SYS_RES_IOPORT;
83 	error = mcd_alloc_resources(dev);
84 	if (error)
85 		goto fail;
86 
87 	error = mcd_probe(sc);
88 	if (error) {
89 		device_printf(dev, "Re-Probe failed.\n");
90 		goto fail;
91 	}
92 
93 	error = mcd_attach(sc);
94 	if (error) {
95 		device_printf(dev, "Attach failed.\n");
96 		goto fail;
97 	}
98 
99 	return (0);
100 fail:
101 	mcd_release_resources(dev);
102 	return (error);
103 }
104 
105 static int
mcd_isa_detach(device_t dev)106 mcd_isa_detach (device_t dev)
107 {
108 	struct mcd_softc *	sc;
109 	int			error;
110 
111 	sc = device_get_softc(dev);
112 	error = 0;
113 
114 	destroy_dev(sc->mcd_dev_t);
115 
116 	mcd_release_resources(dev);
117 
118 	return (error);
119 }
120 
121 static int
mcd_alloc_resources(device_t dev)122 mcd_alloc_resources (device_t dev)
123 {
124 	struct mcd_softc *	sc;
125 	int			error;
126 
127 	sc = device_get_softc(dev);
128 	error = 0;
129 	mtx_init(&sc->mtx, "mcd", NULL, MTX_DEF);
130 
131 	if (sc->port_type) {
132 		sc->port = bus_alloc_resource_any(dev, sc->port_type,
133 				&sc->port_rid, RF_ACTIVE);
134 		if (sc->port == NULL) {
135 			device_printf(dev, "Unable to allocate PORT resource.\n");
136 			error = ENOMEM;
137 			goto bad;
138 		}
139 	}
140 
141 	if (sc->irq_type) {
142 		sc->irq = bus_alloc_resource_any(dev, sc->irq_type,
143 				&sc->irq_rid, RF_ACTIVE);
144 		if (sc->irq == NULL) {
145 			device_printf(dev, "Unable to allocate IRQ resource.\n");
146 			error = ENOMEM;
147 			goto bad;
148 		}
149 	}
150 
151 	if (sc->drq_type) {
152 		sc->drq = bus_alloc_resource_any(dev, sc->drq_type,
153 				&sc->drq_rid, RF_ACTIVE);
154 		if (sc->drq == NULL) {
155 			device_printf(dev, "Unable to allocate DRQ resource.\n");
156 			error = ENOMEM;
157 			goto bad;
158 		}
159 	}
160 
161 bad:
162 	return (error);
163 }
164 
165 static void
mcd_release_resources(device_t dev)166 mcd_release_resources (device_t dev)
167 {
168 	struct mcd_softc *	sc;
169 
170 	sc = device_get_softc(dev);
171 
172 	if (sc->irq_ih)
173 		bus_teardown_intr(dev, sc->irq, sc->irq_ih);
174 	if (sc->port)
175 		bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port);
176 	if (sc->irq)
177 		bus_release_resource(dev, sc->irq_type, sc->irq_rid, sc->irq);
178 	if (sc->drq)
179 		bus_release_resource(dev, sc->drq_type, sc->drq_rid, sc->drq);
180 
181 	mtx_destroy(&sc->mtx);
182 
183 	return;
184 }
185 
186 static device_method_t mcd_isa_methods[] = {
187 	DEVMETHOD(device_probe,         mcd_isa_probe),
188 	DEVMETHOD(device_attach,        mcd_isa_attach),
189 	DEVMETHOD(device_detach,        mcd_isa_detach),
190 
191 	{ 0, 0 }
192 };
193 
194 static driver_t mcd_isa_driver = {
195 	"mcd",
196 	mcd_isa_methods,
197 	sizeof(struct mcd_softc)
198 };
199 
200 static devclass_t	mcd_devclass;
201 
202 DRIVER_MODULE(mcd, isa, mcd_isa_driver, mcd_devclass, NULL, 0);
203