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