ld_iop.c revision 1.3.2.5 1 1.3.2.5 bouyer /* $NetBSD: ld_iop.c,v 1.3.2.5 2001/03/27 15:31:52 bouyer Exp $ */
2 1.3.2.2 bouyer
3 1.3.2.2 bouyer /*-
4 1.3.2.5 bouyer * Copyright (c) 2000, 2001 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.5 bouyer #include <dev/i2o/iopio.h>
67 1.3.2.2 bouyer #include <dev/i2o/iopvar.h>
68 1.3.2.2 bouyer
69 1.3.2.5 bouyer #define LD_IOP_TIMEOUT 30*1000
70 1.3.2.5 bouyer
71 1.3.2.5 bouyer #define LD_IOP_CLAIMED 0x01
72 1.3.2.5 bouyer #define LD_IOP_NEW_EVTMASK 0x02
73 1.3.2.2 bouyer
74 1.3.2.2 bouyer struct ld_iop_softc {
75 1.3.2.2 bouyer struct ld_softc sc_ld;
76 1.3.2.2 bouyer struct iop_initiator sc_ii;
77 1.3.2.2 bouyer struct iop_initiator sc_eventii;
78 1.3.2.5 bouyer int sc_flags;
79 1.3.2.2 bouyer };
80 1.3.2.2 bouyer
81 1.3.2.5 bouyer static void ld_iop_adjqparam(struct device *, int);
82 1.3.2.2 bouyer static void ld_iop_attach(struct device *, struct device *, void *);
83 1.3.2.2 bouyer static int ld_iop_detach(struct device *, int);
84 1.3.2.2 bouyer static int ld_iop_dump(struct ld_softc *, void *, int, int);
85 1.3.2.2 bouyer static int ld_iop_flush(struct ld_softc *);
86 1.3.2.2 bouyer static void ld_iop_intr(struct device *, struct iop_msg *, void *);
87 1.3.2.2 bouyer static void ld_iop_intr_event(struct device *, struct iop_msg *, void *);
88 1.3.2.2 bouyer static int ld_iop_match(struct device *, struct cfdata *, void *);
89 1.3.2.5 bouyer static int ld_iop_start(struct ld_softc *, struct buf *);
90 1.3.2.5 bouyer static void ld_iop_unconfig(struct ld_iop_softc *, int);
91 1.3.2.2 bouyer
92 1.3.2.2 bouyer struct cfattach ld_iop_ca = {
93 1.3.2.2 bouyer sizeof(struct ld_iop_softc),
94 1.3.2.2 bouyer ld_iop_match,
95 1.3.2.2 bouyer ld_iop_attach,
96 1.3.2.2 bouyer ld_iop_detach
97 1.3.2.2 bouyer };
98 1.3.2.2 bouyer
99 1.3.2.2 bouyer #ifdef I2OVERBOSE
100 1.3.2.5 bouyer static const char * const ld_iop_errors[] = {
101 1.3.2.2 bouyer "success",
102 1.3.2.2 bouyer "media error",
103 1.3.2.5 bouyer "access error",
104 1.3.2.2 bouyer "device failure",
105 1.3.2.5 bouyer "device not ready",
106 1.3.2.2 bouyer "media not present",
107 1.3.2.5 bouyer "media locked",
108 1.3.2.2 bouyer "media failure",
109 1.3.2.5 bouyer "protocol failure",
110 1.3.2.5 bouyer "bus failure",
111 1.3.2.5 bouyer "access violation",
112 1.3.2.5 bouyer "media write protected",
113 1.3.2.2 bouyer "device reset",
114 1.3.2.5 bouyer "volume changed, waiting for acknowledgement",
115 1.3.2.5 bouyer "timeout",
116 1.3.2.2 bouyer };
117 1.3.2.2 bouyer #endif
118 1.3.2.2 bouyer
119 1.3.2.2 bouyer static int
120 1.3.2.2 bouyer ld_iop_match(struct device *parent, struct cfdata *match, void *aux)
121 1.3.2.2 bouyer {
122 1.3.2.2 bouyer struct iop_attach_args *ia;
123 1.3.2.2 bouyer
124 1.3.2.2 bouyer ia = aux;
125 1.3.2.2 bouyer
126 1.3.2.2 bouyer return (ia->ia_class == I2O_CLASS_RANDOM_BLOCK_STORAGE);
127 1.3.2.2 bouyer }
128 1.3.2.2 bouyer
129 1.3.2.2 bouyer static void
130 1.3.2.2 bouyer ld_iop_attach(struct device *parent, struct device *self, void *aux)
131 1.3.2.2 bouyer {
132 1.3.2.2 bouyer struct iop_attach_args *ia;
133 1.3.2.2 bouyer struct ld_softc *ld;
134 1.3.2.2 bouyer struct ld_iop_softc *sc;
135 1.3.2.2 bouyer struct iop_softc *iop;
136 1.3.2.2 bouyer int rv, evreg, enable;
137 1.3.2.5 bouyer char *typestr, *fixedstr;
138 1.3.2.2 bouyer u_int cachesz;
139 1.3.2.2 bouyer struct {
140 1.3.2.2 bouyer struct i2o_param_op_results pr;
141 1.3.2.2 bouyer struct i2o_param_read_results prr;
142 1.3.2.2 bouyer union {
143 1.3.2.2 bouyer struct i2o_param_rbs_cache_control cc;
144 1.3.2.2 bouyer struct i2o_param_rbs_device_info bdi;
145 1.3.2.2 bouyer struct i2o_param_rbs_operation op;
146 1.3.2.2 bouyer } p;
147 1.3.2.5 bouyer } param /* XXX gcc __attribute__ ((__packed__)) */;
148 1.3.2.2 bouyer
149 1.3.2.2 bouyer sc = (struct ld_iop_softc *)self;
150 1.3.2.2 bouyer ld = &sc->sc_ld;
151 1.3.2.2 bouyer iop = (struct iop_softc *)parent;
152 1.3.2.2 bouyer ia = (struct iop_attach_args *)aux;
153 1.3.2.2 bouyer evreg = 0;
154 1.3.2.2 bouyer
155 1.3.2.2 bouyer /* Register us as an initiator. */
156 1.3.2.2 bouyer sc->sc_ii.ii_dv = self;
157 1.3.2.2 bouyer sc->sc_ii.ii_intr = ld_iop_intr;
158 1.3.2.5 bouyer sc->sc_ii.ii_adjqparam = ld_iop_adjqparam;
159 1.3.2.2 bouyer sc->sc_ii.ii_flags = 0;
160 1.3.2.2 bouyer sc->sc_ii.ii_tid = ia->ia_tid;
161 1.3.2.5 bouyer iop_initiator_register(iop, &sc->sc_ii);
162 1.3.2.2 bouyer
163 1.3.2.2 bouyer /* Register another initiator to handle events from the device. */
164 1.3.2.2 bouyer sc->sc_eventii.ii_dv = self;
165 1.3.2.2 bouyer sc->sc_eventii.ii_intr = ld_iop_intr_event;
166 1.3.2.2 bouyer sc->sc_eventii.ii_flags = II_DISCARD | II_UTILITY;
167 1.3.2.2 bouyer sc->sc_eventii.ii_tid = ia->ia_tid;
168 1.3.2.5 bouyer iop_initiator_register(iop, &sc->sc_eventii);
169 1.3.2.5 bouyer
170 1.3.2.5 bouyer rv = iop_util_eventreg(iop, &sc->sc_eventii,
171 1.3.2.5 bouyer I2O_EVENT_GEN_EVENT_MASK_MODIFIED |
172 1.3.2.5 bouyer I2O_EVENT_GEN_DEVICE_RESET |
173 1.3.2.5 bouyer I2O_EVENT_GEN_STATE_CHANGE |
174 1.3.2.5 bouyer I2O_EVENT_GEN_GENERAL_WARNING);
175 1.3.2.5 bouyer if (rv != 0) {
176 1.3.2.2 bouyer printf("%s: unable to register for events", self->dv_xname);
177 1.3.2.2 bouyer goto bad;
178 1.3.2.2 bouyer }
179 1.3.2.2 bouyer evreg = 1;
180 1.3.2.2 bouyer
181 1.3.2.5 bouyer /*
182 1.3.2.5 bouyer * Start out with one queued command. The `iop' driver will adjust
183 1.3.2.5 bouyer * the queue parameters once we're up and running.
184 1.3.2.5 bouyer */
185 1.3.2.5 bouyer ld->sc_maxqueuecnt = 1;
186 1.3.2.5 bouyer
187 1.3.2.2 bouyer ld->sc_maxxfer = IOP_MAX_XFER;
188 1.3.2.2 bouyer ld->sc_dump = ld_iop_dump;
189 1.3.2.2 bouyer ld->sc_flush = ld_iop_flush;
190 1.3.2.2 bouyer ld->sc_start = ld_iop_start;
191 1.3.2.2 bouyer
192 1.3.2.2 bouyer /* Say what the device is. */
193 1.3.2.5 bouyer printf(":");
194 1.3.2.5 bouyer iop_print_ident(iop, ia->ia_tid);
195 1.3.2.2 bouyer
196 1.3.2.2 bouyer /*
197 1.3.2.2 bouyer * Claim the device so that we don't get any nasty surprises. Allow
198 1.3.2.2 bouyer * failure.
199 1.3.2.2 bouyer */
200 1.3.2.5 bouyer rv = iop_util_claim(iop, &sc->sc_ii, 0,
201 1.3.2.2 bouyer I2O_UTIL_CLAIM_CAPACITY_SENSITIVE |
202 1.3.2.2 bouyer I2O_UTIL_CLAIM_NO_PEER_SERVICE |
203 1.3.2.2 bouyer I2O_UTIL_CLAIM_NO_MANAGEMENT_SERVICE |
204 1.3.2.2 bouyer I2O_UTIL_CLAIM_PRIMARY_USER);
205 1.3.2.5 bouyer sc->sc_flags = rv ? 0 : LD_IOP_CLAIMED;
206 1.3.2.2 bouyer
207 1.3.2.5 bouyer rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_RBS_DEVICE_INFO,
208 1.3.2.2 bouyer ¶m, sizeof(param));
209 1.3.2.2 bouyer if (rv != 0) {
210 1.3.2.2 bouyer printf("%s: unable to get parameters (0x%04x; %d)\n",
211 1.3.2.2 bouyer ld->sc_dv.dv_xname, I2O_PARAM_RBS_DEVICE_INFO, rv);
212 1.3.2.2 bouyer goto bad;
213 1.3.2.2 bouyer }
214 1.3.2.2 bouyer
215 1.3.2.2 bouyer ld->sc_secsize = le32toh(param.p.bdi.blocksize);
216 1.3.2.2 bouyer ld->sc_secperunit = (int)
217 1.3.2.2 bouyer (le64toh(param.p.bdi.capacity) / ld->sc_secsize);
218 1.3.2.2 bouyer
219 1.3.2.2 bouyer /* Build synthetic geometry. */
220 1.3.2.2 bouyer if (ld->sc_secperunit <= 528 * 2048) /* 528MB */
221 1.3.2.2 bouyer ld->sc_nheads = 16;
222 1.3.2.2 bouyer else if (ld->sc_secperunit <= 1024 * 2048) /* 1GB */
223 1.3.2.2 bouyer ld->sc_nheads = 32;
224 1.3.2.2 bouyer else if (ld->sc_secperunit <= 21504 * 2048) /* 21GB */
225 1.3.2.2 bouyer ld->sc_nheads = 64;
226 1.3.2.2 bouyer else if (ld->sc_secperunit <= 43008 * 2048) /* 42GB */
227 1.3.2.2 bouyer ld->sc_nheads = 128;
228 1.3.2.2 bouyer else
229 1.3.2.2 bouyer ld->sc_nheads = 255;
230 1.3.2.2 bouyer
231 1.3.2.2 bouyer ld->sc_nsectors = 63;
232 1.3.2.2 bouyer ld->sc_ncylinders = ld->sc_secperunit /
233 1.3.2.2 bouyer (ld->sc_nheads * ld->sc_nsectors);
234 1.3.2.2 bouyer
235 1.3.2.2 bouyer switch (param.p.bdi.type) {
236 1.3.2.2 bouyer case I2O_RBS_TYPE_DIRECT:
237 1.3.2.2 bouyer typestr = "direct access";
238 1.3.2.2 bouyer enable = 1;
239 1.3.2.2 bouyer break;
240 1.3.2.2 bouyer case I2O_RBS_TYPE_WORM:
241 1.3.2.2 bouyer typestr = "WORM";
242 1.3.2.2 bouyer enable = 0;
243 1.3.2.2 bouyer break;
244 1.3.2.2 bouyer case I2O_RBS_TYPE_CDROM:
245 1.3.2.5 bouyer typestr = "CD-ROM";
246 1.3.2.2 bouyer enable = 0;
247 1.3.2.2 bouyer break;
248 1.3.2.2 bouyer case I2O_RBS_TYPE_OPTICAL:
249 1.3.2.2 bouyer typestr = "optical";
250 1.3.2.2 bouyer enable = 0;
251 1.3.2.2 bouyer break;
252 1.3.2.2 bouyer default:
253 1.3.2.2 bouyer typestr = "unknown";
254 1.3.2.2 bouyer enable = 0;
255 1.3.2.2 bouyer break;
256 1.3.2.2 bouyer }
257 1.3.2.2 bouyer
258 1.3.2.2 bouyer if ((le32toh(param.p.bdi.capabilities) & I2O_RBS_CAP_REMOVEABLE_MEDIA)
259 1.3.2.2 bouyer != 0) {
260 1.3.2.2 bouyer /* ld->sc_flags = LDF_REMOVEABLE; */
261 1.3.2.2 bouyer fixedstr = "removeable";
262 1.3.2.2 bouyer enable = 0;
263 1.3.2.2 bouyer } else
264 1.3.2.2 bouyer fixedstr = "fixed";
265 1.3.2.2 bouyer
266 1.3.2.5 bouyer printf(" %s, %s", typestr, fixedstr);
267 1.3.2.2 bouyer
268 1.3.2.2 bouyer /*
269 1.3.2.2 bouyer * Determine if the device has an private cache. If so, print the
270 1.3.2.2 bouyer * cache size. Even if the device doesn't appear to have a cache,
271 1.3.2.5 bouyer * we perform a flush at shutdown.
272 1.3.2.2 bouyer */
273 1.3.2.5 bouyer rv = iop_param_op(iop, ia->ia_tid, NULL, 0,
274 1.3.2.5 bouyer I2O_PARAM_RBS_CACHE_CONTROL, ¶m, sizeof(param));
275 1.3.2.2 bouyer if (rv != 0) {
276 1.3.2.2 bouyer printf("%s: unable to get parameters (0x%04x; %d)\n",
277 1.3.2.2 bouyer ld->sc_dv.dv_xname, I2O_PARAM_RBS_CACHE_CONTROL, rv);
278 1.3.2.2 bouyer goto bad;
279 1.3.2.2 bouyer }
280 1.3.2.2 bouyer
281 1.3.2.2 bouyer if ((cachesz = le32toh(param.p.cc.totalcachesize)) != 0)
282 1.3.2.2 bouyer printf(", %dkB cache", cachesz >> 10);
283 1.3.2.2 bouyer
284 1.3.2.2 bouyer printf("\n");
285 1.3.2.2 bouyer
286 1.3.2.2 bouyer /*
287 1.3.2.2 bouyer * Configure the DDM's timeout functions to time out all commands
288 1.3.2.5 bouyer * after 30 seconds.
289 1.3.2.2 bouyer */
290 1.3.2.5 bouyer rv = iop_param_op(iop, ia->ia_tid, NULL, 0, I2O_PARAM_RBS_OPERATION,
291 1.3.2.2 bouyer ¶m, sizeof(param));
292 1.3.2.2 bouyer if (rv != 0) {
293 1.3.2.2 bouyer printf("%s: unable to get parameters (0x%04x; %d)\n",
294 1.3.2.2 bouyer ld->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
295 1.3.2.2 bouyer goto bad;
296 1.3.2.2 bouyer }
297 1.3.2.2 bouyer
298 1.3.2.5 bouyer param.p.op.timeoutbase = htole32(LD_IOP_TIMEOUT * 1000);
299 1.3.2.5 bouyer param.p.op.rwvtimeoutbase = htole32(LD_IOP_TIMEOUT * 1000);
300 1.3.2.2 bouyer param.p.op.rwvtimeout = 0;
301 1.3.2.2 bouyer
302 1.3.2.5 bouyer rv = iop_param_op(iop, ia->ia_tid, NULL, 1, I2O_PARAM_RBS_OPERATION,
303 1.3.2.2 bouyer ¶m, sizeof(param));
304 1.3.2.5 bouyer #ifdef notdef
305 1.3.2.5 bouyer /*
306 1.3.2.5 bouyer * Intel RAID adapters don't like the above, but do post a
307 1.3.2.5 bouyer * `parameter changed' event. Perhaps we're doing something
308 1.3.2.5 bouyer * wrong...
309 1.3.2.5 bouyer */
310 1.3.2.2 bouyer if (rv != 0) {
311 1.3.2.2 bouyer printf("%s: unable to set parameters (0x%04x; %d)\n",
312 1.3.2.2 bouyer ld->sc_dv.dv_xname, I2O_PARAM_RBS_OPERATION, rv);
313 1.3.2.2 bouyer goto bad;
314 1.3.2.2 bouyer }
315 1.3.2.5 bouyer #endif
316 1.3.2.2 bouyer
317 1.3.2.2 bouyer if (enable)
318 1.3.2.2 bouyer ld->sc_flags |= LDF_ENABLED;
319 1.3.2.2 bouyer else
320 1.3.2.2 bouyer printf("%s: device not yet supported\n", self->dv_xname);
321 1.3.2.2 bouyer
322 1.3.2.2 bouyer ldattach(ld);
323 1.3.2.2 bouyer return;
324 1.3.2.2 bouyer
325 1.3.2.5 bouyer bad:
326 1.3.2.5 bouyer ld_iop_unconfig(sc, evreg);
327 1.3.2.5 bouyer }
328 1.3.2.5 bouyer
329 1.3.2.5 bouyer static void
330 1.3.2.5 bouyer ld_iop_unconfig(struct ld_iop_softc *sc, int evreg)
331 1.3.2.5 bouyer {
332 1.3.2.5 bouyer struct iop_softc *iop;
333 1.3.2.5 bouyer int s;
334 1.3.2.5 bouyer
335 1.3.2.5 bouyer iop = (struct iop_softc *)sc->sc_ld.sc_dv.dv_parent;
336 1.3.2.5 bouyer
337 1.3.2.5 bouyer if ((sc->sc_flags & LD_IOP_CLAIMED) != 0)
338 1.3.2.2 bouyer iop_util_claim(iop, &sc->sc_ii, 1,
339 1.3.2.2 bouyer I2O_UTIL_CLAIM_PRIMARY_USER);
340 1.3.2.5 bouyer
341 1.3.2.5 bouyer if (evreg) {
342 1.3.2.5 bouyer /*
343 1.3.2.5 bouyer * Mask off events, and wait up to 5 seconds for a reply.
344 1.3.2.5 bouyer * Note that some adapters won't reply to this (XXX We
345 1.3.2.5 bouyer * should check the event capabilities).
346 1.3.2.5 bouyer */
347 1.3.2.5 bouyer sc->sc_flags &= ~LD_IOP_NEW_EVTMASK;
348 1.3.2.5 bouyer iop_util_eventreg(iop, &sc->sc_eventii,
349 1.3.2.5 bouyer I2O_EVENT_GEN_EVENT_MASK_MODIFIED);
350 1.3.2.5 bouyer s = splbio();
351 1.3.2.5 bouyer if ((sc->sc_flags & LD_IOP_NEW_EVTMASK) == 0)
352 1.3.2.5 bouyer tsleep(&sc->sc_eventii, PRIBIO, "ld_iopevt", hz * 5);
353 1.3.2.5 bouyer splx(s);
354 1.3.2.5 bouyer #ifdef I2ODEBUG
355 1.3.2.5 bouyer if ((sc->sc_flags & LD_IOP_NEW_EVTMASK) == 0)
356 1.3.2.5 bouyer printf("%s: didn't reply to event unregister",
357 1.3.2.5 bouyer sc->sc_ld.sc_dv.dv_xname);
358 1.3.2.5 bouyer #endif
359 1.3.2.5 bouyer }
360 1.3.2.5 bouyer
361 1.3.2.5 bouyer iop_initiator_unregister(iop, &sc->sc_eventii);
362 1.3.2.2 bouyer iop_initiator_unregister(iop, &sc->sc_ii);
363 1.3.2.2 bouyer }
364 1.3.2.2 bouyer
365 1.3.2.2 bouyer static int
366 1.3.2.2 bouyer ld_iop_detach(struct device *self, int flags)
367 1.3.2.2 bouyer {
368 1.3.2.2 bouyer struct ld_iop_softc *sc;
369 1.3.2.2 bouyer struct iop_softc *iop;
370 1.3.2.3 bouyer int rv;
371 1.3.2.2 bouyer
372 1.3.2.2 bouyer sc = (struct ld_iop_softc *)self;
373 1.3.2.5 bouyer iop = (struct iop_softc *)self->dv_parent;
374 1.3.2.2 bouyer
375 1.3.2.4 bouyer if ((rv = ldbegindetach(&sc->sc_ld, flags)) != 0)
376 1.3.2.3 bouyer return (rv);
377 1.3.2.2 bouyer
378 1.3.2.2 bouyer /*
379 1.3.2.2 bouyer * Abort any requests queued with the IOP, but allow requests that
380 1.3.2.2 bouyer * are already in progress to complete.
381 1.3.2.2 bouyer */
382 1.3.2.2 bouyer if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0)
383 1.3.2.2 bouyer iop_util_abort(iop, &sc->sc_ii, 0, 0,
384 1.3.2.2 bouyer I2O_UTIL_ABORT_WILD | I2O_UTIL_ABORT_CLEAN);
385 1.3.2.2 bouyer
386 1.3.2.4 bouyer ldenddetach(&sc->sc_ld);
387 1.3.2.2 bouyer
388 1.3.2.5 bouyer /* Un-claim the target, and un-register our initiators. */
389 1.3.2.5 bouyer if ((sc->sc_ld.sc_flags & LDF_ENABLED) != 0)
390 1.3.2.5 bouyer ld_iop_unconfig(sc, 1);
391 1.3.2.2 bouyer
392 1.3.2.2 bouyer return (0);
393 1.3.2.2 bouyer }
394 1.3.2.2 bouyer
395 1.3.2.2 bouyer static int
396 1.3.2.2 bouyer ld_iop_start(struct ld_softc *ld, struct buf *bp)
397 1.3.2.2 bouyer {
398 1.3.2.2 bouyer struct iop_msg *im;
399 1.3.2.2 bouyer struct iop_softc *iop;
400 1.3.2.2 bouyer struct ld_iop_softc *sc;
401 1.3.2.5 bouyer struct i2o_rbs_block_read *mf;
402 1.3.2.5 bouyer u_int rv, flags, write;
403 1.3.2.2 bouyer u_int64_t ba;
404 1.3.2.5 bouyer u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
405 1.3.2.2 bouyer
406 1.3.2.2 bouyer sc = (struct ld_iop_softc *)ld;
407 1.3.2.2 bouyer iop = (struct iop_softc *)ld->sc_dv.dv_parent;
408 1.3.2.2 bouyer
409 1.3.2.5 bouyer im = iop_msg_alloc(iop, &sc->sc_ii, 0);
410 1.3.2.2 bouyer im->im_dvcontext = bp;
411 1.3.2.2 bouyer
412 1.3.2.2 bouyer write = ((bp->b_flags & B_READ) == 0);
413 1.3.2.2 bouyer ba = (u_int64_t)bp->b_rawblkno * ld->sc_secsize;
414 1.3.2.2 bouyer
415 1.3.2.2 bouyer /*
416 1.3.2.2 bouyer * Write through the cache when performing synchronous writes. When
417 1.3.2.2 bouyer * performing a read, we don't request that the DDM cache the data,
418 1.3.2.2 bouyer * as there's little advantage to it.
419 1.3.2.2 bouyer */
420 1.3.2.2 bouyer if (write) {
421 1.3.2.2 bouyer if ((bp->b_flags & B_ASYNC) == 0)
422 1.3.2.2 bouyer flags = I2O_RBS_BLOCK_WRITE_CACHE_WT;
423 1.3.2.2 bouyer else
424 1.3.2.2 bouyer flags = I2O_RBS_BLOCK_WRITE_CACHE_WB;
425 1.3.2.2 bouyer } else
426 1.3.2.2 bouyer flags = 0;
427 1.3.2.2 bouyer
428 1.3.2.2 bouyer /*
429 1.3.2.2 bouyer * Fill the message frame. We can use the block_read structure for
430 1.3.2.2 bouyer * both reads and writes, as it's almost identical to the
431 1.3.2.2 bouyer * block_write structure.
432 1.3.2.2 bouyer */
433 1.3.2.5 bouyer mf = (struct i2o_rbs_block_read *)mb;
434 1.3.2.5 bouyer mf->msgflags = I2O_MSGFLAGS(i2o_rbs_block_read);
435 1.3.2.5 bouyer mf->msgfunc = I2O_MSGFUNC(sc->sc_ii.ii_tid,
436 1.3.2.2 bouyer write ? I2O_RBS_BLOCK_WRITE : I2O_RBS_BLOCK_READ);
437 1.3.2.5 bouyer mf->msgictx = sc->sc_ii.ii_ictx;
438 1.3.2.5 bouyer mf->msgtctx = im->im_tctx;
439 1.3.2.5 bouyer mf->flags = flags | (1 << 16); /* flags & time multiplier */
440 1.3.2.5 bouyer mf->datasize = bp->b_bcount;
441 1.3.2.5 bouyer mf->lowoffset = (u_int32_t)ba;
442 1.3.2.5 bouyer mf->highoffset = (u_int32_t)(ba >> 32);
443 1.3.2.5 bouyer
444 1.3.2.5 bouyer /* Map the data transfer and enqueue the command. */
445 1.3.2.5 bouyer rv = iop_msg_map_bio(iop, im, mb, bp->b_data, bp->b_bcount, write);
446 1.3.2.5 bouyer if (rv == 0) {
447 1.3.2.5 bouyer if ((rv = iop_msg_post(iop, im, mb, 0)) != 0) {
448 1.3.2.5 bouyer iop_msg_unmap(iop, im);
449 1.3.2.5 bouyer iop_msg_free(iop, im);
450 1.3.2.5 bouyer }
451 1.3.2.5 bouyer }
452 1.3.2.2 bouyer return (rv);
453 1.3.2.2 bouyer }
454 1.3.2.2 bouyer
455 1.3.2.2 bouyer static int
456 1.3.2.2 bouyer ld_iop_dump(struct ld_softc *ld, void *data, int blkno, int blkcnt)
457 1.3.2.2 bouyer {
458 1.3.2.2 bouyer struct iop_msg *im;
459 1.3.2.2 bouyer struct iop_softc *iop;
460 1.3.2.2 bouyer struct ld_iop_softc *sc;
461 1.3.2.5 bouyer struct i2o_rbs_block_write *mf;
462 1.3.2.2 bouyer int rv, bcount;
463 1.3.2.2 bouyer u_int64_t ba;
464 1.3.2.5 bouyer u_int32_t mb[IOP_MAX_MSG_SIZE / sizeof(u_int32_t)];
465 1.3.2.2 bouyer
466 1.3.2.2 bouyer sc = (struct ld_iop_softc *)ld;
467 1.3.2.2 bouyer iop = (struct iop_softc *)ld->sc_dv.dv_parent;
468 1.3.2.2 bouyer bcount = blkcnt * ld->sc_secsize;
469 1.3.2.2 bouyer ba = (u_int64_t)blkno * ld->sc_secsize;
470 1.3.2.5 bouyer im = iop_msg_alloc(iop, &sc->sc_ii, IM_POLL);
471 1.3.2.2 bouyer
472 1.3.2.5 bouyer mf = (struct i2o_rbs_block_write *)mb;
473 1.3.2.5 bouyer mf->msgflags = I2O_MSGFLAGS(i2o_rbs_block_write);
474 1.3.2.5 bouyer mf->msgfunc = I2O_MSGFUNC(sc->sc_ii.ii_tid, I2O_RBS_BLOCK_WRITE);
475 1.3.2.5 bouyer mf->msgictx = sc->sc_ii.ii_ictx;
476 1.3.2.5 bouyer mf->msgtctx = im->im_tctx;
477 1.3.2.5 bouyer mf->flags = I2O_RBS_BLOCK_WRITE_CACHE_WT | (1 << 16);
478 1.3.2.5 bouyer mf->datasize = bcount;
479 1.3.2.5 bouyer mf->lowoffset = (u_int32_t)ba;
480 1.3.2.5 bouyer mf->highoffset = (u_int32_t)(ba >> 32);
481 1.3.2.2 bouyer
482 1.3.2.5 bouyer if ((rv = iop_msg_map(iop, im, mb, data, bcount, 1)) != 0) {
483 1.3.2.5 bouyer iop_msg_free(iop, im);
484 1.3.2.2 bouyer return (rv);
485 1.3.2.2 bouyer }
486 1.3.2.2 bouyer
487 1.3.2.5 bouyer rv = iop_msg_post(iop, im, mb, LD_IOP_TIMEOUT * 2);
488 1.3.2.2 bouyer iop_msg_unmap(iop, im);
489 1.3.2.5 bouyer iop_msg_free(iop, im);
490 1.3.2.2 bouyer return (rv);
491 1.3.2.2 bouyer }
492 1.3.2.2 bouyer
493 1.3.2.2 bouyer static int
494 1.3.2.2 bouyer ld_iop_flush(struct ld_softc *ld)
495 1.3.2.2 bouyer {
496 1.3.2.2 bouyer struct iop_msg *im;
497 1.3.2.2 bouyer struct iop_softc *iop;
498 1.3.2.2 bouyer struct ld_iop_softc *sc;
499 1.3.2.5 bouyer struct i2o_rbs_cache_flush mf;
500 1.3.2.2 bouyer int rv;
501 1.3.2.2 bouyer
502 1.3.2.2 bouyer sc = (struct ld_iop_softc *)ld;
503 1.3.2.2 bouyer iop = (struct iop_softc *)ld->sc_dv.dv_parent;
504 1.3.2.5 bouyer im = iop_msg_alloc(iop, &sc->sc_ii, IM_WAIT);
505 1.3.2.2 bouyer
506 1.3.2.5 bouyer mf.msgflags = I2O_MSGFLAGS(i2o_rbs_cache_flush);
507 1.3.2.5 bouyer mf.msgfunc = I2O_MSGFUNC(sc->sc_ii.ii_tid, I2O_RBS_CACHE_FLUSH);
508 1.3.2.5 bouyer mf.msgictx = sc->sc_ii.ii_ictx;
509 1.3.2.5 bouyer mf.msgtctx = im->im_tctx;
510 1.3.2.5 bouyer mf.flags = 1 << 16; /* time multiplier */
511 1.3.2.2 bouyer
512 1.3.2.5 bouyer /*
513 1.3.2.5 bouyer * XXX Aincent disks will return an error here. Also, we shouldn't
514 1.3.2.5 bouyer * be polling on completion while the system is running.
515 1.3.2.5 bouyer */
516 1.3.2.5 bouyer rv = iop_msg_post(iop, im, &mf, LD_IOP_TIMEOUT * 2);
517 1.3.2.5 bouyer iop_msg_free(iop, im);
518 1.3.2.2 bouyer return (rv);
519 1.3.2.2 bouyer }
520 1.3.2.2 bouyer
521 1.3.2.2 bouyer void
522 1.3.2.2 bouyer ld_iop_intr(struct device *dv, struct iop_msg *im, void *reply)
523 1.3.2.2 bouyer {
524 1.3.2.2 bouyer struct i2o_rbs_reply *rb;
525 1.3.2.2 bouyer struct buf *bp;
526 1.3.2.2 bouyer struct ld_iop_softc *sc;
527 1.3.2.2 bouyer struct iop_softc *iop;
528 1.3.2.5 bouyer int err, detail;
529 1.3.2.2 bouyer #ifdef I2OVERBOSE
530 1.3.2.2 bouyer const char *errstr;
531 1.3.2.2 bouyer #endif
532 1.3.2.2 bouyer
533 1.3.2.2 bouyer rb = reply;
534 1.3.2.2 bouyer bp = im->im_dvcontext;
535 1.3.2.2 bouyer sc = (struct ld_iop_softc *)dv;
536 1.3.2.2 bouyer iop = (struct iop_softc *)dv->dv_parent;
537 1.3.2.2 bouyer
538 1.3.2.5 bouyer err = ((rb->msgflags & I2O_MSGFLAGS_FAIL) != 0);
539 1.3.2.5 bouyer
540 1.3.2.5 bouyer if (!err && rb->reqstatus != I2O_STATUS_SUCCESS) {
541 1.3.2.2 bouyer detail = le16toh(rb->detail);
542 1.3.2.5 bouyer #ifdef I2OVERBOSE
543 1.3.2.2 bouyer if (detail > sizeof(ld_iop_errors) / sizeof(ld_iop_errors[0]))
544 1.3.2.5 bouyer errstr = "<unknown>";
545 1.3.2.2 bouyer else
546 1.3.2.2 bouyer errstr = ld_iop_errors[detail];
547 1.3.2.5 bouyer printf("%s: error 0x%04x: %s\n", dv->dv_xname, detail, errstr);
548 1.3.2.2 bouyer #else
549 1.3.2.5 bouyer printf("%s: error 0x%04x\n", dv->dv_xname, detail);
550 1.3.2.2 bouyer #endif
551 1.3.2.5 bouyer err = 1;
552 1.3.2.5 bouyer }
553 1.3.2.5 bouyer
554 1.3.2.5 bouyer if (err) {
555 1.3.2.2 bouyer bp->b_flags |= B_ERROR;
556 1.3.2.2 bouyer bp->b_error = EIO;
557 1.3.2.2 bouyer bp->b_resid = bp->b_bcount;
558 1.3.2.2 bouyer } else
559 1.3.2.5 bouyer bp->b_resid = bp->b_bcount - le32toh(rb->transfercount);
560 1.3.2.2 bouyer
561 1.3.2.2 bouyer iop_msg_unmap(iop, im);
562 1.3.2.5 bouyer iop_msg_free(iop, im);
563 1.3.2.2 bouyer lddone(&sc->sc_ld, bp);
564 1.3.2.2 bouyer }
565 1.3.2.2 bouyer
566 1.3.2.2 bouyer static void
567 1.3.2.2 bouyer ld_iop_intr_event(struct device *dv, struct iop_msg *im, void *reply)
568 1.3.2.2 bouyer {
569 1.3.2.2 bouyer struct i2o_util_event_register_reply *rb;
570 1.3.2.5 bouyer struct ld_iop_softc *sc;
571 1.3.2.2 bouyer u_int event;
572 1.3.2.2 bouyer
573 1.3.2.2 bouyer rb = reply;
574 1.3.2.5 bouyer
575 1.3.2.5 bouyer if ((rb->msgflags & I2O_MSGFLAGS_FAIL) != 0)
576 1.3.2.5 bouyer return;
577 1.3.2.5 bouyer
578 1.3.2.2 bouyer event = le32toh(rb->event);
579 1.3.2.5 bouyer sc = (struct ld_iop_softc *)dv;
580 1.3.2.2 bouyer
581 1.3.2.5 bouyer if (event == I2O_EVENT_GEN_EVENT_MASK_MODIFIED) {
582 1.3.2.5 bouyer sc->sc_flags |= LD_IOP_NEW_EVTMASK;
583 1.3.2.5 bouyer wakeup(&sc->sc_eventii);
584 1.3.2.2 bouyer #ifndef I2ODEBUG
585 1.3.2.2 bouyer return;
586 1.3.2.2 bouyer #endif
587 1.3.2.5 bouyer }
588 1.3.2.2 bouyer
589 1.3.2.2 bouyer printf("%s: event 0x%08x received\n", dv->dv_xname, event);
590 1.3.2.2 bouyer }
591 1.3.2.5 bouyer
592 1.3.2.5 bouyer static void
593 1.3.2.5 bouyer ld_iop_adjqparam(struct device *dv, int mpi)
594 1.3.2.5 bouyer {
595 1.3.2.5 bouyer struct iop_softc *iop;
596 1.3.2.5 bouyer
597 1.3.2.5 bouyer /*
598 1.3.2.5 bouyer * AMI controllers seem to loose the plot if you hand off lots of
599 1.3.2.5 bouyer * queued commands.
600 1.3.2.5 bouyer */
601 1.3.2.5 bouyer iop = (struct iop_softc *)dv->dv_parent;
602 1.3.2.5 bouyer if (le16toh(I2O_ORG_AMI) == iop->sc_status.orgid && mpi > 64)
603 1.3.2.5 bouyer mpi = 64;
604 1.3.2.5 bouyer
605 1.3.2.5 bouyer ldadjqparam((struct ld_softc *)dv, mpi);
606 1.3.2.5 bouyer }
607