ld_iop.c revision 1.3.2.2 1 1.3.2.2 bouyer /* $NetBSD: ld_iop.c,v 1.3.2.2 2000/12/08 09:12:19 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.2 bouyer int s, 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.2 bouyer /* XXX */
340 1.3.2.2 bouyer if ((flags & DETACH_FORCE) == 0 && sc->sc_ld.sc_dk.dk_openmask != 0)
341 1.3.2.2 bouyer return (EBUSY);
342 1.3.2.2 bouyer s = splbio();
343 1.3.2.2 bouyer sc->sc_ld.sc_flags |= LDF_DRAIN;
344 1.3.2.2 bouyer splx(s);
345 1.3.2.2 bouyer
346 1.3.2.2 bouyer iop = (struct iop_softc *)self->dv_parent;
347 1.3.2.2 bouyer
348 1.3.2.2 bouyer /*
349 1.3.2.2 bouyer * Abort any requests queued with the IOP, but allow requests that
350 1.3.2.2 bouyer * are already in progress to complete.
351 1.3.2.2 bouyer */
352 1.3.2.2 bouyer if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0)
353 1.3.2.2 bouyer iop_util_abort(iop, &sc->sc_ii, 0, 0,
354 1.3.2.2 bouyer I2O_UTIL_ABORT_WILD | I2O_UTIL_ABORT_CLEAN);
355 1.3.2.2 bouyer
356 1.3.2.2 bouyer lddetach(&sc->sc_ld);
357 1.3.2.2 bouyer
358 1.3.2.2 bouyer /* Un-claim the target, and un-register us as an initiator. */
359 1.3.2.2 bouyer if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0) {
360 1.3.2.2 bouyer if (sc->sc_claimed) {
361 1.3.2.2 bouyer rv = iop_util_claim(iop, &sc->sc_ii, 1,
362 1.3.2.2 bouyer I2O_UTIL_CLAIM_PRIMARY_USER);
363 1.3.2.2 bouyer if (rv != 0)
364 1.3.2.2 bouyer return (rv);
365 1.3.2.2 bouyer }
366 1.3.2.2 bouyer iop_util_eventreg(iop, &sc->sc_eventii, 0);
367 1.3.2.2 bouyer iop_initiator_unregister(iop, &sc->sc_eventii);
368 1.3.2.2 bouyer iop_initiator_unregister(iop, &sc->sc_ii);
369 1.3.2.2 bouyer }
370 1.3.2.2 bouyer
371 1.3.2.2 bouyer return (0);
372 1.3.2.2 bouyer }
373 1.3.2.2 bouyer
374 1.3.2.2 bouyer static int
375 1.3.2.2 bouyer ld_iop_start(struct ld_softc *ld, struct buf *bp)
376 1.3.2.2 bouyer {
377 1.3.2.2 bouyer struct iop_msg *im;
378 1.3.2.2 bouyer struct iop_softc *iop;
379 1.3.2.2 bouyer struct ld_iop_softc *sc;
380 1.3.2.2 bouyer struct i2o_rbs_block_read *mb;
381 1.3.2.2 bouyer int rv, flags, write;
382 1.3.2.2 bouyer u_int64_t ba;
383 1.3.2.2 bouyer
384 1.3.2.2 bouyer sc = (struct ld_iop_softc *)ld;
385 1.3.2.2 bouyer iop = (struct iop_softc *)ld->sc_dv.dv_parent;
386 1.3.2.2 bouyer
387 1.3.2.2 bouyer im = NULL;
388 1.3.2.2 bouyer if ((rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT)) != 0)
389 1.3.2.2 bouyer goto bad;
390 1.3.2.2 bouyer im->im_dvcontext = bp;
391 1.3.2.2 bouyer
392 1.3.2.2 bouyer write = ((bp->b_flags & B_READ) == 0);
393 1.3.2.2 bouyer ba = (u_int64_t)bp->b_rawblkno * ld->sc_secsize;
394 1.3.2.2 bouyer
395 1.3.2.2 bouyer /*
396 1.3.2.2 bouyer * Write through the cache when performing synchronous writes. When
397 1.3.2.2 bouyer * performing a read, we don't request that the DDM cache the data,
398 1.3.2.2 bouyer * as there's little advantage to it.
399 1.3.2.2 bouyer */
400 1.3.2.2 bouyer if (write) {
401 1.3.2.2 bouyer if ((bp->b_flags & B_ASYNC) == 0)
402 1.3.2.2 bouyer flags = I2O_RBS_BLOCK_WRITE_CACHE_WT;
403 1.3.2.2 bouyer else
404 1.3.2.2 bouyer flags = I2O_RBS_BLOCK_WRITE_CACHE_WB;
405 1.3.2.2 bouyer } else
406 1.3.2.2 bouyer flags = 0;
407 1.3.2.2 bouyer
408 1.3.2.2 bouyer /*
409 1.3.2.2 bouyer * Fill the message frame. We can use the block_read structure for
410 1.3.2.2 bouyer * both reads and writes, as it's almost identical to the
411 1.3.2.2 bouyer * block_write structure.
412 1.3.2.2 bouyer */
413 1.3.2.2 bouyer mb = (struct i2o_rbs_block_read *)im->im_msg;
414 1.3.2.2 bouyer mb->msgflags = I2O_MSGFLAGS(i2o_rbs_block_read);
415 1.3.2.2 bouyer mb->msgfunc = I2O_MSGFUNC(sc->sc_tid,
416 1.3.2.2 bouyer write ? I2O_RBS_BLOCK_WRITE : I2O_RBS_BLOCK_READ);
417 1.3.2.2 bouyer mb->msgictx = sc->sc_ii.ii_ictx;
418 1.3.2.2 bouyer mb->msgtctx = im->im_tctx;
419 1.3.2.2 bouyer mb->flags = flags | (1 << 16); /* flags & time multiplier */
420 1.3.2.2 bouyer mb->datasize = bp->b_bcount;
421 1.3.2.2 bouyer mb->lowoffset = (u_int32_t)ba;
422 1.3.2.2 bouyer mb->highoffset = (u_int32_t)(ba >> 32);
423 1.3.2.2 bouyer
424 1.3.2.2 bouyer /* Map the data transfer. */
425 1.3.2.2 bouyer if ((rv = iop_msg_map(iop, im, bp->b_data, bp->b_bcount, write)) != 0)
426 1.3.2.2 bouyer goto bad;
427 1.3.2.2 bouyer
428 1.3.2.2 bouyer /* Enqueue the command. */
429 1.3.2.2 bouyer iop_msg_enqueue(iop, im, 0);
430 1.3.2.2 bouyer return (0);
431 1.3.2.2 bouyer
432 1.3.2.2 bouyer bad:
433 1.3.2.2 bouyer if (im != NULL)
434 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
435 1.3.2.2 bouyer return (rv);
436 1.3.2.2 bouyer }
437 1.3.2.2 bouyer
438 1.3.2.2 bouyer static int
439 1.3.2.2 bouyer ld_iop_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt)
440 1.3.2.2 bouyer {
441 1.3.2.2 bouyer struct iop_msg *im;
442 1.3.2.2 bouyer struct iop_softc *iop;
443 1.3.2.2 bouyer struct ld_iop_softc *sc;
444 1.3.2.2 bouyer struct i2o_rbs_block_write *mb;
445 1.3.2.2 bouyer int rv, bcount;
446 1.3.2.2 bouyer u_int64_t ba;
447 1.3.2.2 bouyer
448 1.3.2.2 bouyer sc = (struct ld_iop_softc *)ld;
449 1.3.2.2 bouyer iop = (struct iop_softc *)ld->sc_dv.dv_parent;
450 1.3.2.2 bouyer bcount = blkcnt * ld->sc_secsize;
451 1.3.2.2 bouyer ba = (u_int64_t)blkno * ld->sc_secsize;
452 1.3.2.2 bouyer
453 1.3.2.2 bouyer rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT | IM_NOINTR);
454 1.3.2.2 bouyer if (rv != 0)
455 1.3.2.2 bouyer return (rv);
456 1.3.2.2 bouyer
457 1.3.2.2 bouyer mb = (struct i2o_rbs_block_write *)im->im_msg;
458 1.3.2.2 bouyer mb->msgflags = I2O_MSGFLAGS(i2o_rbs_block_write);
459 1.3.2.2 bouyer mb->msgfunc = I2O_MSGFUNC(sc->sc_tid, I2O_RBS_BLOCK_WRITE);
460 1.3.2.2 bouyer mb->msgictx = sc->sc_ii.ii_ictx;
461 1.3.2.2 bouyer mb->msgtctx = im->im_tctx;
462 1.3.2.2 bouyer mb->flags = I2O_RBS_BLOCK_WRITE_CACHE_WT | (1 << 16);
463 1.3.2.2 bouyer mb->datasize = bcount;
464 1.3.2.2 bouyer mb->lowoffset = (u_int32_t)ba;
465 1.3.2.2 bouyer mb->highoffset = (u_int32_t)(ba >> 32);
466 1.3.2.2 bouyer
467 1.3.2.2 bouyer if ((rv = iop_msg_map(iop, im, data, bcount, 1)) != 0) {
468 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
469 1.3.2.2 bouyer return (rv);
470 1.3.2.2 bouyer }
471 1.3.2.2 bouyer
472 1.3.2.2 bouyer rv = (iop_msg_send(iop, im, 5000) != 0 ? EIO : 0);
473 1.3.2.2 bouyer iop_msg_unmap(iop, im);
474 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
475 1.3.2.2 bouyer return (rv);
476 1.3.2.2 bouyer }
477 1.3.2.2 bouyer
478 1.3.2.2 bouyer static int
479 1.3.2.2 bouyer ld_iop_flush(struct ld_softc *ld)
480 1.3.2.2 bouyer {
481 1.3.2.2 bouyer struct iop_msg *im;
482 1.3.2.2 bouyer struct iop_softc *iop;
483 1.3.2.2 bouyer struct ld_iop_softc *sc;
484 1.3.2.2 bouyer struct i2o_rbs_cache_flush *mb;
485 1.3.2.2 bouyer int rv;
486 1.3.2.2 bouyer
487 1.3.2.2 bouyer sc = (struct ld_iop_softc *)ld;
488 1.3.2.2 bouyer iop = (struct iop_softc *)ld->sc_dv.dv_parent;
489 1.3.2.2 bouyer
490 1.3.2.2 bouyer rv = iop_msg_alloc(iop, &sc->sc_ii, &im, IM_NOWAIT | IM_NOINTR);
491 1.3.2.2 bouyer if (rv != 0)
492 1.3.2.2 bouyer return (rv);
493 1.3.2.2 bouyer
494 1.3.2.2 bouyer mb = (struct i2o_rbs_cache_flush *)im->im_msg;
495 1.3.2.2 bouyer mb->msgflags = I2O_MSGFLAGS(i2o_rbs_cache_flush);
496 1.3.2.2 bouyer mb->msgfunc = I2O_MSGFUNC(sc->sc_tid, I2O_RBS_CACHE_FLUSH);
497 1.3.2.2 bouyer mb->msgictx = sc->sc_ii.ii_ictx;
498 1.3.2.2 bouyer mb->msgtctx = im->im_tctx;
499 1.3.2.2 bouyer mb->flags = 1 << 16; /* time multiplier */
500 1.3.2.2 bouyer
501 1.3.2.2 bouyer rv = iop_msg_send(iop, im, 10000);
502 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
503 1.3.2.2 bouyer return (rv);
504 1.3.2.2 bouyer }
505 1.3.2.2 bouyer
506 1.3.2.2 bouyer void
507 1.3.2.2 bouyer ld_iop_intr(struct device *dv, struct iop_msg *im, void *reply)
508 1.3.2.2 bouyer {
509 1.3.2.2 bouyer struct i2o_rbs_reply *rb;
510 1.3.2.2 bouyer struct buf *bp;
511 1.3.2.2 bouyer struct ld_iop_softc *sc;
512 1.3.2.2 bouyer struct iop_softc *iop;
513 1.3.2.2 bouyer #ifdef I2OVERBOSE
514 1.3.2.2 bouyer int detail;
515 1.3.2.2 bouyer const char *errstr;
516 1.3.2.2 bouyer #endif
517 1.3.2.2 bouyer
518 1.3.2.2 bouyer rb = reply;
519 1.3.2.2 bouyer bp = im->im_dvcontext;
520 1.3.2.2 bouyer sc = (struct ld_iop_softc *)dv;
521 1.3.2.2 bouyer iop = (struct iop_softc *)dv->dv_parent;
522 1.3.2.2 bouyer
523 1.3.2.2 bouyer #ifdef I2OVERBOSE
524 1.3.2.2 bouyer if (rb->reqstatus != I2O_STATUS_SUCCESS) {
525 1.3.2.2 bouyer detail = le16toh(rb->detail);
526 1.3.2.2 bouyer if (detail > sizeof(ld_iop_errors) / sizeof(ld_iop_errors[0]))
527 1.3.2.2 bouyer errstr = "unknown error";
528 1.3.2.2 bouyer else
529 1.3.2.2 bouyer errstr = ld_iop_errors[detail];
530 1.3.2.2 bouyer printf("%s: %s\n", dv->dv_xname, errstr);
531 1.3.2.2 bouyer #else
532 1.3.2.2 bouyer if (rb->reqstatus != I2O_STATUS_SUCCESS) {
533 1.3.2.2 bouyer #endif
534 1.3.2.2 bouyer bp->b_flags |= B_ERROR;
535 1.3.2.2 bouyer bp->b_error = EIO;
536 1.3.2.2 bouyer #ifndef notyet
537 1.3.2.2 bouyer bp->b_resid = bp->b_bcount;
538 1.3.2.2 bouyer } else
539 1.3.2.2 bouyer bp->b_resid = 0;
540 1.3.2.2 bouyer #else
541 1.3.2.2 bouyer }
542 1.3.2.2 bouyer bp->b_resid = bp->b_bcount - le32toh(rb->transfercount);
543 1.3.2.2 bouyer #endif
544 1.3.2.2 bouyer
545 1.3.2.2 bouyer iop_msg_unmap(iop, im);
546 1.3.2.2 bouyer iop_msg_free(iop, &sc->sc_ii, im);
547 1.3.2.2 bouyer lddone(&sc->sc_ld, bp);
548 1.3.2.2 bouyer }
549 1.3.2.2 bouyer
550 1.3.2.2 bouyer static void
551 1.3.2.2 bouyer ld_iop_intr_event(struct device *dv, struct iop_msg *im, void *reply)
552 1.3.2.2 bouyer {
553 1.3.2.2 bouyer struct i2o_util_event_register_reply *rb;
554 1.3.2.2 bouyer u_int event;
555 1.3.2.2 bouyer
556 1.3.2.2 bouyer rb = reply;
557 1.3.2.2 bouyer event = le32toh(rb->event);
558 1.3.2.2 bouyer
559 1.3.2.2 bouyer #ifndef I2ODEBUG
560 1.3.2.2 bouyer if (event == I2O_EVENT_GEN_EVENT_MASK_MODIFIED)
561 1.3.2.2 bouyer return;
562 1.3.2.2 bouyer #endif
563 1.3.2.2 bouyer
564 1.3.2.2 bouyer printf("%s: event 0x%08x received\n", dv->dv_xname, event);
565 1.3.2.2 bouyer }
566