mlx.c revision 1.66 1 /* $NetBSD: mlx.c,v 1.66 2017/10/28 04:53:55 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
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 * Copyright (c) 1999 Michael Smith
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 *
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * SUCH DAMAGE.
56 *
57 * from FreeBSD: mlx.c,v 1.14.2.3 2000/08/04 06:52:50 msmith Exp
58 */
59
60 /*
61 * Driver for the Mylex DAC960 family of RAID controllers.
62 *
63 * TODO:
64 *
65 * o Test and enable channel pause.
66 * o SCSI pass-through.
67 */
68
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: mlx.c,v 1.66 2017/10/28 04:53:55 riastradh Exp $");
71
72 #if defined(_KERNEL_OPT)
73 #include "ld.h"
74 #endif
75
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 #include <sys/kernel.h>
79 #include <sys/device.h>
80 #include <sys/queue.h>
81 #include <sys/proc.h>
82 #include <sys/buf.h>
83 #include <sys/bufq.h>
84 #include <sys/endian.h>
85 #include <sys/malloc.h>
86 #include <sys/conf.h>
87 #include <sys/kthread.h>
88 #include <sys/disk.h>
89 #include <sys/kauth.h>
90 #include <sys/module.h>
91 #include <machine/vmparam.h>
92 #include <sys/bus.h>
93
94 #include <dev/ldvar.h>
95
96 #include <dev/ic/mlxreg.h>
97 #include <dev/ic/mlxio.h>
98 #include <dev/ic/mlxvar.h>
99
100 #include "ioconf.h"
101 #include "locators.h"
102
103 #define MLX_TIMEOUT 60
104
105 #ifdef DIAGNOSTIC
106 #define DPRINTF(x) printf x
107 #else
108 #define DPRINTF(x)
109 #endif
110
111 static void mlx_adjqparam(struct mlx_softc *, int, int);
112 static int mlx_ccb_submit(struct mlx_softc *, struct mlx_ccb *);
113 static int mlx_check(struct mlx_softc *, int);
114 static void mlx_describe(struct mlx_softc *);
115 static void *mlx_enquire(struct mlx_softc *, int, size_t,
116 void (*)(struct mlx_ccb *), int);
117 static int mlx_fw_message(struct mlx_softc *, int, int, int);
118 static void mlx_pause_action(struct mlx_softc *);
119 static void mlx_pause_done(struct mlx_ccb *);
120 static void mlx_periodic(struct mlx_softc *);
121 static void mlx_periodic_enquiry(struct mlx_ccb *);
122 static void mlx_periodic_eventlog_poll(struct mlx_softc *);
123 static void mlx_periodic_eventlog_respond(struct mlx_ccb *);
124 static void mlx_periodic_rebuild(struct mlx_ccb *);
125 static void mlx_periodic_thread(void *);
126 static int mlx_print(void *, const char *);
127 static int mlx_rebuild(struct mlx_softc *, int, int);
128 static void mlx_shutdown(void *);
129 static int mlx_user_command(struct mlx_softc *, struct mlx_usercommand *);
130
131 dev_type_open(mlxopen);
132 dev_type_close(mlxclose);
133 dev_type_ioctl(mlxioctl);
134
135 const struct cdevsw mlx_cdevsw = {
136 .d_open = mlxopen,
137 .d_close = mlxclose,
138 .d_read = noread,
139 .d_write = nowrite,
140 .d_ioctl = mlxioctl,
141 .d_stop = nostop,
142 .d_tty = notty,
143 .d_poll = nopoll,
144 .d_mmap = nommap,
145 .d_kqfilter = nokqfilter,
146 .d_discard = nodiscard,
147 .d_flag = D_OTHER
148 };
149
150 static struct lwp *mlx_periodic_lwp;
151 static void *mlx_sdh;
152
153 static struct {
154 int hwid;
155 const char *name;
156 } const mlx_cname[] = {
157 { 0x00, "960E/960M" },
158 { 0x01, "960P/PD" },
159 { 0x02, "960PL" },
160 { 0x10, "960PG" },
161 { 0x11, "960PJ" },
162 { 0x12, "960PR" },
163 { 0x13, "960PT" },
164 { 0x14, "960PTL0" },
165 { 0x15, "960PRL" },
166 { 0x16, "960PTL1" },
167 { 0x20, "1164PVX" },
168 };
169
170 static const char * const mlx_sense_msgs[] = {
171 "because write recovery failed",
172 "because of SCSI bus reset failure",
173 "because of double check condition",
174 "because it was removed",
175 "because of gross error on SCSI chip",
176 "because of bad tag returned from drive",
177 "because of timeout on SCSI command",
178 "because of reset SCSI command issued from system",
179 "because busy or parity error count exceeded limit",
180 "because of 'kill drive' command from system",
181 "because of selection timeout",
182 "due to SCSI phase sequence error",
183 "due to unknown status"
184 };
185
186 static const char * const mlx_status_msgs[] = {
187 "normal completion", /* 0 */
188 "irrecoverable data error", /* 1 */
189 "drive does not exist, or is offline", /* 2 */
190 "attempt to write beyond end of drive", /* 3 */
191 "bad data encountered", /* 4 */
192 "invalid log entry request", /* 5 */
193 "attempt to rebuild online drive", /* 6 */
194 "new disk failed during rebuild", /* 7 */
195 "invalid channel/target", /* 8 */
196 "rebuild/check already in progress", /* 9 */
197 "one or more disks are dead", /* 10 */
198 "invalid or non-redundant drive", /* 11 */
199 "channel is busy", /* 12 */
200 "channel is not stopped", /* 13 */
201 "rebuild successfully terminated", /* 14 */
202 "unsupported command", /* 15 */
203 "check condition received", /* 16 */
204 "device is busy", /* 17 */
205 "selection or command timeout", /* 18 */
206 "command terminated abnormally", /* 19 */
207 "controller wedged", /* 20 */
208 "software timeout", /* 21 */
209 "command busy (?)", /* 22 */
210 };
211
212 static struct {
213 u_char command;
214 u_char msg; /* Index into mlx_status_msgs[]. */
215 u_short status;
216 } const mlx_msgs[] = {
217 { MLX_CMD_READSG, 1, 0x0001 },
218 { MLX_CMD_READSG, 1, 0x0002 },
219 { MLX_CMD_READSG, 3, 0x0105 },
220 { MLX_CMD_READSG, 4, 0x010c },
221 { MLX_CMD_WRITESG, 1, 0x0001 },
222 { MLX_CMD_WRITESG, 1, 0x0002 },
223 { MLX_CMD_WRITESG, 3, 0x0105 },
224 { MLX_CMD_READSG_OLD, 1, 0x0001 },
225 { MLX_CMD_READSG_OLD, 1, 0x0002 },
226 { MLX_CMD_READSG_OLD, 3, 0x0105 },
227 { MLX_CMD_WRITESG_OLD, 1, 0x0001 },
228 { MLX_CMD_WRITESG_OLD, 1, 0x0002 },
229 { MLX_CMD_WRITESG_OLD, 3, 0x0105 },
230 { MLX_CMD_LOGOP, 5, 0x0105 },
231 { MLX_CMD_REBUILDASYNC, 6, 0x0002 },
232 { MLX_CMD_REBUILDASYNC, 7, 0x0004 },
233 { MLX_CMD_REBUILDASYNC, 8, 0x0105 },
234 { MLX_CMD_REBUILDASYNC, 9, 0x0106 },
235 { MLX_CMD_REBUILDASYNC, 14, 0x0107 },
236 { MLX_CMD_CHECKASYNC, 10, 0x0002 },
237 { MLX_CMD_CHECKASYNC, 11, 0x0105 },
238 { MLX_CMD_CHECKASYNC, 9, 0x0106 },
239 { MLX_CMD_STOPCHANNEL, 12, 0x0106 },
240 { MLX_CMD_STOPCHANNEL, 8, 0x0105 },
241 { MLX_CMD_STARTCHANNEL, 13, 0x0005 },
242 { MLX_CMD_STARTCHANNEL, 8, 0x0105 },
243 { MLX_CMD_DIRECT_CDB, 16, 0x0002 },
244 { MLX_CMD_DIRECT_CDB, 17, 0x0008 },
245 { MLX_CMD_DIRECT_CDB, 18, 0x000e },
246 { MLX_CMD_DIRECT_CDB, 19, 0x000f },
247 { MLX_CMD_DIRECT_CDB, 8, 0x0105 },
248
249 { 0, 20, MLX_STATUS_WEDGED },
250 { 0, 21, MLX_STATUS_LOST },
251 { 0, 22, MLX_STATUS_BUSY },
252
253 { 0, 14, 0x0104 },
254 };
255
256 /*
257 * Initialise the controller and our interface.
258 */
259 void
260 mlx_init(struct mlx_softc *mlx, const char *intrstr)
261 {
262 struct mlx_ccb *mc;
263 struct mlx_enquiry_old *meo;
264 struct mlx_enquiry2 *me2;
265 struct mlx_cinfo *ci;
266 int rv, fwminor, hscode, hserr, hsparam1, hsparam2, hsmsg;
267 int size, i, rseg;
268 const char *wantfwstr;
269 bus_dma_segment_t seg;
270
271 SIMPLEQ_INIT(&mlx->mlx_ccb_queue);
272 SLIST_INIT(&mlx->mlx_ccb_freelist);
273 TAILQ_INIT(&mlx->mlx_ccb_worklist);
274
275 if (intrstr != NULL)
276 printf("%s: interrupting at %s\n", device_xname(mlx->mlx_dv),
277 intrstr);
278
279 /*
280 * Allocate the scatter/gather lists.
281 */
282 size = MLX_SGL_SIZE * MLX_MAX_QUEUECNT;
283
284 if ((rv = bus_dmamem_alloc(mlx->mlx_dmat, size, PAGE_SIZE, 0, &seg, 1,
285 &rseg, BUS_DMA_NOWAIT)) != 0) {
286 aprint_error_dev(mlx->mlx_dv,
287 "unable to allocate sglists, rv = %d\n", rv);
288 return;
289 }
290
291 if ((rv = bus_dmamem_map(mlx->mlx_dmat, &seg, rseg, size,
292 (void **)&mlx->mlx_sgls,
293 BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
294 aprint_error_dev(mlx->mlx_dv,
295 "unable to map sglists, rv = %d\n", rv);
296 return;
297 }
298
299 if ((rv = bus_dmamap_create(mlx->mlx_dmat, size, 1, size, 0,
300 BUS_DMA_NOWAIT, &mlx->mlx_dmamap)) != 0) {
301 aprint_error_dev(mlx->mlx_dv,
302 "unable to create sglist DMA map, rv = %d\n", rv);
303 return;
304 }
305
306 if ((rv = bus_dmamap_load(mlx->mlx_dmat, mlx->mlx_dmamap,
307 mlx->mlx_sgls, size, NULL, BUS_DMA_NOWAIT)) != 0) {
308 aprint_error_dev(mlx->mlx_dv,
309 "unable to load sglist DMA map, rv = %d\n", rv);
310 return;
311 }
312
313 mlx->mlx_sgls_paddr = mlx->mlx_dmamap->dm_segs[0].ds_addr;
314 memset(mlx->mlx_sgls, 0, size);
315
316 /*
317 * Allocate and initialize the CCBs.
318 */
319 mc = malloc(sizeof(*mc) * MLX_MAX_QUEUECNT, M_DEVBUF, M_NOWAIT);
320 mlx->mlx_ccbs = mc;
321
322 for (i = 0; i < MLX_MAX_QUEUECNT; i++, mc++) {
323 mc->mc_ident = i;
324 rv = bus_dmamap_create(mlx->mlx_dmat, MLX_MAX_XFER,
325 MLX_MAX_SEGS, MLX_MAX_XFER, 0,
326 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
327 &mc->mc_xfer_map);
328 if (rv != 0)
329 break;
330 mlx->mlx_nccbs++;
331 mlx_ccb_free(mlx, mc);
332 }
333 if (mlx->mlx_nccbs != MLX_MAX_QUEUECNT)
334 printf("%s: %d/%d CCBs usable\n", device_xname(mlx->mlx_dv),
335 mlx->mlx_nccbs, MLX_MAX_QUEUECNT);
336
337 /* Disable interrupts before we start talking to the controller */
338 (*mlx->mlx_intaction)(mlx, 0);
339
340 /* If we've got a reset routine, then reset the controller now. */
341 if (mlx->mlx_reset != NULL) {
342 printf("%s: resetting controller...\n",
343 device_xname(mlx->mlx_dv));
344 if ((*mlx->mlx_reset)(mlx) != 0) {
345 aprint_error_dev(mlx->mlx_dv, "reset failed\n");
346 return;
347 }
348 }
349
350 /*
351 * Wait for the controller to come ready, handshaking with the
352 * firmware if required. This is typically only necessary on
353 * platforms where the controller BIOS does not run.
354 */
355 hsmsg = 0;
356
357 for (;;) {
358 hscode = (*mlx->mlx_fw_handshake)(mlx, &hserr, &hsparam1,
359 &hsparam2);
360 if (hscode == 0) {
361 if (hsmsg != 0)
362 printf("%s: initialization complete\n",
363 device_xname(mlx->mlx_dv));
364 break;
365 }
366
367 /* Report first time around... */
368 if (hsmsg == 0) {
369 printf("%s: initializing (may take some time)...\n",
370 device_xname(mlx->mlx_dv));
371 hsmsg = 1;
372 }
373
374 /* Did we get a real message? */
375 if (hscode == 2) {
376 hscode = mlx_fw_message(mlx, hserr, hsparam1, hsparam2);
377
378 /* Fatal initialisation error? */
379 if (hscode != 0)
380 return;
381 }
382 }
383
384 /*
385 * Do quirk/feature related things.
386 */
387 ci = &mlx->mlx_ci;
388
389 if (ci->ci_iftype > 1) {
390 me2 = mlx_enquire(mlx, MLX_CMD_ENQUIRY2,
391 sizeof(struct mlx_enquiry2), NULL, 0);
392 if (me2 == NULL) {
393 aprint_error_dev(mlx->mlx_dv, "ENQUIRY2 failed\n");
394 return;
395 }
396
397 ci->ci_firmware_id[0] = me2->me_firmware_id[0];
398 ci->ci_firmware_id[1] = me2->me_firmware_id[1];
399 ci->ci_firmware_id[2] = me2->me_firmware_id[2];
400 ci->ci_firmware_id[3] = me2->me_firmware_id[3];
401 ci->ci_hardware_id = me2->me_hardware_id[0];
402 ci->ci_mem_size = le32toh(me2->me_mem_size);
403 ci->ci_max_sg = le16toh(me2->me_max_sg);
404 ci->ci_max_commands = le16toh(me2->me_max_commands);
405 ci->ci_nchan = me2->me_actual_channels;
406
407 free(me2, M_DEVBUF);
408 }
409
410 if (ci->ci_iftype <= 2) {
411 /*
412 * These controllers may not report the firmware version in
413 * the ENQUIRY2 response, or may not even support it.
414 */
415 meo = mlx_enquire(mlx, MLX_CMD_ENQUIRY_OLD,
416 sizeof(struct mlx_enquiry_old), NULL, 0);
417 if (meo == NULL) {
418 aprint_error_dev(mlx->mlx_dv, "ENQUIRY_OLD failed\n");
419 return;
420 }
421 ci->ci_firmware_id[0] = meo->me_fwmajor;
422 ci->ci_firmware_id[1] = meo->me_fwminor;
423 ci->ci_firmware_id[2] = 0;
424 ci->ci_firmware_id[3] = '0';
425
426 if (ci->ci_iftype == 1) {
427 ci->ci_hardware_id = 0; /* XXX */
428 ci->ci_mem_size = 0; /* XXX */
429 ci->ci_max_sg = 17; /* XXX */
430 ci->ci_max_commands = meo->me_max_commands;
431 }
432
433 free(meo, M_DEVBUF);
434 }
435
436 wantfwstr = NULL;
437 fwminor = ci->ci_firmware_id[1];
438
439 switch (ci->ci_firmware_id[0]) {
440 case 2:
441 if (ci->ci_iftype == 1) {
442 if (fwminor < 14)
443 wantfwstr = "2.14";
444 } else if (fwminor < 42)
445 wantfwstr = "2.42";
446 break;
447
448 case 3:
449 if (fwminor < 51)
450 wantfwstr = "3.51";
451 break;
452
453 case 4:
454 if (fwminor < 6)
455 wantfwstr = "4.06";
456 break;
457
458 case 5:
459 if (fwminor < 7)
460 wantfwstr = "5.07";
461 break;
462 }
463
464 /* Print a little information about the controller. */
465 mlx_describe(mlx);
466
467 if (wantfwstr != NULL) {
468 printf("%s: WARNING: this f/w revision is not recommended\n",
469 device_xname(mlx->mlx_dv));
470 printf("%s: WARNING: use revision %s or later\n",
471 device_xname(mlx->mlx_dv), wantfwstr);
472 }
473
474 /* We don't (yet) know where the event log is up to. */
475 mlx->mlx_currevent = -1;
476
477 /* No user-requested background operation is in progress. */
478 mlx->mlx_bg = 0;
479 mlx->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
480
481 /* Set maximum number of queued commands for `regular' operations. */
482 mlx->mlx_max_queuecnt =
483 min(ci->ci_max_commands, MLX_MAX_QUEUECNT) -
484 MLX_NCCBS_CONTROL;
485 #ifdef DIAGNOSTIC
486 if (mlx->mlx_max_queuecnt < MLX_NCCBS_CONTROL + MLX_MAX_DRIVES)
487 printf("%s: WARNING: few CCBs available\n",
488 device_xname(mlx->mlx_dv));
489 if (ci->ci_max_sg < MLX_MAX_SEGS) {
490 aprint_error_dev(mlx->mlx_dv,
491 "oops, not enough S/G segments\n");
492 return;
493 }
494 #endif
495
496 /* Attach child devices and enable interrupts. */
497 mlx_configure(mlx, 0);
498 (*mlx->mlx_intaction)(mlx, 1);
499 mlx->mlx_flags |= MLXF_INITOK;
500
501 if (mlx_sdh == NULL) {
502 /*
503 * Set our `shutdownhook' before we start any device
504 * activity.
505 */
506 mlx_sdh = shutdownhook_establish(mlx_shutdown, NULL);
507
508 /* Create a status monitoring thread. */
509 rv = kthread_create(PRI_NONE, 0, NULL, mlx_periodic_thread,
510 NULL, &mlx_periodic_lwp, "mlxtask");
511 if (rv != 0)
512 aprint_error_dev(mlx->mlx_dv,
513 "mlx_init: unable to create thread (%d)\n", rv);
514 }
515 }
516
517 /*
518 * Tell the world about the controller.
519 */
520 static void
521 mlx_describe(struct mlx_softc *mlx)
522 {
523 struct mlx_cinfo *ci;
524 static char tbuf[80];
525 const char *model;
526 int i;
527
528 model = NULL;
529 ci = &mlx->mlx_ci;
530
531 for (i = 0; i < sizeof(mlx_cname) / sizeof(mlx_cname[0]); i++)
532 if (ci->ci_hardware_id == mlx_cname[i].hwid) {
533 model = mlx_cname[i].name;
534 break;
535 }
536
537 if (model == NULL) {
538 snprintf(tbuf, sizeof(tbuf), " model 0x%x", ci->ci_hardware_id);
539 model = tbuf;
540 }
541
542 printf("%s: DAC%s, %d channel%s, firmware %d.%02d-%c-%02d",
543 device_xname(mlx->mlx_dv), model, ci->ci_nchan,
544 ci->ci_nchan > 1 ? "s" : "",
545 ci->ci_firmware_id[0], ci->ci_firmware_id[1],
546 ci->ci_firmware_id[3], ci->ci_firmware_id[2]);
547 if (ci->ci_mem_size != 0)
548 printf(", %dMB RAM", ci->ci_mem_size >> 20);
549 printf("\n");
550 }
551
552 /*
553 * Locate disk resources and attach children to them.
554 */
555 int
556 mlx_configure(struct mlx_softc *mlx, int waitok)
557 {
558 struct mlx_enquiry *me;
559 struct mlx_enquiry_old *meo;
560 struct mlx_enq_sys_drive *mes;
561 struct mlx_sysdrive *ms;
562 struct mlx_attach_args mlxa;
563 int i, nunits;
564 u_int size;
565 int locs[MLXCF_NLOCS];
566
567 mlx->mlx_flags |= MLXF_RESCANNING;
568
569 if (mlx->mlx_ci.ci_iftype <= 2) {
570 meo = mlx_enquire(mlx, MLX_CMD_ENQUIRY_OLD,
571 sizeof(struct mlx_enquiry_old), NULL, waitok);
572 if (meo == NULL) {
573 aprint_error_dev(mlx->mlx_dv, "ENQUIRY_OLD failed\n");
574 goto out;
575 }
576 mlx->mlx_numsysdrives = meo->me_num_sys_drvs;
577 free(meo, M_DEVBUF);
578 } else {
579 me = mlx_enquire(mlx, MLX_CMD_ENQUIRY,
580 sizeof(struct mlx_enquiry), NULL, waitok);
581 if (me == NULL) {
582 aprint_error_dev(mlx->mlx_dv, "ENQUIRY failed\n");
583 goto out;
584 }
585 mlx->mlx_numsysdrives = me->me_num_sys_drvs;
586 free(me, M_DEVBUF);
587 }
588
589 mes = mlx_enquire(mlx, MLX_CMD_ENQSYSDRIVE,
590 sizeof(*mes) * MLX_MAX_DRIVES, NULL, waitok);
591 if (mes == NULL) {
592 aprint_error_dev(mlx->mlx_dv, "error fetching drive status\n");
593 goto out;
594 }
595
596 /* Allow 1 queued command per unit while re-configuring. */
597 mlx_adjqparam(mlx, 1, 0);
598
599 ms = &mlx->mlx_sysdrive[0];
600 nunits = 0;
601 for (i = 0; i < MLX_MAX_DRIVES; i++, ms++) {
602 size = le32toh(mes[i].sd_size);
603 ms->ms_state = mes[i].sd_state;
604
605 /*
606 * If an existing device has changed in some way (e.g. no
607 * longer present) then detach it.
608 */
609 if (ms->ms_dv != NULL && (size != ms->ms_size ||
610 (mes[i].sd_raidlevel & 0xf) != ms->ms_raidlevel))
611 config_detach(ms->ms_dv, DETACH_FORCE);
612
613 ms->ms_size = size;
614 ms->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
615 ms->ms_state = mes[i].sd_state;
616 ms->ms_dv = NULL;
617
618 if (i >= mlx->mlx_numsysdrives)
619 continue;
620 if (size == 0xffffffffU || size == 0)
621 continue;
622
623 /*
624 * Attach a new device.
625 */
626 mlxa.mlxa_unit = i;
627
628 locs[MLXCF_UNIT] = i;
629
630 ms->ms_dv = config_found_sm_loc(mlx->mlx_dv, "mlx", locs,
631 &mlxa, mlx_print, config_stdsubmatch);
632 nunits += (ms->ms_dv != NULL);
633 }
634
635 free(mes, M_DEVBUF);
636
637 if (nunits != 0)
638 mlx_adjqparam(mlx, mlx->mlx_max_queuecnt / nunits,
639 mlx->mlx_max_queuecnt % nunits);
640 out:
641 mlx->mlx_flags &= ~MLXF_RESCANNING;
642
643 return 0;
644 }
645
646 /*
647 * Print autoconfiguration message for a sub-device.
648 */
649 static int
650 mlx_print(void *aux, const char *pnp)
651 {
652 struct mlx_attach_args *mlxa;
653
654 mlxa = (struct mlx_attach_args *)aux;
655
656 if (pnp != NULL)
657 aprint_normal("block device at %s", pnp);
658 aprint_normal(" unit %d", mlxa->mlxa_unit);
659 return (UNCONF);
660 }
661
662 /*
663 * Shut down all configured `mlx' devices.
664 */
665 static void
666 mlx_shutdown(void *cookie)
667 {
668 struct mlx_softc *mlx;
669 int i;
670
671 for (i = 0; i < mlx_cd.cd_ndevs; i++)
672 if ((mlx = device_lookup_private(&mlx_cd, i)) != NULL)
673 mlx_flush(mlx, 0);
674 }
675
676 /*
677 * Adjust queue parameters for all child devices.
678 */
679 static void
680 mlx_adjqparam(struct mlx_softc *mlx, int mpu, int slop)
681 {
682 #if NLD > 0
683 struct ld_softc *ld;
684 int i;
685
686 for (i = 0; i < ld_cd.cd_ndevs; i++) {
687 if ((ld = device_lookup_private(&ld_cd, i)) == NULL)
688 continue;
689 if (device_parent(ld->sc_dv) != mlx->mlx_dv)
690 continue;
691 ldadjqparam(ld, mpu + (slop-- > 0));
692 }
693 #endif
694 }
695
696 /*
697 * Accept an open operation on the control device.
698 */
699 int
700 mlxopen(dev_t dev, int flag, int mode, struct lwp *l)
701 {
702 struct mlx_softc *mlx;
703
704 if ((mlx = device_lookup_private(&mlx_cd, minor(dev))) == NULL)
705 return (ENXIO);
706 if ((mlx->mlx_flags & MLXF_INITOK) == 0)
707 return (ENXIO);
708 if ((mlx->mlx_flags & MLXF_OPEN) != 0)
709 return (EBUSY);
710
711 mlx->mlx_flags |= MLXF_OPEN;
712 return (0);
713 }
714
715 /*
716 * Accept the last close on the control device.
717 */
718 int
719 mlxclose(dev_t dev, int flag, int mode, struct lwp *l)
720 {
721 struct mlx_softc *mlx;
722
723 mlx = device_lookup_private(&mlx_cd, minor(dev));
724 mlx->mlx_flags &= ~MLXF_OPEN;
725 return (0);
726 }
727
728 /*
729 * Handle control operations.
730 */
731 int
732 mlxioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
733 {
734 struct mlx_softc *mlx;
735 struct mlx_rebuild_request *rb;
736 struct mlx_rebuild_status *rs;
737 struct mlx_pause *mp;
738 struct mlx_sysdrive *ms;
739 int i, rv, *arg, result;
740
741 mlx = device_lookup_private(&mlx_cd, minor(dev));
742
743 rb = (struct mlx_rebuild_request *)data;
744 rs = (struct mlx_rebuild_status *)data;
745 arg = (int *)data;
746 rv = 0;
747
748 switch (cmd) {
749 case MLX_RESCAN_DRIVES:
750 /*
751 * Scan the controller to see whether new drives have
752 * appeared, or old ones disappeared.
753 */
754 mlx_configure(mlx, 1);
755 return (0);
756
757 case MLX_PAUSE_CHANNEL:
758 /*
759 * Pause one or more SCSI channels for a period of time, to
760 * assist in the process of hot-swapping devices.
761 *
762 * Note that at least the 3.51 firmware on the DAC960PL
763 * doesn't seem to do this right.
764 */
765 if ((mlx->mlx_flags & MLXF_PAUSEWORKS) == 0)
766 return (EOPNOTSUPP);
767
768 mp = (struct mlx_pause *)data;
769
770 if ((mp->mp_which == MLX_PAUSE_CANCEL) &&
771 (mlx->mlx_pause.mp_when != 0)) {
772 /* Cancel a pending pause operation. */
773 mlx->mlx_pause.mp_which = 0;
774 break;
775 }
776
777 /* Fix for legal channels. */
778 mp->mp_which &= ((1 << mlx->mlx_ci.ci_nchan) -1);
779
780 /* Check time values. */
781 if (mp->mp_when < 0 || mp->mp_when > 3600 ||
782 mp->mp_howlong < 1 || mp->mp_howlong > (0xf * 30)) {
783 rv = EINVAL;
784 break;
785 }
786
787 /* Check for a pause currently running. */
788 if ((mlx->mlx_pause.mp_which != 0) &&
789 (mlx->mlx_pause.mp_when == 0)) {
790 rv = EBUSY;
791 break;
792 }
793
794 /* Looks ok, go with it. */
795 mlx->mlx_pause.mp_which = mp->mp_which;
796 mlx->mlx_pause.mp_when = time_second + mp->mp_when;
797 mlx->mlx_pause.mp_howlong =
798 mlx->mlx_pause.mp_when + mp->mp_howlong;
799
800 return (0);
801
802 case MLX_COMMAND:
803 rv = kauth_authorize_device_passthru(l->l_cred, dev,
804 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL, data);
805 if (rv)
806 return (rv);
807
808 /*
809 * Accept a command passthrough-style.
810 */
811 return (mlx_user_command(mlx, (struct mlx_usercommand *)data));
812
813 case MLX_REBUILDASYNC:
814 /*
815 * Start a rebuild on a given SCSI disk
816 */
817 if (mlx->mlx_bg != 0) {
818 rb->rr_status = 0x0106;
819 rv = EBUSY;
820 break;
821 }
822
823 rb->rr_status = mlx_rebuild(mlx, rb->rr_channel, rb->rr_target);
824 switch (rb->rr_status) {
825 case 0:
826 rv = 0;
827 break;
828 case 0x10000:
829 rv = ENOMEM; /* Couldn't set up the command. */
830 break;
831 case 0x0002:
832 rv = EBUSY;
833 break;
834 case 0x0104:
835 rv = EIO;
836 break;
837 case 0x0105:
838 rv = ERANGE;
839 break;
840 case 0x0106:
841 rv = EBUSY;
842 break;
843 default:
844 rv = EINVAL;
845 break;
846 }
847
848 if (rv == 0)
849 mlx->mlx_bg = MLX_BG_REBUILD;
850
851 return (0);
852
853 case MLX_REBUILDSTAT:
854 /*
855 * Get the status of the current rebuild or consistency check.
856 */
857 *rs = mlx->mlx_rebuildstat;
858 return (0);
859
860 case MLX_GET_SYSDRIVE:
861 /*
862 * Return the system drive number matching the `ld' device
863 * unit in (arg), if it happens to belong to us.
864 */
865 for (i = 0; i < MLX_MAX_DRIVES; i++) {
866 ms = &mlx->mlx_sysdrive[i];
867 if (ms->ms_dv != NULL)
868 if (device_xname(ms->ms_dv)[2] == '0' + *arg) {
869 *arg = i;
870 return (0);
871 }
872 }
873 return (ENOENT);
874
875 case MLX_GET_CINFO:
876 /*
877 * Return controller info.
878 */
879 memcpy(arg, &mlx->mlx_ci, sizeof(mlx->mlx_ci));
880 return (0);
881 }
882
883 switch (cmd) {
884 case MLXD_DETACH:
885 case MLXD_STATUS:
886 case MLXD_CHECKASYNC:
887 if ((u_int)*arg >= MLX_MAX_DRIVES)
888 return (EINVAL);
889 ms = &mlx->mlx_sysdrive[*arg];
890 if (*arg > MLX_MAX_DRIVES || ms->ms_dv == NULL)
891 return (ENOENT);
892 break;
893
894 default:
895 return (ENOTTY);
896 }
897
898 switch (cmd) {
899 case MLXD_DETACH:
900 /*
901 * Disconnect from the specified drive; it may be about to go
902 * away.
903 */
904 return (config_detach(ms->ms_dv, 0));
905
906 case MLXD_STATUS:
907 /*
908 * Return the current status of this drive.
909 */
910 *arg = ms->ms_state;
911 return (0);
912
913 case MLXD_CHECKASYNC:
914 /*
915 * Start a background consistency check on this drive.
916 */
917 if (mlx->mlx_bg != 0) {
918 *arg = 0x0106;
919 return (EBUSY);
920 }
921
922 switch (result = mlx_check(mlx, *arg)) {
923 case 0:
924 rv = 0;
925 break;
926 case 0x10000:
927 rv = ENOMEM; /* Couldn't set up the command. */
928 break;
929 case 0x0002:
930 rv = EIO;
931 break;
932 case 0x0105:
933 rv = ERANGE;
934 break;
935 case 0x0106:
936 rv = EBUSY;
937 break;
938 default:
939 rv = EINVAL;
940 break;
941 }
942
943 if (rv == 0)
944 mlx->mlx_bg = MLX_BG_CHECK;
945 *arg = result;
946 return (rv);
947 }
948
949 return (ENOTTY); /* XXX shut up gcc */
950 }
951
952 static void
953 mlx_periodic_thread(void *cookie)
954 {
955 struct mlx_softc *mlx;
956 int i;
957
958 for (;;) {
959 for (i = 0; i < mlx_cd.cd_ndevs; i++)
960 if ((mlx = device_lookup_private(&mlx_cd, i)) != NULL)
961 if (mlx->mlx_ci.ci_iftype > 1)
962 mlx_periodic(mlx);
963
964 tsleep(mlx_periodic_thread, PWAIT, "mlxzzz", hz * 2);
965 }
966 }
967
968 static void
969 mlx_periodic(struct mlx_softc *mlx)
970 {
971 struct mlx_ccb *mc, *nmc;
972 int etype, s;
973
974 if ((mlx->mlx_pause.mp_which != 0) &&
975 (mlx->mlx_pause.mp_when > 0) &&
976 (time_second >= mlx->mlx_pause.mp_when)) {
977 /*
978 * Start bus pause.
979 */
980 mlx_pause_action(mlx);
981 mlx->mlx_pause.mp_when = 0;
982 } else if ((mlx->mlx_pause.mp_which != 0) &&
983 (mlx->mlx_pause.mp_when == 0)) {
984 /*
985 * Stop pause if required.
986 */
987 if (time_second >= mlx->mlx_pause.mp_howlong) {
988 mlx_pause_action(mlx);
989 mlx->mlx_pause.mp_which = 0;
990 }
991 } else if (time_second > (mlx->mlx_lastpoll + 10)) {
992 /*
993 * Run normal periodic activities...
994 */
995 mlx->mlx_lastpoll = time_second;
996
997 /*
998 * Check controller status.
999 */
1000 if ((mlx->mlx_flags & MLXF_PERIODIC_CTLR) == 0) {
1001 mlx->mlx_flags |= MLXF_PERIODIC_CTLR;
1002
1003 if (mlx->mlx_ci.ci_iftype <= 2)
1004 etype = MLX_CMD_ENQUIRY_OLD;
1005 else
1006 etype = MLX_CMD_ENQUIRY;
1007
1008 mlx_enquire(mlx, etype, max(sizeof(struct mlx_enquiry),
1009 sizeof(struct mlx_enquiry_old)),
1010 mlx_periodic_enquiry, 1);
1011 }
1012
1013 /*
1014 * Check system drive status.
1015 */
1016 if ((mlx->mlx_flags & MLXF_PERIODIC_DRIVE) == 0) {
1017 mlx->mlx_flags |= MLXF_PERIODIC_DRIVE;
1018 mlx_enquire(mlx, MLX_CMD_ENQSYSDRIVE,
1019 sizeof(struct mlx_enq_sys_drive) * MLX_MAX_DRIVES,
1020 mlx_periodic_enquiry, 1);
1021 }
1022 }
1023
1024 /*
1025 * Get drive rebuild/check status.
1026 */
1027 if ((mlx->mlx_flags & MLXF_PERIODIC_REBUILD) == 0) {
1028 mlx->mlx_flags |= MLXF_PERIODIC_REBUILD;
1029 mlx_enquire(mlx, MLX_CMD_REBUILDSTAT,
1030 sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild, 1);
1031 }
1032
1033 /*
1034 * Time-out busy CCBs.
1035 */
1036 s = splbio();
1037 for (mc = TAILQ_FIRST(&mlx->mlx_ccb_worklist); mc != NULL; mc = nmc) {
1038 nmc = TAILQ_NEXT(mc, mc_chain.tailq);
1039 if (mc->mc_expiry > time_second) {
1040 /*
1041 * The remaining CCBs will expire after this one, so
1042 * there's no point in going further.
1043 */
1044 break;
1045 }
1046 TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
1047 mc->mc_status = MLX_STATUS_LOST;
1048 if (mc->mc_mx.mx_handler != NULL)
1049 (*mc->mc_mx.mx_handler)(mc);
1050 else if ((mc->mc_flags & MC_WAITING) != 0)
1051 wakeup(mc);
1052 }
1053 splx(s);
1054 }
1055
1056 /*
1057 * Handle the result of an ENQUIRY command instigated by periodic status
1058 * polling.
1059 */
1060 static void
1061 mlx_periodic_enquiry(struct mlx_ccb *mc)
1062 {
1063 struct mlx_softc *mlx;
1064 struct mlx_enquiry *me;
1065 struct mlx_enquiry_old *meo;
1066 struct mlx_enq_sys_drive *mes;
1067 struct mlx_sysdrive *dr;
1068 const char *statestr;
1069 int i, j;
1070 u_int lsn;
1071
1072 mlx = device_private(mc->mc_mx.mx_dv);
1073 mlx_ccb_unmap(mlx, mc);
1074
1075 /*
1076 * Command completed OK?
1077 */
1078 if (mc->mc_status != 0) {
1079 aprint_error_dev(mlx->mlx_dv, "periodic enquiry failed - %s\n",
1080 mlx_ccb_diagnose(mc));
1081 goto out;
1082 }
1083
1084 /*
1085 * Respond to command.
1086 */
1087 switch (mc->mc_mbox[0]) {
1088 case MLX_CMD_ENQUIRY_OLD:
1089 /*
1090 * This is currently a bit fruitless, as we don't know how
1091 * to extract the eventlog pointer yet.
1092 */
1093 me = (struct mlx_enquiry *)mc->mc_mx.mx_context;
1094 meo = (struct mlx_enquiry_old *)mc->mc_mx.mx_context;
1095
1096 /* Convert data in-place to new format */
1097 i = sizeof(me->me_dead) / sizeof(me->me_dead[0]);
1098 while (--i >= 0) {
1099 me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
1100 me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
1101 }
1102
1103 me->me_misc_flags = 0;
1104 me->me_rebuild_count = meo->me_rebuild_count;
1105 me->me_dead_count = meo->me_dead_count;
1106 me->me_critical_sd_count = meo->me_critical_sd_count;
1107 me->me_event_log_seq_num = 0;
1108 me->me_offline_sd_count = meo->me_offline_sd_count;
1109 me->me_max_commands = meo->me_max_commands;
1110 me->me_rebuild_flag = meo->me_rebuild_flag;
1111 me->me_fwmajor = meo->me_fwmajor;
1112 me->me_fwminor = meo->me_fwminor;
1113 me->me_status_flags = meo->me_status_flags;
1114 me->me_flash_age = meo->me_flash_age;
1115
1116 i = sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0]);
1117 j = sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0]);
1118
1119 while (--i >= 0) {
1120 if (i >= j)
1121 me->me_drvsize[i] = 0;
1122 else
1123 me->me_drvsize[i] = meo->me_drvsize[i];
1124 }
1125
1126 me->me_num_sys_drvs = meo->me_num_sys_drvs;
1127
1128 /* FALLTHROUGH */
1129
1130 case MLX_CMD_ENQUIRY:
1131 /*
1132 * Generic controller status update. We could do more with
1133 * this than just checking the event log.
1134 */
1135 me = (struct mlx_enquiry *)mc->mc_mx.mx_context;
1136 lsn = le16toh(me->me_event_log_seq_num);
1137
1138 if (mlx->mlx_currevent == -1) {
1139 /* Initialise our view of the event log. */
1140 mlx->mlx_currevent = lsn;
1141 mlx->mlx_lastevent = lsn;
1142 } else if (lsn != mlx->mlx_lastevent &&
1143 (mlx->mlx_flags & MLXF_EVENTLOG_BUSY) == 0) {
1144 /* Record where current events are up to */
1145 mlx->mlx_currevent = lsn;
1146
1147 /* Mark the event log as busy. */
1148 mlx->mlx_flags |= MLXF_EVENTLOG_BUSY;
1149
1150 /* Drain new eventlog entries. */
1151 mlx_periodic_eventlog_poll(mlx);
1152 }
1153 break;
1154
1155 case MLX_CMD_ENQSYSDRIVE:
1156 /*
1157 * Perform drive status comparison to see if something
1158 * has failed. Don't perform the comparison if we're
1159 * reconfiguring, since the system drive table will be
1160 * changing.
1161 */
1162 if ((mlx->mlx_flags & MLXF_RESCANNING) != 0)
1163 break;
1164
1165 mes = (struct mlx_enq_sys_drive *)mc->mc_mx.mx_context;
1166 dr = &mlx->mlx_sysdrive[0];
1167
1168 for (i = 0; i < mlx->mlx_numsysdrives; i++, dr++) {
1169 /* Has state been changed by controller? */
1170 if (dr->ms_state != mes[i].sd_state) {
1171 switch (mes[i].sd_state) {
1172 case MLX_SYSD_OFFLINE:
1173 statestr = "offline";
1174 break;
1175
1176 case MLX_SYSD_ONLINE:
1177 statestr = "online";
1178 break;
1179
1180 case MLX_SYSD_CRITICAL:
1181 statestr = "critical";
1182 break;
1183
1184 default:
1185 statestr = "unknown";
1186 break;
1187 }
1188
1189 printf("%s: unit %d %s\n",
1190 device_xname(mlx->mlx_dv), i, statestr);
1191
1192 /* Save new state. */
1193 dr->ms_state = mes[i].sd_state;
1194 }
1195 }
1196 break;
1197
1198 #ifdef DIAGNOSTIC
1199 default:
1200 printf("%s: mlx_periodic_enquiry: eh?\n",
1201 device_xname(mlx->mlx_dv));
1202 break;
1203 #endif
1204 }
1205
1206 out:
1207 if (mc->mc_mbox[0] == MLX_CMD_ENQSYSDRIVE)
1208 mlx->mlx_flags &= ~MLXF_PERIODIC_DRIVE;
1209 else
1210 mlx->mlx_flags &= ~MLXF_PERIODIC_CTLR;
1211
1212 free(mc->mc_mx.mx_context, M_DEVBUF);
1213 mlx_ccb_free(mlx, mc);
1214 }
1215
1216 /*
1217 * Instigate a poll for one event log message on (mlx). We only poll for
1218 * one message at a time, to keep our command usage down.
1219 */
1220 static void
1221 mlx_periodic_eventlog_poll(struct mlx_softc *mlx)
1222 {
1223 struct mlx_ccb *mc;
1224 void *result;
1225 int rv;
1226
1227 result = NULL;
1228
1229 if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0)
1230 goto out;
1231
1232 if ((result = malloc(1024, M_DEVBUF, M_WAITOK)) == NULL) {
1233 rv = ENOMEM;
1234 goto out;
1235 }
1236 if ((rv = mlx_ccb_map(mlx, mc, result, 1024, MC_XFER_IN)) != 0)
1237 goto out;
1238 if (mc->mc_nsgent != 1) {
1239 mlx_ccb_unmap(mlx, mc);
1240 printf("mlx_periodic_eventlog_poll: too many segs\n");
1241 goto out;
1242 }
1243
1244 /* Build the command to get one log entry. */
1245 mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1,
1246 mlx->mlx_lastevent, 0, 0, mc->mc_xfer_phys, 0);
1247
1248 mc->mc_mx.mx_handler = mlx_periodic_eventlog_respond;
1249 mc->mc_mx.mx_dv = mlx->mlx_dv;
1250 mc->mc_mx.mx_context = result;
1251
1252 /* Start the command. */
1253 mlx_ccb_enqueue(mlx, mc);
1254
1255 out:
1256 if (rv != 0) {
1257 if (mc != NULL)
1258 mlx_ccb_free(mlx, mc);
1259 if (result != NULL)
1260 free(result, M_DEVBUF);
1261 }
1262 }
1263
1264 /*
1265 * Handle the result of polling for a log message, generate diagnostic
1266 * output. If this wasn't the last message waiting for us, we'll go collect
1267 * another.
1268 */
1269 static void
1270 mlx_periodic_eventlog_respond(struct mlx_ccb *mc)
1271 {
1272 struct mlx_softc *mlx;
1273 struct mlx_eventlog_entry *el;
1274 const char *reason;
1275 u_int8_t sensekey, chan, targ;
1276
1277 mlx = device_private(mc->mc_mx.mx_dv);
1278 el = mc->mc_mx.mx_context;
1279 mlx_ccb_unmap(mlx, mc);
1280
1281 mlx->mlx_lastevent++;
1282
1283 if (mc->mc_status == 0) {
1284 switch (el->el_type) {
1285 case MLX_LOGMSG_SENSE: /* sense data */
1286 sensekey = el->el_sense & 0x0f;
1287 chan = (el->el_target >> 4) & 0x0f;
1288 targ = el->el_target & 0x0f;
1289
1290 /*
1291 * This is the only sort of message we understand at
1292 * the moment. The tests here are probably
1293 * incomplete.
1294 */
1295
1296 /*
1297 * Mylex vendor-specific message indicating a drive
1298 * was killed?
1299 */
1300 if (sensekey == 9 && el->el_asc == 0x80) {
1301 if (el->el_asq < sizeof(mlx_sense_msgs) /
1302 sizeof(mlx_sense_msgs[0]))
1303 reason = mlx_sense_msgs[el->el_asq];
1304 else
1305 reason = "for unknown reason";
1306
1307 printf("%s: physical drive %d:%d killed %s\n",
1308 device_xname(mlx->mlx_dv), chan, targ,
1309 reason);
1310 }
1311
1312 /*
1313 * SCSI drive was reset?
1314 */
1315 if (sensekey == 6 && el->el_asc == 0x29)
1316 printf("%s: physical drive %d:%d reset\n",
1317 device_xname(mlx->mlx_dv), chan, targ);
1318
1319 /*
1320 * SCSI drive error?
1321 */
1322 if (!(sensekey == 0 ||
1323 (sensekey == 2 &&
1324 el->el_asc == 0x04 &&
1325 (el->el_asq == 0x01 || el->el_asq == 0x02)))) {
1326 printf("%s: physical drive %d:%d error log: "
1327 "sense = %d asc = %x asq = %x\n",
1328 device_xname(mlx->mlx_dv), chan, targ,
1329 sensekey, el->el_asc, el->el_asq);
1330 printf("%s: info = %d:%d:%d:%d "
1331 " csi = %d:%d:%d:%d\n",
1332 device_xname(mlx->mlx_dv),
1333 el->el_information[0],
1334 el->el_information[1],
1335 el->el_information[2],
1336 el->el_information[3],
1337 el->el_csi[0], el->el_csi[1],
1338 el->el_csi[2], el->el_csi[3]);
1339 }
1340
1341 break;
1342
1343 default:
1344 aprint_error_dev(mlx->mlx_dv,
1345 "unknown log message type 0x%x\n", el->el_type);
1346 break;
1347 }
1348 } else {
1349 aprint_error_dev(mlx->mlx_dv,
1350 "error reading message log - %s\n", mlx_ccb_diagnose(mc));
1351
1352 /*
1353 * Give up on all the outstanding messages, as we may have
1354 * come unsynched.
1355 */
1356 mlx->mlx_lastevent = mlx->mlx_currevent;
1357 }
1358
1359 free(mc->mc_mx.mx_context, M_DEVBUF);
1360 mlx_ccb_free(mlx, mc);
1361
1362 /*
1363 * Is there another message to obtain?
1364 */
1365 if (mlx->mlx_lastevent != mlx->mlx_currevent)
1366 mlx_periodic_eventlog_poll(mlx);
1367 else
1368 mlx->mlx_flags &= ~MLXF_EVENTLOG_BUSY;
1369 }
1370
1371 /*
1372 * Handle check/rebuild operations in progress.
1373 */
1374 static void
1375 mlx_periodic_rebuild(struct mlx_ccb *mc)
1376 {
1377 struct mlx_softc *mlx;
1378 const char *opstr;
1379 struct mlx_rebuild_status *mr;
1380
1381 mlx = device_private(mc->mc_mx.mx_dv);
1382 mr = mc->mc_mx.mx_context;
1383 mlx_ccb_unmap(mlx, mc);
1384
1385 switch (mc->mc_status) {
1386 case 0:
1387 /*
1388 * Operation running, update stats.
1389 */
1390 mlx->mlx_rebuildstat = *mr;
1391
1392 /* Spontaneous rebuild/check? */
1393 if (mlx->mlx_bg == 0) {
1394 mlx->mlx_bg = MLX_BG_SPONTANEOUS;
1395 printf("%s: background check/rebuild started\n",
1396 device_xname(mlx->mlx_dv));
1397 }
1398 break;
1399
1400 case 0x0105:
1401 /*
1402 * Nothing running, finalise stats and report.
1403 */
1404 switch (mlx->mlx_bg) {
1405 case MLX_BG_CHECK:
1406 /* XXX Print drive? */
1407 opstr = "consistency check";
1408 break;
1409
1410 case MLX_BG_REBUILD:
1411 /* XXX Print channel:target? */
1412 opstr = "drive rebuild";
1413 break;
1414
1415 case MLX_BG_SPONTANEOUS:
1416 default:
1417 /*
1418 * If we have previously been non-idle, report the
1419 * transition
1420 */
1421 if (mlx->mlx_rebuildstat.rs_code !=
1422 MLX_REBUILDSTAT_IDLE)
1423 opstr = "background check/rebuild";
1424 else
1425 opstr = NULL;
1426 }
1427
1428 if (opstr != NULL)
1429 printf("%s: %s completed\n", device_xname(mlx->mlx_dv),
1430 opstr);
1431
1432 mlx->mlx_bg = 0;
1433 mlx->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
1434 break;
1435 }
1436
1437 free(mc->mc_mx.mx_context, M_DEVBUF);
1438 mlx_ccb_free(mlx, mc);
1439 mlx->mlx_flags &= ~MLXF_PERIODIC_REBUILD;
1440 }
1441
1442 /*
1443 * It's time to perform a channel pause action for (mlx), either start or
1444 * stop the pause.
1445 */
1446 static void
1447 mlx_pause_action(struct mlx_softc *mlx)
1448 {
1449 struct mlx_ccb *mc;
1450 int failsafe, i, cmd;
1451
1452 /* What are we doing here? */
1453 if (mlx->mlx_pause.mp_when == 0) {
1454 cmd = MLX_CMD_STARTCHANNEL;
1455 failsafe = 0;
1456 } else {
1457 cmd = MLX_CMD_STOPCHANNEL;
1458
1459 /*
1460 * Channels will always start again after the failsafe
1461 * period, which is specified in multiples of 30 seconds.
1462 * This constrains us to a maximum pause of 450 seconds.
1463 */
1464 failsafe = ((mlx->mlx_pause.mp_howlong - time_second) + 5) / 30;
1465
1466 if (failsafe > 0xf) {
1467 failsafe = 0xf;
1468 mlx->mlx_pause.mp_howlong =
1469 time_second + (0xf * 30) - 5;
1470 }
1471 }
1472
1473 /* Build commands for every channel requested. */
1474 for (i = 0; i < mlx->mlx_ci.ci_nchan; i++) {
1475 if ((1 << i) & mlx->mlx_pause.mp_which) {
1476 if (mlx_ccb_alloc(mlx, &mc, 1) != 0) {
1477 aprint_error_dev(mlx->mlx_dv,
1478 "%s failed for channel %d\n",
1479 cmd == MLX_CMD_STOPCHANNEL ?
1480 "pause" : "resume", i);
1481 continue;
1482 }
1483
1484 /* Build the command. */
1485 mlx_make_type2(mc, cmd, (failsafe << 4) | i, 0, 0,
1486 0, 0, 0, 0, 0);
1487 mc->mc_mx.mx_handler = mlx_pause_done;
1488 mc->mc_mx.mx_dv = mlx->mlx_dv;
1489
1490 mlx_ccb_enqueue(mlx, mc);
1491 }
1492 }
1493 }
1494
1495 static void
1496 mlx_pause_done(struct mlx_ccb *mc)
1497 {
1498 struct mlx_softc *mlx;
1499 int command, channel;
1500
1501 mlx = device_private(mc->mc_mx.mx_dv);
1502 command = mc->mc_mbox[0];
1503 channel = mc->mc_mbox[2] & 0xf;
1504
1505 if (mc->mc_status != 0)
1506 aprint_error_dev(mlx->mlx_dv, "%s command failed - %s\n",
1507 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume",
1508 mlx_ccb_diagnose(mc));
1509 else if (command == MLX_CMD_STOPCHANNEL)
1510 printf("%s: channel %d pausing for %ld seconds\n",
1511 device_xname(mlx->mlx_dv), channel,
1512 (long)(mlx->mlx_pause.mp_howlong - time_second));
1513 else
1514 printf("%s: channel %d resuming\n", device_xname(mlx->mlx_dv),
1515 channel);
1516
1517 mlx_ccb_free(mlx, mc);
1518 }
1519
1520 /*
1521 * Perform an Enquiry command using a type-3 command buffer and a return a
1522 * single linear result buffer. If the completion function is specified, it
1523 * will be called with the completed command (and the result response will
1524 * not be valid until that point). Otherwise, the command will either be
1525 * busy-waited for (interrupts must be blocked), or slept for.
1526 */
1527 static void *
1528 mlx_enquire(struct mlx_softc *mlx, int command, size_t bufsize,
1529 void (*handler)(struct mlx_ccb *mc), int waitok)
1530 {
1531 struct mlx_ccb *mc;
1532 void *result;
1533 int rv, mapped;
1534
1535 result = NULL;
1536 mapped = 0;
1537
1538 if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0)
1539 goto out;
1540
1541 result = malloc(bufsize, M_DEVBUF, waitok ? M_WAITOK : M_NOWAIT);
1542 if (result == NULL) {
1543 printf("mlx_enquire: malloc() failed\n");
1544 goto out;
1545 }
1546 if ((rv = mlx_ccb_map(mlx, mc, result, bufsize, MC_XFER_IN)) != 0)
1547 goto out;
1548 mapped = 1;
1549 if (mc->mc_nsgent != 1) {
1550 printf("mlx_enquire: too many segs\n");
1551 goto out;
1552 }
1553
1554 /* Build an enquiry command. */
1555 mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_xfer_phys, 0);
1556
1557 /* Do we want a completion callback? */
1558 if (handler != NULL) {
1559 mc->mc_mx.mx_context = result;
1560 mc->mc_mx.mx_dv = mlx->mlx_dv;
1561 mc->mc_mx.mx_handler = handler;
1562 mlx_ccb_enqueue(mlx, mc);
1563 } else {
1564 /* Run the command in either polled or wait mode. */
1565 if (waitok)
1566 rv = mlx_ccb_wait(mlx, mc);
1567 else
1568 rv = mlx_ccb_poll(mlx, mc, 5000);
1569 }
1570
1571 out:
1572 /* We got a command, but nobody else will free it. */
1573 if (handler == NULL && mc != NULL) {
1574 if (mapped)
1575 mlx_ccb_unmap(mlx, mc);
1576 mlx_ccb_free(mlx, mc);
1577 }
1578
1579 /* We got an error, and we allocated a result. */
1580 if (rv != 0 && result != NULL) {
1581 if (mc != NULL)
1582 mlx_ccb_free(mlx, mc);
1583 free(result, M_DEVBUF);
1584 result = NULL;
1585 }
1586
1587 return (result);
1588 }
1589
1590 /*
1591 * Perform a Flush command on the nominated controller.
1592 *
1593 * May be called with interrupts enabled or disabled; will not return until
1594 * the flush operation completes or fails.
1595 */
1596 int
1597 mlx_flush(struct mlx_softc *mlx, int async)
1598 {
1599 struct mlx_ccb *mc;
1600 int rv;
1601
1602 if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0)
1603 goto out;
1604
1605 /* Build a flush command and fire it off. */
1606 mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1607
1608 if (async)
1609 rv = mlx_ccb_wait(mlx, mc);
1610 else
1611 rv = mlx_ccb_poll(mlx, mc, MLX_TIMEOUT * 1000);
1612 if (rv != 0)
1613 goto out;
1614
1615 /* Command completed OK? */
1616 if (mc->mc_status != 0) {
1617 aprint_error_dev(mlx->mlx_dv, "FLUSH failed - %s\n",
1618 mlx_ccb_diagnose(mc));
1619 rv = EIO;
1620 }
1621 out:
1622 if (mc != NULL)
1623 mlx_ccb_free(mlx, mc);
1624
1625 return (rv);
1626 }
1627
1628 /*
1629 * Start a background consistency check on (drive).
1630 */
1631 static int
1632 mlx_check(struct mlx_softc *mlx, int drive)
1633 {
1634 struct mlx_ccb *mc;
1635 int rv;
1636
1637 /* Get ourselves a command buffer. */
1638 rv = 0x10000;
1639
1640 if (mlx_ccb_alloc(mlx, &mc, 1) != 0)
1641 goto out;
1642
1643 /* Build a checkasync command, set the "fix it" flag. */
1644 mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80,
1645 0, 0);
1646
1647 /* Start the command and wait for it to be returned. */
1648 if (mlx_ccb_wait(mlx, mc) != 0)
1649 goto out;
1650
1651 /* Command completed OK? */
1652 if (mc->mc_status != 0)
1653 aprint_error_dev(mlx->mlx_dv, "CHECK ASYNC failed - %s\n",
1654 mlx_ccb_diagnose(mc));
1655 else
1656 printf("%s: consistency check started",
1657 device_xname(mlx->mlx_sysdrive[drive].ms_dv));
1658
1659 rv = mc->mc_status;
1660 out:
1661 if (mc != NULL)
1662 mlx_ccb_free(mlx, mc);
1663
1664 return (rv);
1665 }
1666
1667 /*
1668 * Start a background rebuild of the physical drive at (channel),(target).
1669 *
1670 * May be called with interrupts enabled or disabled; will return as soon as
1671 * the operation has started or been refused.
1672 */
1673 static int
1674 mlx_rebuild(struct mlx_softc *mlx, int channel, int target)
1675 {
1676 struct mlx_ccb *mc;
1677 int error;
1678
1679 error = 0x10000;
1680 if (mlx_ccb_alloc(mlx, &mc, 1) != 0)
1681 goto out;
1682
1683 /* Build a rebuildasync command, set the "fix it" flag. */
1684 mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0,
1685 0, 0);
1686
1687 /* Start the command and wait for it to be returned. */
1688 if (mlx_ccb_wait(mlx, mc) != 0)
1689 goto out;
1690
1691 /* Command completed OK? */
1692 if (mc->mc_status != 0)
1693 aprint_normal_dev(mlx->mlx_dv, "REBUILD ASYNC failed - %s\n",
1694 mlx_ccb_diagnose(mc));
1695 else
1696 aprint_normal_dev(mlx->mlx_dv, "rebuild started for %d:%d\n",
1697 channel, target);
1698
1699 error = mc->mc_status;
1700
1701 out:
1702 if (mc != NULL)
1703 mlx_ccb_free(mlx, mc);
1704
1705 return (error);
1706 }
1707
1708 /*
1709 * Take a command from user-space and try to run it.
1710 *
1711 * XXX Note that this can't perform very much in the way of error checking,
1712 * XXX and as such, applications _must_ be considered trustworthy.
1713 *
1714 * XXX Commands using S/G for data are not supported.
1715 */
1716 static int
1717 mlx_user_command(struct mlx_softc *mlx, struct mlx_usercommand *mu)
1718 {
1719 struct mlx_ccb *mc;
1720 struct mlx_dcdb *dcdb;
1721 void *kbuf;
1722 int rv, mapped;
1723
1724 if ((mu->mu_bufdir & ~MU_XFER_MASK) != 0)
1725 return (EINVAL);
1726
1727 kbuf = NULL;
1728 dcdb = NULL;
1729 mapped = 0;
1730
1731 /* Get ourselves a command and copy in from user space. */
1732 if ((rv = mlx_ccb_alloc(mlx, &mc, 1)) != 0) {
1733 DPRINTF(("mlx_user_command: mlx_ccb_alloc = %d\n", rv));
1734 goto out;
1735 }
1736
1737 memcpy(mc->mc_mbox, mu->mu_command, sizeof(mc->mc_mbox));
1738
1739 /*
1740 * If we need a buffer for data transfer, allocate one and copy in
1741 * its initial contents.
1742 */
1743 if (mu->mu_datasize > 0) {
1744 if (mu->mu_datasize > MAXPHYS)
1745 return (EINVAL);
1746
1747 kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK);
1748 if (kbuf == NULL) {
1749 DPRINTF(("mlx_user_command: malloc = NULL\n"));
1750 rv = ENOMEM;
1751 goto out;
1752 }
1753
1754 if ((mu->mu_bufdir & MU_XFER_OUT) != 0) {
1755 rv = copyin(mu->mu_buf, kbuf, mu->mu_datasize);
1756 if (rv != 0) {
1757 DPRINTF(("mlx_user_command: copyin = %d\n",
1758 rv));
1759 goto out;
1760 }
1761 }
1762
1763 /* Map the buffer so the controller can see it. */
1764 rv = mlx_ccb_map(mlx, mc, kbuf, mu->mu_datasize, mu->mu_bufdir);
1765 if (rv != 0) {
1766 DPRINTF(("mlx_user_command: mlx_ccb_map = %d\n", rv));
1767 goto out;
1768 }
1769 if (mc->mc_nsgent > 1) {
1770 DPRINTF(("mlx_user_command: too many s/g entries\n"));
1771 rv = EFBIG;
1772 goto out;
1773 }
1774 mapped = 1;
1775 /*
1776 * If this is a passthrough SCSI command, the DCDB is packed at
1777 * the beginning of the data area. Fix up the DCDB to point to
1778 * the correct physical address and override any bufptr
1779 * supplied by the caller since we know what it's meant to be.
1780 */
1781 if (mc->mc_mbox[0] == MLX_CMD_DIRECT_CDB) {
1782 dcdb = (struct mlx_dcdb *)kbuf;
1783 dcdb->dcdb_physaddr = mc->mc_xfer_phys + sizeof(*dcdb);
1784 mu->mu_bufptr = 8;
1785 }
1786 }
1787
1788
1789 /*
1790 * If there's a data buffer, fix up the command's buffer pointer.
1791 */
1792 if (mu->mu_datasize > 0) {
1793 /* Range check the pointer to physical buffer address. */
1794 if (mu->mu_bufptr < 0 ||
1795 mu->mu_bufptr > sizeof(mu->mu_command) - 4) {
1796 DPRINTF(("mlx_user_command: bufptr botch\n"));
1797 rv = EINVAL;
1798 goto out;
1799 }
1800
1801 mc->mc_mbox[mu->mu_bufptr] = mc->mc_xfer_phys;
1802 mc->mc_mbox[mu->mu_bufptr+1] = mc->mc_xfer_phys >> 8;
1803 mc->mc_mbox[mu->mu_bufptr+2] = mc->mc_xfer_phys >> 16;
1804 mc->mc_mbox[mu->mu_bufptr+3] = mc->mc_xfer_phys >> 24;
1805 }
1806
1807 /* Submit the command and wait. */
1808 if ((rv = mlx_ccb_wait(mlx, mc)) != 0) {
1809 #ifdef DEBUG
1810 printf("mlx_user_command: mlx_ccb_wait = %d\n", rv);
1811 #endif
1812 }
1813
1814 out:
1815 if (mc != NULL) {
1816 /* Copy out status and data */
1817 mu->mu_status = mc->mc_status;
1818 if (mapped)
1819 mlx_ccb_unmap(mlx, mc);
1820 mlx_ccb_free(mlx, mc);
1821 }
1822
1823 if (kbuf != NULL) {
1824 if (mu->mu_datasize > 0 && (mu->mu_bufdir & MU_XFER_IN) != 0) {
1825 rv = copyout(kbuf, mu->mu_buf, mu->mu_datasize);
1826 #ifdef DIAGNOSTIC
1827 if (rv != 0)
1828 printf("mlx_user_command: copyout = %d\n", rv);
1829 #endif
1830 }
1831 }
1832 if (kbuf != NULL)
1833 free(kbuf, M_DEVBUF);
1834
1835 return (rv);
1836 }
1837
1838 /*
1839 * Allocate and initialise a CCB.
1840 */
1841 int
1842 mlx_ccb_alloc(struct mlx_softc *mlx, struct mlx_ccb **mcp, int control)
1843 {
1844 struct mlx_ccb *mc;
1845 int s;
1846
1847 s = splbio();
1848 mc = SLIST_FIRST(&mlx->mlx_ccb_freelist);
1849 if (control) {
1850 if (mlx->mlx_nccbs_ctrl >= MLX_NCCBS_CONTROL) {
1851 splx(s);
1852 *mcp = NULL;
1853 return (EAGAIN);
1854 }
1855 mc->mc_flags |= MC_CONTROL;
1856 mlx->mlx_nccbs_ctrl++;
1857 }
1858 SLIST_REMOVE_HEAD(&mlx->mlx_ccb_freelist, mc_chain.slist);
1859 splx(s);
1860
1861 *mcp = mc;
1862 return (0);
1863 }
1864
1865 /*
1866 * Free a CCB.
1867 */
1868 void
1869 mlx_ccb_free(struct mlx_softc *mlx, struct mlx_ccb *mc)
1870 {
1871 int s;
1872
1873 s = splbio();
1874 if ((mc->mc_flags & MC_CONTROL) != 0)
1875 mlx->mlx_nccbs_ctrl--;
1876 mc->mc_flags = 0;
1877 SLIST_INSERT_HEAD(&mlx->mlx_ccb_freelist, mc, mc_chain.slist);
1878 splx(s);
1879 }
1880
1881 /*
1882 * If a CCB is specified, enqueue it. Pull CCBs off the software queue in
1883 * the order that they were enqueued and try to submit their mailboxes to
1884 * the controller for execution.
1885 */
1886 void
1887 mlx_ccb_enqueue(struct mlx_softc *mlx, struct mlx_ccb *mc)
1888 {
1889 int s;
1890
1891 s = splbio();
1892
1893 if (mc != NULL)
1894 SIMPLEQ_INSERT_TAIL(&mlx->mlx_ccb_queue, mc, mc_chain.simpleq);
1895
1896 while ((mc = SIMPLEQ_FIRST(&mlx->mlx_ccb_queue)) != NULL) {
1897 if (mlx_ccb_submit(mlx, mc) != 0)
1898 break;
1899 SIMPLEQ_REMOVE_HEAD(&mlx->mlx_ccb_queue, mc_chain.simpleq);
1900 TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
1901 }
1902
1903 splx(s);
1904 }
1905
1906 /*
1907 * Map the specified CCB's data buffer onto the bus, and fill the
1908 * scatter-gather list.
1909 */
1910 int
1911 mlx_ccb_map(struct mlx_softc *mlx, struct mlx_ccb *mc, void *data, int size,
1912 int dir)
1913 {
1914 struct mlx_sgentry *sge;
1915 int nsegs, i, rv, sgloff;
1916 bus_dmamap_t xfer;
1917
1918 xfer = mc->mc_xfer_map;
1919
1920 rv = bus_dmamap_load(mlx->mlx_dmat, xfer, data, size, NULL,
1921 BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1922 ((dir & MC_XFER_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
1923 if (rv != 0)
1924 return (rv);
1925
1926 nsegs = xfer->dm_nsegs;
1927 mc->mc_xfer_size = size;
1928 mc->mc_flags |= dir;
1929 mc->mc_nsgent = nsegs;
1930 mc->mc_xfer_phys = xfer->dm_segs[0].ds_addr;
1931
1932 sgloff = MLX_SGL_SIZE * mc->mc_ident;
1933 sge = (struct mlx_sgentry *)((char *)mlx->mlx_sgls + sgloff);
1934
1935 for (i = 0; i < nsegs; i++, sge++) {
1936 sge->sge_addr = htole32(xfer->dm_segs[i].ds_addr);
1937 sge->sge_count = htole32(xfer->dm_segs[i].ds_len);
1938 }
1939
1940 if ((dir & MC_XFER_OUT) != 0)
1941 i = BUS_DMASYNC_PREWRITE;
1942 else
1943 i = 0;
1944 if ((dir & MC_XFER_IN) != 0)
1945 i |= BUS_DMASYNC_PREREAD;
1946
1947 bus_dmamap_sync(mlx->mlx_dmat, xfer, 0, mc->mc_xfer_size, i);
1948 bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap, sgloff,
1949 MLX_SGL_SIZE, BUS_DMASYNC_PREWRITE);
1950
1951 return (0);
1952 }
1953
1954 /*
1955 * Unmap the specified CCB's data buffer.
1956 */
1957 void
1958 mlx_ccb_unmap(struct mlx_softc *mlx, struct mlx_ccb *mc)
1959 {
1960 int i;
1961
1962 bus_dmamap_sync(mlx->mlx_dmat, mlx->mlx_dmamap,
1963 MLX_SGL_SIZE * mc->mc_ident, MLX_SGL_SIZE,
1964 BUS_DMASYNC_POSTWRITE);
1965
1966 if ((mc->mc_flags & MC_XFER_OUT) != 0)
1967 i = BUS_DMASYNC_POSTWRITE;
1968 else
1969 i = 0;
1970 if ((mc->mc_flags & MC_XFER_IN) != 0)
1971 i |= BUS_DMASYNC_POSTREAD;
1972
1973 bus_dmamap_sync(mlx->mlx_dmat, mc->mc_xfer_map, 0, mc->mc_xfer_size, i);
1974 bus_dmamap_unload(mlx->mlx_dmat, mc->mc_xfer_map);
1975 }
1976
1977 /*
1978 * Submit the CCB, and busy-wait for it to complete. Return non-zero on
1979 * timeout or submission error. Must be called with interrupts blocked.
1980 */
1981 int
1982 mlx_ccb_poll(struct mlx_softc *mlx, struct mlx_ccb *mc, int timo)
1983 {
1984 int rv;
1985
1986 mc->mc_mx.mx_handler = NULL;
1987
1988 if ((rv = mlx_ccb_submit(mlx, mc)) != 0)
1989 return (rv);
1990 TAILQ_INSERT_TAIL(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
1991
1992 for (timo *= 10; timo != 0; timo--) {
1993 mlx_intr(mlx);
1994 if (mc->mc_status != MLX_STATUS_BUSY)
1995 break;
1996 DELAY(100);
1997 }
1998
1999 if (timo != 0) {
2000 if (mc->mc_status != 0) {
2001 aprint_error_dev(mlx->mlx_dv, "command failed - %s\n",
2002 mlx_ccb_diagnose(mc));
2003 rv = EIO;
2004 } else
2005 rv = 0;
2006 } else {
2007 printf("%s: command timed out\n", device_xname(mlx->mlx_dv));
2008 rv = EIO;
2009 }
2010
2011 return (rv);
2012 }
2013
2014 /*
2015 * Enqueue the CCB, and sleep until it completes. Return non-zero on
2016 * timeout or error.
2017 */
2018 int
2019 mlx_ccb_wait(struct mlx_softc *mlx, struct mlx_ccb *mc)
2020 {
2021 int s;
2022
2023 mc->mc_flags |= MC_WAITING;
2024 mc->mc_mx.mx_handler = NULL;
2025
2026 s = splbio();
2027 mlx_ccb_enqueue(mlx, mc);
2028 tsleep(mc, PRIBIO, "mlxwccb", 0);
2029 splx(s);
2030
2031 if (mc->mc_status != 0) {
2032 aprint_error_dev(mlx->mlx_dv, "command failed - %s\n",
2033 mlx_ccb_diagnose(mc));
2034 return (EIO);
2035 }
2036
2037 return (0);
2038 }
2039
2040 /*
2041 * Try to submit a CCB's mailbox to the controller for execution. Return
2042 * non-zero on timeout or error. Must be called with interrupts blocked.
2043 */
2044 static int
2045 mlx_ccb_submit(struct mlx_softc *mlx, struct mlx_ccb *mc)
2046 {
2047 int i, s, r;
2048
2049 /* Save the ident so we can handle this command when complete. */
2050 mc->mc_mbox[1] = (u_int8_t)(mc->mc_ident + 1);
2051
2052 /* Mark the command as currently being processed. */
2053 mc->mc_status = MLX_STATUS_BUSY;
2054 mc->mc_expiry = time_second + MLX_TIMEOUT;
2055
2056 /* Spin waiting for the mailbox. */
2057 for (i = 100; i != 0; i--) {
2058 s = splbio();
2059 r = (*mlx->mlx_submit)(mlx, mc);
2060 splx(s);
2061 if (r != 0)
2062 break;
2063 DELAY(100);
2064 }
2065 if (i != 0)
2066 return (0);
2067
2068 DPRINTF(("mlx_ccb_submit: rejected; queueing\n"));
2069 mc->mc_status = MLX_STATUS_WEDGED;
2070 return (EIO);
2071 }
2072
2073 /*
2074 * Return a string that describes why a command has failed.
2075 */
2076 const char *
2077 mlx_ccb_diagnose(struct mlx_ccb *mc)
2078 {
2079 static char tbuf[80];
2080 int i;
2081
2082 for (i = 0; i < sizeof(mlx_msgs) / sizeof(mlx_msgs[0]); i++)
2083 if ((mc->mc_mbox[0] == mlx_msgs[i].command ||
2084 mlx_msgs[i].command == 0) &&
2085 mc->mc_status == mlx_msgs[i].status) {
2086 snprintf(tbuf, sizeof(tbuf), "%s (0x%x)",
2087 mlx_status_msgs[mlx_msgs[i].msg], mc->mc_status);
2088 return (tbuf);
2089 }
2090
2091 snprintf(tbuf, sizeof(tbuf), "unknown response 0x%x for command 0x%x",
2092 (int)mc->mc_status, (int)mc->mc_mbox[0]);
2093
2094 return (tbuf);
2095 }
2096
2097 /*
2098 * Poll the controller for completed commands. Returns non-zero if one or
2099 * more commands were completed. Must be called with interrupts blocked.
2100 */
2101 int
2102 mlx_intr(void *cookie)
2103 {
2104 struct mlx_softc *mlx;
2105 struct mlx_ccb *mc;
2106 int result;
2107 u_int ident, status;
2108
2109 mlx = cookie;
2110 result = 0;
2111
2112 while ((*mlx->mlx_findcomplete)(mlx, &ident, &status) != 0) {
2113 result = 1;
2114 ident--;
2115
2116 if (ident >= MLX_MAX_QUEUECNT) {
2117 aprint_error_dev(mlx->mlx_dv,
2118 "bad completion returned\n");
2119 continue;
2120 }
2121
2122 mc = mlx->mlx_ccbs + ident;
2123
2124 if (mc->mc_status != MLX_STATUS_BUSY) {
2125 aprint_error_dev(mlx->mlx_dv,
2126 "bad completion returned\n");
2127 continue;
2128 }
2129
2130 TAILQ_REMOVE(&mlx->mlx_ccb_worklist, mc, mc_chain.tailq);
2131
2132 /* Record status and notify the initiator, if requested. */
2133 mc->mc_status = status;
2134 if (mc->mc_mx.mx_handler != NULL)
2135 (*mc->mc_mx.mx_handler)(mc);
2136 else if ((mc->mc_flags & MC_WAITING) != 0)
2137 wakeup(mc);
2138 }
2139
2140 /* If we've completed any commands, try posting some more. */
2141 if (result)
2142 mlx_ccb_enqueue(mlx, NULL);
2143
2144 return (result);
2145 }
2146
2147 /*
2148 * Emit a string describing the firmware handshake status code, and return a
2149 * flag indicating whether the code represents a fatal error.
2150 *
2151 * Error code interpretations are from the Linux driver, and don't directly
2152 * match the messages printed by Mylex's BIOS. This may change if
2153 * documentation on the codes is forthcoming.
2154 */
2155 static int
2156 mlx_fw_message(struct mlx_softc *mlx, int error, int param1, int param2)
2157 {
2158 const char *fmt;
2159
2160 switch (error) {
2161 case 0x00:
2162 fmt = "physical drive %d:%d not responding";
2163 break;
2164
2165 case 0x08:
2166 /*
2167 * We could be neater about this and give some indication
2168 * when we receive more of them.
2169 */
2170 if ((mlx->mlx_flags & MLXF_SPINUP_REPORTED) == 0) {
2171 printf("%s: spinning up drives...\n",
2172 device_xname(mlx->mlx_dv));
2173 mlx->mlx_flags |= MLXF_SPINUP_REPORTED;
2174 }
2175 return (0);
2176
2177 case 0x30:
2178 fmt = "configuration checksum error";
2179 break;
2180
2181 case 0x60:
2182 fmt = "mirror race recovery failed";
2183 break;
2184
2185 case 0x70:
2186 fmt = "mirror race recovery in progress";
2187 break;
2188
2189 case 0x90:
2190 fmt = "physical drive %d:%d COD mismatch";
2191 break;
2192
2193 case 0xa0:
2194 fmt = "logical drive installation aborted";
2195 break;
2196
2197 case 0xb0:
2198 fmt = "mirror race on a critical system drive";
2199 break;
2200
2201 case 0xd0:
2202 fmt = "new controller configuration found";
2203 break;
2204
2205 case 0xf0:
2206 aprint_error_dev(mlx->mlx_dv, "FATAL MEMORY PARITY ERROR\n");
2207 return (1);
2208
2209 default:
2210 aprint_error_dev(mlx->mlx_dv,
2211 "unknown firmware init error %02x:%02x:%02x\n",
2212 error, param1, param2);
2213 return (0);
2214 }
2215
2216 aprint_normal_dev(mlx->mlx_dv, fmt, param2, param1);
2217 aprint_normal("\n");
2218
2219 return (0);
2220 }
2221
2222 MODULE(MODULE_CLASS_DRIVER, mlx, NULL);
2223
2224 #ifdef _MODULE
2225 CFDRIVER_DECL(cac, DV_DISK, NULL);
2226 #endif
2227
2228 static int
2229 mlx_modcmd(modcmd_t cmd, void *opaque)
2230 {
2231 int error = 0;
2232
2233 #ifdef _MODULE
2234 switch (cmd) {
2235 case MODULE_CMD_INIT:
2236 error = config_cfdriver_attach(&mlx_cd);
2237 break;
2238 case MODULE_CMD_FINI:
2239 error = config_cfdriver_detach(&mlx_cd);
2240 break;
2241 default:
2242 error = ENOTTY;
2243 break;
2244 }
2245 #endif
2246 return error;
2247 }
2248