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