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