ld_iop.c revision 1.3.2.4 1 1.3.2.4 bouyer /* $NetBSD: ld_iop.c,v 1.3.2.4 2001/02/11 19:15:23 bouyer Exp $ */
2 1.3.2.2 bouyer
3 1.3.2.2 bouyer /*-
4 1.3.2.2 bouyer * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 1.3.2.2 bouyer * All rights reserved.
6 1.3.2.2 bouyer *
7 1.3.2.2 bouyer * This code is derived from software contributed to The NetBSD Foundation
8 1.3.2.2 bouyer * by Andrew Doran.
9 1.3.2.2 bouyer *
10 1.3.2.2 bouyer * Redistribution and use in source and binary forms, with or without
11 1.3.2.2 bouyer * modification, are permitted provided that the following conditions
12 1.3.2.2 bouyer * are met:
13 1.3.2.2 bouyer * 1. Redistributions of source code must retain the above copyright
14 1.3.2.2 bouyer * notice, this list of conditions and the following disclaimer.
15 1.3.2.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright
16 1.3.2.2 bouyer * notice, this list of conditions and the following disclaimer in the
17 1.3.2.2 bouyer * documentation and/or other materials provided with the distribution.
18 1.3.2.2 bouyer * 3. All advertising materials mentioning features or use of this software
19 1.3.2.2 bouyer * must display the following acknowledgement:
20 1.3.2.2 bouyer * This product includes software developed by the NetBSD
21 1.3.2.2 bouyer * Foundation, Inc. and its contributors.
22 1.3.2.2 bouyer * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.3.2.2 bouyer * contributors may be used to endorse or promote products derived
24 1.3.2.2 bouyer * from this software without specific prior written permission.
25 1.3.2.2 bouyer *
26 1.3.2.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.3.2.2 bouyer * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.3.2.2 bouyer * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.3.2.2 bouyer * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.3.2.2 bouyer * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.3.2.2 bouyer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.3.2.2 bouyer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.3.2.2 bouyer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.3.2.2 bouyer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.3.2.2 bouyer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.3.2.2 bouyer * POSSIBILITY OF SUCH DAMAGE.
37 1.3.2.2 bouyer */
38 1.3.2.2 bouyer
39 1.3.2.2 bouyer /*
40 1.3.2.2 bouyer * I2O front-end for ld(4) driver, supporting random block storage class
41 1.3.2.2 bouyer * devices. Currently, this doesn't handle anything more complex than
42 1.3.2.2 bouyer * fixed direct-access devices.
43 1.3.2.2 bouyer */
44 1.3.2.2 bouyer
45 1.3.2.2 bouyer #include "opt_i2o.h"
46 1.3.2.2 bouyer #include "rnd.h"
47 1.3.2.2 bouyer
48 1.3.2.2 bouyer #include <sys/param.h>
49 1.3.2.2 bouyer #include <sys/systm.h>
50 1.3.2.2 bouyer #include <sys/kernel.h>
51 1.3.2.2 bouyer #include <sys/device.h>
52 1.3.2.2 bouyer #include <sys/buf.h>
53 1.3.2.2 bouyer #include <sys/endian.h>
54 1.3.2.2 bouyer #include <sys/dkio.h>
55 1.3.2.2 bouyer #include <sys/disk.h>
56 1.3.2.2 bouyer #include <sys/proc.h>
57 1.3.2.2 bouyer #if NRND > 0
58 1.3.2.2 bouyer #include <sys/rnd.h>
59 1.3.2.2 bouyer #endif
60 1.3.2.2 bouyer
61 1.3.2.2 bouyer #include <machine/bus.h>
62 1.3.2.2 bouyer
63 1.3.2.2 bouyer #include <dev/ldvar.h>
64 1.3.2.2 bouyer
65 1.3.2.2 bouyer #include <dev/i2o/i2o.h>
66 1.3.2.2 bouyer #include <dev/i2o/iopvar.h>
67 1.3.2.2 bouyer
68 1.3.2.2 bouyer #define LD_IOP_MAXQUEUECNT 64 /* XXX */
69 1.3.2.2 bouyer #define LD_IOP_TIMEOUT 10*1000*1000
70 1.3.2.2 bouyer
71 1.3.2.2 bouyer struct ld_iop_softc {
72 1.3.2.2 bouyer struct ld_softc sc_ld;
73 1.3.2.2 bouyer struct iop_initiator sc_ii;
74 1.3.2.2 bouyer struct iop_initiator sc_eventii;
75 1.3.2.2 bouyer int sc_claimed;
76 1.3.2.2 bouyer u_int sc_tid;
77 1.3.2.2 bouyer };
78 1.3.2.2 bouyer
79 1.3.2.2 bouyer static void ld_iop_attach(struct device *, struct device *, void *);
80 1.3.2.2 bouyer static int ld_iop_detach(struct device *, int);
81 1.3.2.2 bouyer static int ld_iop_dump(struct ld_softc *, void *, int, int);
82 1.3.2.2 bouyer static int ld_iop_flush(struct ld_softc *);
83 1.3.2.2 bouyer static void ld_iop_intr(struct device *, struct iop_msg *, void *);
84 1.3.2.2 bouyer static void ld_iop_intr_event(struct device *, struct iop_msg *, void *);
85 1.3.2.2 bouyer static int ld_iop_start(struct ld_softc *, struct buf *);
86 1.3.2.2 bouyer static int ld_iop_match(struct device *, struct cfdata *, void *);
87 1.3.2.2 bouyer
88 1.3.2.2 bouyer struct cfattach ld_iop_ca = {
89 1.3.2.2 bouyer sizeof(struct ld_iop_softc),
90 1.3.2.2 bouyer ld_iop_match,
91 1.3.2.2 bouyer ld_iop_attach,
92 1.3.2.2 bouyer ld_iop_detach
93 1.3.2.2 bouyer };
94 1.3.2.2 bouyer
95 1.3.2.2 bouyer #ifdef I2OVERBOSE
96 1.3.2.2 bouyer static const char *ld_iop_errors[] = {
97 1.3.2.2 bouyer "success",
98 1.3.2.2 bouyer "media error",
99 1.3.2.2 bouyer "failure communicating with device",
100 1.3.2.2 bouyer "device failure",
101 1.3.2.2 bouyer "device is not ready",
102 1.3.2.2 bouyer "media not present",
103 1.3.2.2 bouyer "media locked by another user",
104 1.3.2.2 bouyer "media failure",
105 1.3.2.2 bouyer "failure communicating to device",
106 1.3.2.2 bouyer "device bus failure",
107 1.3.2.2 bouyer "device locked by another user",
108 1.3.2.2 bouyer "device write protected",
109 1.3.2.2 bouyer "device reset",
110 1.3.2.2 bouyer "volume has changed, waiting for acknowledgement",
111 1.3.2.2 bouyer };
112 1.3.2.2 bouyer #endif
113 1.3.2.2 bouyer
114 1.3.2.2 bouyer static int
115 1.3.2.2 bouyer ld_iop_match(struct device *parent, struct cfdata *match, void *aux)
116 1.3.2.2 bouyer {
117 1.3.2.2 bouyer struct iop_attach_args *ia;
118 1.3.2.2 bouyer
119 1.3.2.2 bouyer ia = aux;
120 1.3.2.2 bouyer
121 1.3.2.2 bouyer return (ia->ia_class == I2O_CLASS_RANDOM_BLOCK_STORAGE);
122 1.3.2.2 bouyer }
123 1.3.2.2 bouyer
124 1.3.2.2 bouyer static void
125 1.3.2.2 bouyer ld_iop_attach(struct device *parent, struct device *self, void *aux)
126 1.3.2.2 bouyer {
127 1.3.2.2 bouyer struct iop_attach_args *ia;
128 1.3.2.2 bouyer struct ld_softc *ld;
129 1.3.2.2 bouyer struct ld_iop_softc *sc;
130 1.3.2.2 bouyer struct iop_softc *iop;
131 1.3.2.2 bouyer int rv, evreg, enable;
132 1.3.2.2 bouyer char ident[64 + 1], *typestr, *fixedstr;
133 1.3.2.2 bouyer u_int cachesz;
134 1.3.2.2 bouyer struct {
135 1.3.2.2 bouyer struct i2o_param_op_results pr;
136 1.3.2.2 bouyer struct i2o_param_read_results prr;
137 1.3.2.2 bouyer union {
138 1.3.2.2 bouyer struct i2o_param_rbs_cache_control cc;
139 1.3.2.2 bouyer struct i2o_param_rbs_device_info bdi;
140 1.3.2.2 bouyer struct i2o_param_device_identity di;
141 1.3.2.2 bouyer struct i2o_param_rbs_operation op;
142 1.3.2.2 bouyer } p;
143 1.3.2.2 bouyer } param;
144 1.3.2.2 bouyer
145 1.3.2.2 bouyer sc = (struct ld_iop_softc *)self;
146 1.3.2.2 bouyer ld = &sc->sc_ld;
147 1.3.2.2 bouyer iop = (struct iop_softc *)parent;
148 1.3.2.2 bouyer ia = (struct iop_attach_args *)aux;
149 1.3.2.2 bouyer sc->sc_tid = ia->ia_tid;
150 1.3.2.2 bouyer evreg = 0;
151 1.3.2.2 bouyer
152 1.3.2.2 bouyer /* Register us as an initiator. */
153 1.3.2.2 bouyer sc->sc_ii.ii_dv = self;
154 1.3.2.2 bouyer sc->sc_ii.ii_intr = ld_iop_intr;
155 1.3.2.2 bouyer sc->sc_ii.ii_flags = 0;
156 1.3.2.2 bouyer sc->sc_ii.ii_tid = ia->ia_tid;
157 1.3.2.2 bouyer if (iop_initiator_register(iop, &sc->sc_ii) != 0) {
158 1.3.2.2 bouyer printf("%s: unable to register initiator\n", self->dv_xname);
159 1.3.2.2 bouyer return;
160 1.3.2.2 bouyer }
161 1.3.2.2 bouyer
162 1.3.2.2 bouyer /* Register another initiator to handle events from the device. */
163 1.3.2.2 bouyer sc->sc_eventii.ii_dv = self;
164 1.3.2.2 bouyer sc->sc_eventii.ii_intr = ld_iop_intr_event;
165 1.3.2.2 bouyer sc->sc_eventii.ii_flags = II_DISCARD | II_UTILITY;
166 1.3.2.2 bouyer sc->sc_eventii.ii_tid = ia->ia_tid;
167 1.3.2.2 bouyer if (iop_initiator_register(iop, &sc->sc_eventii) != 0) {
168 1.3.2.2 bouyer printf("%s: unable to register initiator", self->dv_xname);
169 1.3.2.2 bouyer goto bad;
170 1.3.2.2 bouyer }
171 1.3.2.2 bouyer if (iop_util_eventreg(iop, &sc->sc_eventii, 0xffffffff)) {
172 1.3.2.2 bouyer printf("%s: unable to register for events", self->dv_xname);
173 1.3.2.2 bouyer goto bad;
174 1.3.2.2 bouyer }
175 1.3.2.2 bouyer evreg = 1;
176 1.3.2.2 bouyer
177 1.3.2.2 bouyer ld->sc_maxxfer = IOP_MAX_XFER;
178 1.3.2.2 bouyer ld->sc_maxqueuecnt = LD_IOP_MAXQUEUECNT;
179 1.3.2.2 bouyer ld->sc_dump = ld_iop_dump;
180 1.3.2.2 bouyer ld->sc_flush = ld_iop_flush;
181 1.3.2.2 bouyer ld->sc_start = ld_iop_start;
182 1.3.2.2 bouyer
183 1.3.2.2 bouyer /* Say what the device is. */
184 1.3.2.2 bouyer printf(": ");
185 1.3.2.2 bouyer if (iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_DEVICE_IDENTITY, ¶m,
186 1.3.2.2 bouyer sizeof(param)) == 0) {
187 1.3.2.2 bouyer iop_strvis(iop, param.p.di.vendorinfo,
188 1.3.2.2 bouyer sizeof(param.p.di.vendorinfo), ident, sizeof(ident));
189 1.3.2.2 bouyer printf("<%s, ", ident);
190 1.3.2.2 bouyer iop_strvis(iop, param.p.di.productinfo,
191 1.3.2.2 bouyer sizeof(param.p.di.productinfo), ident, sizeof(ident));
192 1.3.2.2 bouyer printf("%s, ", ident);
193 1.3.2.2 bouyer iop_strvis(iop, param.p.di.revlevel,
194 1.3.2.2 bouyer sizeof(param.p.di.revlevel), ident, sizeof(ident));
195 1.3.2.2 bouyer printf("%s> ", ident);
196 1.3.2.2 bouyer }
197 1.3.2.2 bouyer
198 1.3.2.2 bouyer /*
199 1.3.2.2 bouyer * Claim the device so that we don't get any nasty surprises. Allow
200 1.3.2.2 bouyer * failure.
201 1.3.2.2 bouyer */
202 1.3.2.2 bouyer sc->sc_claimed = !iop_util_claim(iop, &sc->sc_ii, 0,
203 1.3.2.2 bouyer I2O_UTIL_CLAIM_CAPACITY_SENSITIVE |
204 1.3.2.2 bouyer I2O_UTIL_CLAIM_NO_PEER_SERVICE |
205 1.3.2.2 bouyer I2O_UTIL_CLAIM_NO_MANAGEMENT_SERVICE |
206 1.3.2.2 bouyer I2O_UTIL_CLAIM_PRIMARY_USER);
207 1.3.2.2 bouyer
208 1.3.2.2 bouyer rv = iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_RBS_DEVICE_INFO,
209 1.3.2.2 bouyer ¶m, sizeof(param));
210 1.3.2.2 bouyer if (rv != 0) {
211 1.3.2.2 bouyer printf("%s: unable to get parameters (0x%04x; %d)\n",
212 1.3.2.2 bouyer ld->sc_dv.dv_xname, I2O_PARAM_RBS_DEVICE_INFO, rv);
213 1.3.2.2 bouyer goto bad;
214 1.3.2.2 bouyer }
215 1.3.2.2 bouyer
216 1.3.2.2 bouyer ld->sc_secsize = le32toh(param.p.bdi.blocksize);
217 1.3.2.2 bouyer ld->sc_secperunit = (int)
218 1.3.2.2 bouyer (le64toh(param.p.bdi.capacity) / ld->sc_secsize);
219 1.3.2.2 bouyer
220 1.3.2.2 bouyer /* Build synthetic geometry. */
221 1.3.2.2 bouyer if (ld->sc_secperunit <= 528 * 2048) /* 528MB */
222 1.3.2.2 bouyer ld->sc_nheads = 16;
223 1.3.2.2 bouyer else if (ld->sc_secperunit <= 1024 * 2048) /* 1GB */
224 1.3.2.2 bouyer ld->sc_nheads = 32;
225 1.3.2.2 bouyer else if (ld->sc_secperunit <= 21504 * 2048) /* 21GB */
226 1.3.2.2 bouyer ld->sc_nheads = 64;
227 1.3.2.2 bouyer else if (ld->sc_secperunit <= 43008 * 2048) /* 42GB */
228 1.3.2.2 bouyer ld->sc_nheads = 128;
229 1.3.2.2 bouyer else
230 1.3.2.2 bouyer ld->sc_nheads = 255;
231 1.3.2.2 bouyer
232 1.3.2.2 bouyer ld->sc_nsectors = 63;
233 1.3.2.2 bouyer ld->sc_ncylinders = ld->sc_secperunit /
234 1.3.2.2 bouyer (ld->sc_nheads * ld->sc_nsectors);
235 1.3.2.2 bouyer
236 1.3.2.2 bouyer switch (param.p.bdi.type) {
237 1.3.2.2 bouyer case I2O_RBS_TYPE_DIRECT:
238 1.3.2.2 bouyer typestr = "direct access";
239 1.3.2.2 bouyer enable = 1;
240 1.3.2.2 bouyer break;
241 1.3.2.2 bouyer case I2O_RBS_TYPE_WORM:
242 1.3.2.2 bouyer typestr = "WORM";
243 1.3.2.2 bouyer enable = 0;
244 1.3.2.2 bouyer break;
245 1.3.2.2 bouyer case I2O_RBS_TYPE_CDROM:
246 1.3.2.2 bouyer typestr = "cdrom";
247 1.3.2.2 bouyer enable = 0;
248 1.3.2.2 bouyer break;
249 1.3.2.2 bouyer case I2O_RBS_TYPE_OPTICAL:
250 1.3.2.2 bouyer typestr = "optical";
251 1.3.2.2 bouyer enable = 0;
252 1.3.2.2 bouyer break;
253 1.3.2.2 bouyer default:
254 1.3.2.2 bouyer typestr = "unknown";
255 1.3.2.2 bouyer enable = 0;
256 1.3.2.2 bouyer break;
257 1.3.2.2 bouyer }
258 1.3.2.2 bouyer
259 1.3.2.2 bouyer if ((le32toh(param.p.bdi.capabilities) & I2O_RBS_CAP_REMOVEABLE_MEDIA)
260 1.3.2.2 bouyer != 0) {
261 1.3.2.2 bouyer /* ld->sc_flags = LDF_REMOVEABLE; */
262 1.3.2.2 bouyer fixedstr = "removeable";
263 1.3.2.2 bouyer enable = 0;
264 1.3.2.2 bouyer } else
265 1.3.2.2 bouyer fixedstr = "fixed";
266 1.3.2.2 bouyer
267 1.3.2.2 bouyer printf("%s, %s", typestr, fixedstr);
268 1.3.2.2 bouyer
269 1.3.2.2 bouyer /*
270 1.3.2.2 bouyer * Determine if the device has an private cache. If so, print the
271 1.3.2.2 bouyer * cache size. Even if the device doesn't appear to have a cache,
272 1.3.2.2 bouyer * we perform a flush at shutdown, as it is still valid to do so.
273 1.3.2.2 bouyer */
274 1.3.2.2 bouyer rv = iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_RBS_CACHE_CONTROL,
275 1.3.2.2 bouyer ¶m, sizeof(param));
276 1.3.2.2 bouyer if (rv != 0) {
277 1.3.2.2 bouyer printf("%s: unable to get parameters (0x%04x; %d)\n",
278 1.3.2.2 bouyer ld->sc_dv.dv_xname, I2O_PARAM_RBS_CACHE_CONTROL, rv);
279 1.3.2.2 bouyer goto bad;
280 1.3.2.2 bouyer }
281 1.3.2.2 bouyer
282 1.3.2.2 bouyer if ((cachesz = le32toh(param.p.cc.totalcachesize)) != 0)
283 1.3.2.2 bouyer printf(", %dkB cache", cachesz >> 10);
284 1.3.2.2 bouyer
285 1.3.2.2 bouyer printf("\n");
286 1.3.2.2 bouyer
287 1.3.2.2 bouyer /*
288 1.3.2.2 bouyer * Configure the DDM's timeout functions to time out all commands
289 1.3.2.2 bouyer * after 10 seconds.
290 1.3.2.2 bouyer */
291 1.3.2.2 bouyer rv = iop_param_op(iop, ia->ia_tid, 0, I2O_PARAM_RBS_OPERATION,
292 1.3.2.2 bouyer ¶m, sizeof(param));
293 1.3.2.2 bouyer if (rv != 0) {
294 1.3.2.2 bouyer printf("%s: unable to get parameters (0x%04x; %d)\n",
295 1.3.2.2 bouyer ld->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
296 1.3.2.2 bouyer goto bad;
297 1.3.2.2 bouyer }
298 1.3.2.2 bouyer
299 1.3.2.2 bouyer param.p.op.timeoutbase = htole32(LD_IOP_TIMEOUT);
300 1.3.2.2 bouyer param.p.op.rwvtimeoutbase = htole32(LD_IOP_TIMEOUT);
301 1.3.2.2 bouyer param.p.op.rwvtimeout = 0;
302 1.3.2.2 bouyer
303 1.3.2.2 bouyer rv = iop_param_op(iop, ia->ia_tid, 1, I2O_PARAM_RBS_OPERATION,
304 1.3.2.2 bouyer ¶m, sizeof(param));
305 1.3.2.2 bouyer if (rv != 0) {
306 1.3.2.2 bouyer printf("%s: unable to set parameters (0x%04x; %d)\n",
307 1.3.2.2 bouyer ld->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
308 1.3.2.2 bouyer goto bad;
309 1.3.2.2 bouyer }
310 1.3.2.2 bouyer
311 1.3.2.2 bouyer if (enable)
312 1.3.2.2 bouyer ld->sc_flags |= LDF_ENABLED;
313 1.3.2.2 bouyer else
314 1.3.2.2 bouyer printf("%s: device not yet supported\n", self->dv_xname);
315 1.3.2.2 bouyer
316 1.3.2.2 bouyer ldattach(ld);
317 1.3.2.2 bouyer return;
318 1.3.2.2 bouyer
319 1.3.2.2 bouyer bad:
320 1.3.2.2 bouyer if (sc->sc_claimed)
321 1.3.2.2 bouyer iop_util_claim(iop, &sc->sc_ii, 1,
322 1.3.2.2 bouyer I2O_UTIL_CLAIM_PRIMARY_USER);
323 1.3.2.2 bouyer if (evreg)
324 1.3.2.2 bouyer iop_util_eventreg(iop, &sc->sc_eventii, 0);
325 1.3.2.2 bouyer if (sc->sc_eventii.ii_intr != NULL)
326 1.3.2.2 bouyer iop_initiator_unregister(iop, &sc->sc_eventii);
327 1.3.2.2 bouyer iop_initiator_unregister(iop, &sc->sc_ii);
328 1.3.2.2 bouyer }
329 1.3.2.2 bouyer
330 1.3.2.2 bouyer static int
331 1.3.2.2 bouyer ld_iop_detach(struct device *self, int flags)
332 1.3.2.2 bouyer {
333 1.3.2.2 bouyer struct ld_iop_softc *sc;
334 1.3.2.2 bouyer struct iop_softc *iop;
335 1.3.2.3 bouyer int rv;
336 1.3.2.2 bouyer
337 1.3.2.2 bouyer sc = (struct ld_iop_softc *)self;
338 1.3.2.2 bouyer
339 1.3.2.4 bouyer if ((rv = ldbegindetach(&sc->sc_ld, flags)) != 0)
340 1.3.2.3 bouyer return (rv);
341 1.3.2.2 bouyer
342 1.3.2.2 bouyer iop = (struct iop_softc *)self->dv_parent;
343 1.3.2.2 bouyer
344 1.3.2.2 bouyer /*
345 1.3.2.2 bouyer * Abort any requests queued with the IOP, but allow requests that
346 1.3.2.2 bouyer * are already in progress to complete.
347 1.3.2.2 bouyer */
348 1.3.2.2 bouyer if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0)
349 1.3.2.2 bouyer iop_util_abort(iop, &sc->sc_ii, 0, 0,
350 1.3.2.2 bouyer I2O_UTIL_ABORT_WILD | I2O_UTIL_ABORT_CLEAN);
351 1.3.2.2 bouyer
352 1.3.2.4 bouyer ldenddetach(&sc->sc_ld);
353 1.3.2.2 bouyer
354 1.3.2.2 bouyer /* Un-claim the target, and un-register us as an initiator. */
355 1.3.2.2 bouyer if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0) {
356 1.3.2.2 bouyer if (sc->sc_claimed) {
357 1.3.2.2 bouyer rv = iop_util_claim(iop, &sc->sc_ii, 1,
358 1.3.2.2 bouyer I2O_UTIL_CLAIM_PRIMARY_USER);
359 1.3.2.2 bouyer if (rv != 0)
360 1.3.2.2 bouyer return (rv);
361 1.3.2.2 bouyer }
362 1.3.2.2 bouyer iop_util_eventreg(iop, &sc->sc_eventii, 0);
363 1.3.2.2 bouyer iop_initiator_unregister(iop, &sc->sc_eventii);
364 1.3.2.2 bouyer iop_initiator_unregister(iop, &sc->sc_ii);
365 1.3.2.2 bouyer }
366 1.3.2.2 bouyer
367 1.3.2.2 bouyer return (0);
368 1.3.2.2 bouyer }
369 1.3.2.2 bouyer
370 1.3.2.2 bouyer static int
371 1.3.2.2 bouyer ld_iop_start(struct ld_softc *ld, struct buf *bp)
372 1.3.2.2 bouyer {
373 1.3.2.2 bouyer struct iop_msg *im;
374 1.3.2.2 bouyer struct iop_softc *iop;
375 1.3.2.2 bouyer struct ld_iop_softc *sc;
376 1.3.2.2 bouyer struct i2o_rbs_block_read *mb;
377 1.3.2.2 bouyer int rv, flags, write;
378 1.3.2.2 bouyer u_int64_t ba;
379 1.3.2.2 bouyer
380 1.3.2.2 bouyer sc = (struct ld_iop_softc *)ld;
381 1.3.2.2 bouyer iop = (struct iop_softc *)ld->sc_dv.dv_parent;
382 1.3.2.2 bouyer
383 1.3.2.2 bouyer im = NULL;
384 1.3.2.2 bouyer if ((rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT)) != 0)
385 1.3.2.2 bouyer goto bad;
386 1.3.2.2 bouyer im->im_dvcontext = bp;
387 1.3.2.2 bouyer
388 1.3.2.2 bouyer write = ((bp->b_flags & B_READ) == 0);
389 1.3.2.2 bouyer ba = (u_int64_t)bp->b_rawblkno * ld->sc_secsize;
390 1.3.2.2 bouyer
391 1.3.2.2 bouyer /*
392 1.3.2.2 bouyer * Write through the cache when performing synchronous writes. When
393 1.3.2.2 bouyer * performing a read, we don't request that the DDM cache the data,
394 1.3.2.2 bouyer * as there's little advantage to it.
395 1.3.2.2 bouyer */
396 1.3.2.2 bouyer if (write) {
397 1.3.2.2 bouyer if ((bp->b_flags & B_ASYNC) == 0)
398 1.3.2.2 bouyer flags = I2O_RBS_BLOCK_WRITE_CACHE_WT;
399 1.3.2.2 bouyer else
400 1.3.2.2 bouyer flags = I2O_RBS_BLOCK_WRITE_CACHE_WB;
401 1.3.2.2 bouyer } else
402 1.3.2.2 bouyer flags = 0;
403 1.3.2.2 bouyer
404 1.3.2.2 bouyer /*
405 1.3.2.2 bouyer * Fill the message frame. We can use the block_read structure for
406 1.3.2.2 bouyer * both reads and writes, as it's almost identical to the
407 1.3.2.2 bouyer * block_write structure.
408 1.3.2.2 bouyer */
409 1.3.2.2 bouyer mb = (struct i2o_rbs_block_read *)im->im_msg;
410 1.3.2.2 bouyer mb->msgflags = I2O_MSGFLAGS(i2o_rbs_block_read);
411 1.3.2.2 bouyer mb->msgfunc = I2O_MSGFUNC(sc->sc_tid,
412 1.3.2.2 bouyer write ? I2O_RBS_BLOCK_WRITE : I2O_RBS_BLOCK_READ);
413 1.3.2.2 bouyer mb->msgictx = sc->sc_ii.ii_ictx;
414 1.3.2.2 bouyer mb->msgtctx = im->im_tctx;
415 1.3.2.2 bouyer mb->flags = flags | (1 << 16); /* flags & time multiplier */
416 1.3.2.2 bouyer mb->datasize = bp->b_bcount;
417 1.3.2.2 bouyer mb->lowoffset = (u_int32_t)ba;
418 1.3.2.2 bouyer mb->highoffset = (u_int32_t)(ba >> 32);
419 1.3.2.2 bouyer
420 1.3.2.2 bouyer /* Map the data transfer. */
421 1.3.2.2 bouyer if ((rv = iop_msg_map(iop, im, bp->b_data, bp->b_bcount, write)) != 0)
422 1.3.2.2 bouyer goto bad;
423 1.3.2.2 bouyer
424 1.3.2.2 bouyer /* Enqueue the command. */
425 1.3.2.2 bouyer iop_msg_enqueue(iop, im, 0);
426 1.3.2.2 bouyer return (0);
427 1.3.2.2 bouyer
428 1.3.2.2 bouyer bad:
429 1.3.2.2 bouyer if (im != NULL)
430 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
431 1.3.2.2 bouyer return (rv);
432 1.3.2.2 bouyer }
433 1.3.2.2 bouyer
434 1.3.2.2 bouyer static int
435 1.3.2.2 bouyer ld_iop_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt)
436 1.3.2.2 bouyer {
437 1.3.2.2 bouyer struct iop_msg *im;
438 1.3.2.2 bouyer struct iop_softc *iop;
439 1.3.2.2 bouyer struct ld_iop_softc *sc;
440 1.3.2.2 bouyer struct i2o_rbs_block_write *mb;
441 1.3.2.2 bouyer int rv, bcount;
442 1.3.2.2 bouyer u_int64_t ba;
443 1.3.2.2 bouyer
444 1.3.2.2 bouyer sc = (struct ld_iop_softc *)ld;
445 1.3.2.2 bouyer iop = (struct iop_softc *)ld->sc_dv.dv_parent;
446 1.3.2.2 bouyer bcount = blkcnt * ld->sc_secsize;
447 1.3.2.2 bouyer ba = (u_int64_t)blkno * ld->sc_secsize;
448 1.3.2.2 bouyer
449 1.3.2.2 bouyer rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT | IM_NOINTR);
450 1.3.2.2 bouyer if (rv != 0)
451 1.3.2.2 bouyer return (rv);
452 1.3.2.2 bouyer
453 1.3.2.2 bouyer mb = (struct i2o_rbs_block_write *)im->im_msg;
454 1.3.2.2 bouyer mb->msgflags = I2O_MSGFLAGS(i2o_rbs_block_write);
455 1.3.2.2 bouyer mb->msgfunc = I2O_MSGFUNC(sc->sc_tid, I2O_RBS_BLOCK_WRITE);
456 1.3.2.2 bouyer mb->msgictx = sc->sc_ii.ii_ictx;
457 1.3.2.2 bouyer mb->msgtctx = im->im_tctx;
458 1.3.2.2 bouyer mb->flags = I2O_RBS_BLOCK_WRITE_CACHE_WT | (1 << 16);
459 1.3.2.2 bouyer mb->datasize = bcount;
460 1.3.2.2 bouyer mb->lowoffset = (u_int32_t)ba;
461 1.3.2.2 bouyer mb->highoffset = (u_int32_t)(ba >> 32);
462 1.3.2.2 bouyer
463 1.3.2.2 bouyer if ((rv = iop_msg_map(iop, im, data, bcount, 1)) != 0) {
464 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
465 1.3.2.2 bouyer return (rv);
466 1.3.2.2 bouyer }
467 1.3.2.2 bouyer
468 1.3.2.2 bouyer rv = (iop_msg_send(iop, im, 5000) != 0 ? EIO : 0);
469 1.3.2.2 bouyer iop_msg_unmap(iop, im);
470 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
471 1.3.2.2 bouyer return (rv);
472 1.3.2.2 bouyer }
473 1.3.2.2 bouyer
474 1.3.2.2 bouyer static int
475 1.3.2.2 bouyer ld_iop_flush(struct ld_softc *ld)
476 1.3.2.2 bouyer {
477 1.3.2.2 bouyer struct iop_msg *im;
478 1.3.2.2 bouyer struct iop_softc *iop;
479 1.3.2.2 bouyer struct ld_iop_softc *sc;
480 1.3.2.2 bouyer struct i2o_rbs_cache_flush *mb;
481 1.3.2.2 bouyer int rv;
482 1.3.2.2 bouyer
483 1.3.2.2 bouyer sc = (struct ld_iop_softc *)ld;
484 1.3.2.2 bouyer iop = (struct iop_softc *)ld->sc_dv.dv_parent;
485 1.3.2.2 bouyer
486 1.3.2.2 bouyer rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT | IM_NOINTR);
487 1.3.2.2 bouyer if (rv != 0)
488 1.3.2.2 bouyer return (rv);
489 1.3.2.2 bouyer
490 1.3.2.2 bouyer mb = (struct i2o_rbs_cache_flush *)im->im_msg;
491 1.3.2.2 bouyer mb->msgflags = I2O_MSGFLAGS(i2o_rbs_cache_flush);
492 1.3.2.2 bouyer mb->msgfunc = I2O_MSGFUNC(sc->sc_tid, I2O_RBS_CACHE_FLUSH);
493 1.3.2.2 bouyer mb->msgictx = sc->sc_ii.ii_ictx;
494 1.3.2.2 bouyer mb->msgtctx = im->im_tctx;
495 1.3.2.2 bouyer mb->flags = 1 << 16; /* time multiplier */
496 1.3.2.2 bouyer
497 1.3.2.2 bouyer rv = iop_msg_send(iop, im, 10000);
498 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
499 1.3.2.2 bouyer return (rv);
500 1.3.2.2 bouyer }
501 1.3.2.2 bouyer
502 1.3.2.2 bouyer void
503 1.3.2.2 bouyer ld_iop_intr(struct device *dv, struct iop_msg *im, void *reply)
504 1.3.2.2 bouyer {
505 1.3.2.2 bouyer struct i2o_rbs_reply *rb;
506 1.3.2.2 bouyer struct buf *bp;
507 1.3.2.2 bouyer struct ld_iop_softc *sc;
508 1.3.2.2 bouyer struct iop_softc *iop;
509 1.3.2.2 bouyer #ifdef I2OVERBOSE
510 1.3.2.2 bouyer int detail;
511 1.3.2.2 bouyer const char *errstr;
512 1.3.2.2 bouyer #endif
513 1.3.2.2 bouyer
514 1.3.2.2 bouyer rb = reply;
515 1.3.2.2 bouyer bp = im->im_dvcontext;
516 1.3.2.2 bouyer sc = (struct ld_iop_softc *)dv;
517 1.3.2.2 bouyer iop = (struct iop_softc *)dv->dv_parent;
518 1.3.2.2 bouyer
519 1.3.2.2 bouyer #ifdef I2OVERBOSE
520 1.3.2.2 bouyer if (rb->reqstatus != I2O_STATUS_SUCCESS) {
521 1.3.2.2 bouyer detail = le16toh(rb->detail);
522 1.3.2.2 bouyer if (detail > sizeof(ld_iop_errors) / sizeof(ld_iop_errors[0]))
523 1.3.2.2 bouyer errstr = "unknown error";
524 1.3.2.2 bouyer else
525 1.3.2.2 bouyer errstr = ld_iop_errors[detail];
526 1.3.2.2 bouyer printf("%s: %s\n", dv->dv_xname, errstr);
527 1.3.2.2 bouyer #else
528 1.3.2.2 bouyer if (rb->reqstatus != I2O_STATUS_SUCCESS) {
529 1.3.2.2 bouyer #endif
530 1.3.2.2 bouyer bp->b_flags |= B_ERROR;
531 1.3.2.2 bouyer bp->b_error = EIO;
532 1.3.2.2 bouyer #ifndef notyet
533 1.3.2.2 bouyer bp->b_resid = bp->b_bcount;
534 1.3.2.2 bouyer } else
535 1.3.2.2 bouyer bp->b_resid = 0;
536 1.3.2.2 bouyer #else
537 1.3.2.2 bouyer }
538 1.3.2.2 bouyer bp->b_resid = bp->b_bcount - le32toh(rb->transfercount);
539 1.3.2.2 bouyer #endif
540 1.3.2.2 bouyer
541 1.3.2.2 bouyer iop_msg_unmap(iop, im);
542 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
543 1.3.2.2 bouyer lddone(&sc->sc_ld, bp);
544 1.3.2.2 bouyer }
545 1.3.2.2 bouyer
546 1.3.2.2 bouyer static void
547 1.3.2.2 bouyer ld_iop_intr_event(struct device *dv, struct iop_msg *im, void *reply)
548 1.3.2.2 bouyer {
549 1.3.2.2 bouyer struct i2o_util_event_register_reply *rb;
550 1.3.2.2 bouyer u_int event;
551 1.3.2.2 bouyer
552 1.3.2.2 bouyer rb = reply;
553 1.3.2.2 bouyer event = le32toh(rb->event);
554 1.3.2.2 bouyer
555 1.3.2.2 bouyer #ifndef I2ODEBUG
556 1.3.2.2 bouyer if (event == I2O_EVENT_GEN_EVENT_MASK_MODIFIED)
557 1.3.2.2 bouyer return;
558 1.3.2.2 bouyer #endif
559 1.3.2.2 bouyer
560 1.3.2.2 bouyer printf("%s: event 0x%08x received\n", dv->dv_xname, event);
561 1.3.2.2 bouyer }
562