kernel: Use DEVMETHOD_END in the drivers.
[dragonfly.git] / sys / dev / disk / stg / tmc18c30_isa.c
1 /*      $FreeBSD: src/sys/dev/stg/tmc18c30_isa.c,v 1.2.2.4 2001/09/04 04:45:23 non Exp $        */
2 /*      $NecBSD: tmc18c30_pisa.c,v 1.22 1998/11/26 01:59:21 honda Exp $ */
3 /*      $NetBSD$        */
4
5 /*
6 * [Ported for FreeBSD]
7 *  Copyright (c) 2000
8 *      Noriaki Mitsunaga, Mitsuru Iwasaki and Takanori Watanabe.
9 *      All rights reserved.
10 * [NetBSD for NEC PC-98 series]
11 *  Copyright (c) 1996, 1997, 1998
12 *       NetBSD/pc98 porting staff. All rights reserved.
13 *  Copyright (c) 1996, 1997, 1998
14 *       Naofumi HONDA. All rights reserved.
15 *  Copyright (c) 1996, 1997, 1998
16 *       Kouichi Matsuda. All rights reserved.
17
18 *  Redistribution and use in source and binary forms, with or without
19 *  modification, are permitted provided that the following conditions
20 *  are met:
21 *  1. Redistributions of source code must retain the above copyright
22 *     notice, this list of conditions and the following disclaimer.
23 *  2. Redistributions in binary form must reproduce the above copyright
24 *     notice, this list of conditions and the following disclaimer in the
25 *     documentation and/or other materials provided with the distribution.
26 *  3. The name of the author may not be used to endorse or promote products
27 *     derived from this software without specific prior written permission.
28
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
30 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/module.h>
46 #include <sys/bus.h>
47 #include <sys/buf.h>
48 #include <sys/queue.h>
49 #include <sys/malloc.h>
50 #include <sys/errno.h>
51 #include <sys/rman.h>
52 #include <sys/device_port.h>
53 #include <sys/thread2.h>
54
55 #include <vm/vm.h>
56
57 #include <bus/isa/isavar.h>
58
59 #include <bus/cam/scsi/scsi_low.h>
60 #include <bus/isa/isa_common.h>
61 #include <bus/cam/scsi/scsi_low_pisa.h>
62
63 #include "tmc18c30reg.h"
64 #include "tmc18c30var.h"
65
66 #define STG_HOSTID      7
67
68 #include        <sys/kernel.h>
69 #include        <sys/module.h>
70
71 static  int     stgprobe(device_t devi);
72 static  int     stgattach(device_t devi);
73
74 static  void    stg_isa_unload  (device_t);
75
76 static void
77 stg_isa_intr(void * arg)
78 {
79         stgintr(arg);
80 }
81
82 static void
83 stg_release_resource(device_t dev)
84 {
85         struct stg_softc        *sc = device_get_softc(dev);
86
87         if (sc->stg_intrhand) {
88                 bus_teardown_intr(dev, sc->irq_res, sc->stg_intrhand);
89         }
90
91         if (sc->port_res) {
92                 bus_release_resource(dev, SYS_RES_IOPORT,
93                                      sc->port_rid, sc->port_res);
94         }
95
96         if (sc->irq_res) {
97                 bus_release_resource(dev, SYS_RES_IRQ,
98                                      sc->irq_rid, sc->irq_res);
99         }
100
101         if (sc->mem_res) {
102                 bus_release_resource(dev, SYS_RES_MEMORY,
103                                      sc->mem_rid, sc->mem_res);
104         }
105 }
106
107 static int
108 stg_alloc_resource(device_t dev)
109 {
110         struct stg_softc        *sc = device_get_softc(dev);
111         u_long                  maddr, msize;
112         int                     error;
113
114         sc->port_rid = 0;
115         sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid,
116                                           0, ~0, STGIOSZ, RF_ACTIVE);
117         if (sc->port_res == NULL) {
118                 stg_release_resource(dev);
119                 return(ENOMEM);
120         }
121
122         sc->irq_rid = 0;
123         sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
124                                          0, ~0, 1, RF_ACTIVE);
125         if (sc->irq_res == NULL) {
126                 stg_release_resource(dev);
127                 return(ENOMEM);
128         }
129
130         error = bus_get_resource(dev, SYS_RES_MEMORY, 0, &maddr, &msize);
131         if (error) {
132                 return(0);      /* XXX */
133         }
134
135         /* no need to allocate memory if not configured */
136         if (maddr == 0 || msize == 0) {
137                 return(0);
138         }
139
140         sc->mem_rid = 0;
141         sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid,
142                                          0, ~0, 1, RF_ACTIVE);
143         if (sc->mem_res == NULL) {
144                 stg_release_resource(dev);
145                 return(ENOMEM);
146         }
147
148         return(0);
149 }
150
151 static int
152 stg_isa_probe(device_t dev)
153 {
154         struct stg_softc        *sc = device_get_softc(dev);
155         int                     error;
156
157         bzero(sc, sizeof(struct stg_softc));
158
159         error = stg_alloc_resource(dev);
160         if (error) {
161                 return(error);
162         }
163
164         if (stgprobe(dev) == 0) {
165                 stg_release_resource(dev);
166                 return(ENXIO);
167         }
168
169         stg_release_resource(dev);
170
171         return(0);
172 }
173
174 static int
175 stg_isa_attach(device_t dev)
176 {
177         struct stg_softc        *sc = device_get_softc(dev);
178         int                     error;
179
180         error = stg_alloc_resource(dev);
181         if (error) {
182                 return(error);
183         }
184
185         error = bus_setup_intr(dev, sc->irq_res, 0,
186                                stg_isa_intr, (void *)sc,
187                                &sc->stg_intrhand, NULL);
188         if (error) {
189                 stg_release_resource(dev);
190                 return(error);
191         }
192
193         if (stgattach(dev) == 0) {
194                 stg_release_resource(dev);
195                 return(ENXIO);
196         }
197
198         return(0);
199 }
200
201 static  void
202 stg_isa_detach(device_t dev)
203 {
204         stg_isa_unload(dev);
205         stg_release_resource(dev);
206 }
207
208 static device_method_t stg_isa_methods[] = {
209         /* Device interface */
210         DEVMETHOD(device_probe,         stg_isa_probe),
211         DEVMETHOD(device_attach,        stg_isa_attach),
212         DEVMETHOD(device_detach,        stg_isa_detach),
213
214         DEVMETHOD_END
215 };
216
217 static driver_t stg_isa_driver = {
218         "stg",
219         stg_isa_methods,
220         sizeof(struct stg_softc),
221 };
222
223 static devclass_t stg_devclass;
224
225 DRIVER_MODULE(stg, isa, stg_isa_driver, stg_devclass, NULL, NULL);
226
227 static  void
228 stg_isa_unload(device_t devi)
229 {
230         struct stg_softc *sc = device_get_softc(devi);
231
232         kprintf("%s: unload\n",sc->sc_sclow.sl_xname);
233         crit_enter();
234         scsi_low_deactivate((struct scsi_low_softc *)sc);
235         scsi_low_dettach(&sc->sc_sclow);
236         crit_exit();
237 }
238
239 static  int
240 stgprobe(device_t devi)
241 {
242         int rv;
243         struct stg_softc *sc = device_get_softc(devi);
244
245         rv = stgprobesubr(rman_get_bustag(sc->port_res),
246                           rman_get_bushandle(sc->port_res),
247                           device_get_flags(devi));
248
249         return rv;
250 }
251
252 static  int
253 stgattach(device_t devi)
254 {
255         struct stg_softc *sc;
256         struct scsi_low_softc *slp;
257         u_int32_t flags = device_get_flags(devi);
258         u_int iobase = bus_get_resource_start(devi, SYS_RES_IOPORT, 0);
259         char    dvname[16];
260
261         strcpy(dvname,"stg");
262
263
264         if (iobase == 0)
265         {
266                 kprintf("%s: no ioaddr is given\n", dvname);
267                 return (0);
268         }
269
270         sc = device_get_softc(devi);
271         if (sc == NULL) {
272                 return(0);
273         }
274
275         slp = &sc->sc_sclow;
276         slp->sl_dev = devi;
277         sc->sc_iot = rman_get_bustag(sc->port_res);
278         sc->sc_ioh = rman_get_bushandle(sc->port_res);
279
280         slp->sl_hostid = STG_HOSTID;
281         slp->sl_cfgflags = flags;
282
283         crit_enter();
284         stgattachsubr(sc);
285         crit_exit();
286
287         return(STGIOSZ);
288 }