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