uk.c revision 1.52.36.5 1 /* $NetBSD: uk.c,v 1.52.36.5 2009/01/17 13:29:08 mjf Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Dummy driver for a device we can't identify.
34 * Originally by Julian Elischer (julian (at) tfs.com)
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: uk.c,v 1.52.36.5 2009/01/17 13:29:08 mjf Exp $");
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42
43 #include <sys/errno.h>
44 #include <sys/ioctl.h>
45 #include <sys/device.h>
46 #include <sys/conf.h>
47 #include <sys/vnode.h>
48
49 #include <dev/scsipi/scsi_all.h>
50 #include <dev/scsipi/scsipi_all.h>
51 #include <dev/scsipi/scsiconf.h>
52
53 #define UKUNIT(z) (minor(z))
54
55 struct uk_softc {
56 struct device sc_dev;
57
58 struct scsipi_periph *sc_periph; /* all the inter level info */
59 };
60
61 static int ukmatch(struct device *, struct cfdata *, void *);
62 static void ukattach(struct device *, struct device *, void *);
63 static int ukactivate(struct device *, enum devact);
64 static int ukdetach(struct device *, int);
65
66
67 CFATTACH_DECL(uk, sizeof(struct uk_softc), ukmatch, ukattach, ukdetach,
68 ukactivate);
69
70 extern struct cfdriver uk_cd;
71
72 static dev_type_open(ukopen);
73 static dev_type_close(ukclose);
74 static dev_type_ioctl(ukioctl);
75
76 const struct cdevsw uk_cdevsw = {
77 ukopen, ukclose, noread, nowrite, ukioctl,
78 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
79 };
80
81 static int
82 ukmatch(struct device *parent, struct cfdata *match,
83 void *aux)
84 {
85
86 return (1);
87 }
88
89 /*
90 * The routine called by the low level scsi routine when it discovers
91 * a device suitable for this driver.
92 */
93 static void
94 ukattach(struct device *parent, struct device *self, void *aux)
95 {
96 struct uk_softc *uk = device_private(self);
97 struct scsipibus_attach_args *sa = aux;
98 struct scsipi_periph *periph = sa->sa_periph;
99 int maj;
100
101 SC_DEBUG(periph, SCSIPI_DB2, ("ukattach: "));
102
103 /*
104 * Store information needed to contact our base driver
105 */
106 uk->sc_periph = periph;
107 periph->periph_dev = &uk->sc_dev;
108
109 printf("\n");
110
111 maj = cdevsw_lookup_major(&uk_cdevsw);
112 device_register_name(makedev(maj, device_unit(self)), self, true,
113 DEV_OTHER, device_xname(self));
114 }
115
116 static int
117 ukactivate(struct device *self, enum devact act)
118 {
119 int rv = 0;
120
121 switch (act) {
122 case DVACT_ACTIVATE:
123 rv = EOPNOTSUPP;
124 break;
125
126 case DVACT_DEACTIVATE:
127 /*
128 * Nothing to do; we key off the device's DVF_ACTIVE.
129 */
130 break;
131 }
132 return (rv);
133 }
134
135 static int
136 ukdetach(struct device *self, int flags)
137 {
138 /*struct uk_softc *uk = device_private(self);*/
139 int cmaj, mn;
140
141 device_deregister_all(self);
142
143 /* locate the major number */
144 cmaj = cdevsw_lookup_major(&uk_cdevsw);
145
146 /* Nuke the vnodes for any open instances */
147 mn = device_unit(self);
148 vdevgone(cmaj, mn, mn, VCHR);
149
150 return (0);
151 }
152
153 /*
154 * open the device.
155 */
156 static int
157 ukopen(dev_t dev, int flag, int fmt, struct lwp *l)
158 {
159 int unit, error;
160 struct uk_softc *uk;
161 struct scsipi_periph *periph;
162 struct scsipi_adapter *adapt;
163
164 unit = UKUNIT(dev);
165 uk = device_lookup_private(&uk_cd, unit);
166 if (uk == NULL)
167 return (ENXIO);
168
169 periph = uk->sc_periph;
170 adapt = periph->periph_channel->chan_adapter;
171
172 SC_DEBUG(periph, SCSIPI_DB1,
173 ("ukopen: dev=0x%"PRIx64" (unit %d (of %d))\n", dev, unit,
174 uk_cd.cd_ndevs));
175
176 /*
177 * Only allow one at a time
178 */
179 if (periph->periph_flags & PERIPH_OPEN) {
180 aprint_error_dev(&uk->sc_dev, "already open\n");
181 return (EBUSY);
182 }
183
184 if ((error = scsipi_adapter_addref(adapt)) != 0)
185 return (error);
186 periph->periph_flags |= PERIPH_OPEN;
187
188 SC_DEBUG(periph, SCSIPI_DB3, ("open complete\n"));
189 return (0);
190 }
191
192 /*
193 * close the device.. only called if we are the LAST
194 * occurence of an open device
195 */
196 static int
197 ukclose(dev_t dev, int flag, int fmt, struct lwp *l)
198 {
199 struct uk_softc *uk = device_lookup_private(&uk_cd, UKUNIT(dev));
200 struct scsipi_periph *periph = uk->sc_periph;
201 struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
202
203 SC_DEBUG(uk->sc_periph, SCSIPI_DB1, ("closing\n"));
204
205 scsipi_wait_drain(periph);
206
207 scsipi_adapter_delref(adapt);
208 periph->periph_flags &= ~PERIPH_OPEN;
209
210 return (0);
211 }
212
213 /*
214 * Perform special action on behalf of the user
215 * Only does generic scsi ioctls.
216 */
217 static int
218 ukioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
219 {
220 struct uk_softc *uk = device_lookup_private(&uk_cd, UKUNIT(dev));
221
222 return (scsipi_do_ioctl(uk->sc_periph, dev, cmd, addr, flag, l));
223 }
224