]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/mcd/mcd_isa.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / mcd / mcd_isa.c
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
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
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
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
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
130         if (sc->port_type) {
131                 sc->port = bus_alloc_resource_any(dev, sc->port_type,
132                                 &sc->port_rid, RF_ACTIVE);
133                 if (sc->port == NULL) {
134                         device_printf(dev, "Unable to allocate PORT resource.\n");
135                         error = ENOMEM;
136                         goto bad;
137                 }
138                 sc->port_bst = rman_get_bustag(sc->port);
139                 sc->port_bsh = rman_get_bushandle(sc->port);
140         }
141
142         if (sc->irq_type) {
143                 sc->irq = bus_alloc_resource_any(dev, sc->irq_type,
144                                 &sc->irq_rid, RF_ACTIVE);
145                 if (sc->irq == NULL) {
146                         device_printf(dev, "Unable to allocate IRQ resource.\n");
147                         error = ENOMEM;
148                         goto bad;
149                 }
150         }
151
152         if (sc->drq_type) {
153                 sc->drq = bus_alloc_resource_any(dev, sc->drq_type,
154                                 &sc->drq_rid, RF_ACTIVE);
155                 if (sc->drq == NULL) {
156                         device_printf(dev, "Unable to allocate DRQ resource.\n");
157                         error = ENOMEM;
158                         goto bad;
159                 }
160         }
161
162         mtx_init(&sc->mtx, device_get_nameunit(dev),
163                 "Interrupt lock", MTX_DEF | MTX_RECURSE);
164
165 bad:
166         return (error);
167 }
168
169 static void
170 mcd_release_resources (device_t dev)
171 {
172         struct mcd_softc *      sc;
173
174         sc = device_get_softc(dev);
175
176         if (sc->irq_ih)
177                 bus_teardown_intr(dev, sc->irq, sc->irq_ih);
178         if (sc->port) {
179                 bus_release_resource(dev, sc->port_type, sc->port_rid, sc->port);
180                 sc->port_bst = 0;
181                 sc->port_bsh = 0;
182         }
183         if (sc->irq)
184                 bus_release_resource(dev, sc->irq_type, sc->irq_rid, sc->irq);
185         if (sc->drq)
186                 bus_release_resource(dev, sc->drq_type, sc->drq_rid, sc->drq);
187
188         if (mtx_initialized(&sc->mtx) != 0)
189                 mtx_destroy(&sc->mtx);
190
191         return;
192 }
193
194 static device_method_t mcd_isa_methods[] = {
195         DEVMETHOD(device_probe,         mcd_isa_probe),
196         DEVMETHOD(device_attach,        mcd_isa_attach),
197         DEVMETHOD(device_detach,        mcd_isa_detach),
198
199         { 0, 0 }
200 };
201
202 static driver_t mcd_isa_driver = {
203         "mcd",
204         mcd_isa_methods,
205         sizeof(struct mcd_softc)
206 };
207
208 static devclass_t       mcd_devclass;
209
210 DRIVER_MODULE(mcd, isa, mcd_isa_driver, mcd_devclass, NULL, 0);