1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 1999 Michael Smith
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD$
29 */
30
31 /*
32 * Driver for the Mylex DAC960 family of RAID controllers.
33 */
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/bio.h>
38 #include <sys/lock.h>
39 #include <sys/malloc.h>
40 #include <sys/mutex.h>
41 #include <sys/kernel.h>
42 #include <sys/sx.h>
43
44 #include <sys/bus.h>
45 #include <sys/conf.h>
46 #include <sys/stat.h>
47
48 #include <machine/resource.h>
49 #include <machine/bus.h>
50 #include <machine/clock.h>
51 #include <sys/rman.h>
52
53 #include <geom/geom_disk.h>
54
55 #include <dev/mlx/mlxio.h>
56 #include <dev/mlx/mlxvar.h>
57 #include <dev/mlx/mlxreg.h>
58
59 static struct cdevsw mlx_cdevsw = {
60 .d_version = D_VERSION,
61 .d_open = mlx_open,
62 .d_close = mlx_close,
63 .d_ioctl = mlx_ioctl,
64 .d_name = "mlx",
65 };
66
67 devclass_t mlx_devclass;
68
69 /*
70 * Per-interface accessor methods
71 */
72 static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
73 static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
74 static void mlx_v3_intaction(struct mlx_softc *sc, int action);
75 static int mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first);
76
77 static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
78 static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
79 static void mlx_v4_intaction(struct mlx_softc *sc, int action);
80 static int mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first);
81
82 static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
83 static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
84 static void mlx_v5_intaction(struct mlx_softc *sc, int action);
85 static int mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2, int first);
86
87 /*
88 * Status monitoring
89 */
90 static void mlx_periodic(void *data);
91 static void mlx_periodic_enquiry(struct mlx_command *mc);
92 static void mlx_periodic_eventlog_poll(struct mlx_softc *sc);
93 static void mlx_periodic_eventlog_respond(struct mlx_command *mc);
94 static void mlx_periodic_rebuild(struct mlx_command *mc);
95
96 /*
97 * Channel Pause
98 */
99 static void mlx_pause_action(struct mlx_softc *sc);
100 static void mlx_pause_done(struct mlx_command *mc);
101
102 /*
103 * Command submission.
104 */
105 static void *mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize,
106 void (*complete)(struct mlx_command *mc));
107 static int mlx_flush(struct mlx_softc *sc);
108 static int mlx_check(struct mlx_softc *sc, int drive);
109 static int mlx_rebuild(struct mlx_softc *sc, int channel, int target);
110 static int mlx_wait_command(struct mlx_command *mc);
111 static int mlx_poll_command(struct mlx_command *mc);
112 void mlx_startio_cb(void *arg,
113 bus_dma_segment_t *segs,
114 int nsegments, int error);
115 static void mlx_startio(struct mlx_softc *sc);
116 static void mlx_completeio(struct mlx_command *mc);
117 static int mlx_user_command(struct mlx_softc *sc,
118 struct mlx_usercommand *mu);
119 void mlx_user_cb(void *arg, bus_dma_segment_t *segs,
120 int nsegments, int error);
121
122 /*
123 * Command buffer allocation.
124 */
125 static struct mlx_command *mlx_alloccmd(struct mlx_softc *sc);
126 static void mlx_releasecmd(struct mlx_command *mc);
127 static void mlx_freecmd(struct mlx_command *mc);
128
129 /*
130 * Command management.
131 */
132 static int mlx_getslot(struct mlx_command *mc);
133 static void mlx_setup_dmamap(struct mlx_command *mc,
134 bus_dma_segment_t *segs,
135 int nsegments, int error);
136 static void mlx_unmapcmd(struct mlx_command *mc);
137 static int mlx_shutdown_locked(struct mlx_softc *sc);
138 static int mlx_start(struct mlx_command *mc);
139 static int mlx_done(struct mlx_softc *sc, int startio);
140 static void mlx_complete(struct mlx_softc *sc);
141
142 /*
143 * Debugging.
144 */
145 static char *mlx_diagnose_command(struct mlx_command *mc);
146 static void mlx_describe_controller(struct mlx_softc *sc);
147 static int mlx_fw_message(struct mlx_softc *sc, int status, int param1, int param2);
148
149 /*
150 * Utility functions.
151 */
152 static struct mlx_sysdrive *mlx_findunit(struct mlx_softc *sc, int unit);
153
154 /********************************************************************************
155 ********************************************************************************
156 Public Interfaces
157 ********************************************************************************
158 ********************************************************************************/
159
160 /********************************************************************************
161 * Free all of the resources associated with (sc)
162 *
163 * Should not be called if the controller is active.
164 */
165 void
mlx_free(struct mlx_softc * sc)166 mlx_free(struct mlx_softc *sc)
167 {
168 struct mlx_command *mc;
169
170 debug_called(1);
171
172 /* destroy control device */
173 if (sc->mlx_dev_t != NULL)
174 destroy_dev(sc->mlx_dev_t);
175
176 if (sc->mlx_intr)
177 bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr);
178
179 /* cancel status timeout */
180 MLX_IO_LOCK(sc);
181 callout_stop(&sc->mlx_timeout);
182
183 /* throw away any command buffers */
184 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
185 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
186 mlx_freecmd(mc);
187 }
188 MLX_IO_UNLOCK(sc);
189 callout_drain(&sc->mlx_timeout);
190
191 /* destroy data-transfer DMA tag */
192 if (sc->mlx_buffer_dmat)
193 bus_dma_tag_destroy(sc->mlx_buffer_dmat);
194
195 /* free and destroy DMA memory and tag for s/g lists */
196 if (sc->mlx_sgbusaddr)
197 bus_dmamap_unload(sc->mlx_sg_dmat, sc->mlx_sg_dmamap);
198 if (sc->mlx_sgtable)
199 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
200 if (sc->mlx_sg_dmat)
201 bus_dma_tag_destroy(sc->mlx_sg_dmat);
202
203 /* disconnect the interrupt handler */
204 if (sc->mlx_irq != NULL)
205 bus_release_resource(sc->mlx_dev, SYS_RES_IRQ, 0, sc->mlx_irq);
206
207 /* destroy the parent DMA tag */
208 if (sc->mlx_parent_dmat)
209 bus_dma_tag_destroy(sc->mlx_parent_dmat);
210
211 /* release the register window mapping */
212 if (sc->mlx_mem != NULL)
213 bus_release_resource(sc->mlx_dev, sc->mlx_mem_type, sc->mlx_mem_rid, sc->mlx_mem);
214
215 /* free controller enquiry data */
216 if (sc->mlx_enq2 != NULL)
217 free(sc->mlx_enq2, M_DEVBUF);
218
219 sx_destroy(&sc->mlx_config_lock);
220 mtx_destroy(&sc->mlx_io_lock);
221 }
222
223 /********************************************************************************
224 * Map the scatter/gather table into bus space
225 */
226 static void
mlx_dma_map_sg(void * arg,bus_dma_segment_t * segs,int nseg,int error)227 mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
228 {
229 struct mlx_softc *sc = (struct mlx_softc *)arg;
230
231 debug_called(1);
232
233 /* save base of s/g table's address in bus space */
234 sc->mlx_sgbusaddr = segs->ds_addr;
235 }
236
237 static int
mlx_sglist_map(struct mlx_softc * sc)238 mlx_sglist_map(struct mlx_softc *sc)
239 {
240 size_t segsize;
241 int error, ncmd;
242
243 debug_called(1);
244
245 /* destroy any existing mappings */
246 if (sc->mlx_sgbusaddr)
247 bus_dmamap_unload(sc->mlx_sg_dmat, sc->mlx_sg_dmamap);
248 if (sc->mlx_sgtable)
249 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
250 if (sc->mlx_sg_dmat)
251 bus_dma_tag_destroy(sc->mlx_sg_dmat);
252 sc->mlx_sgbusaddr = 0;
253 sc->mlx_sgtable = NULL;
254 sc->mlx_sg_dmat = NULL;
255
256 /*
257 * Create a single tag describing a region large enough to hold all of
258 * the s/g lists we will need. If we're called early on, we don't know how
259 * many commands we're going to be asked to support, so only allocate enough
260 * for a couple.
261 */
262 if (sc->mlx_enq2 == NULL) {
263 ncmd = 2;
264 } else {
265 ncmd = sc->mlx_enq2->me_max_commands;
266 }
267 segsize = sizeof(struct mlx_sgentry) * MLX_NSEG * ncmd;
268 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
269 1, 0, /* alignment,boundary */
270 BUS_SPACE_MAXADDR, /* lowaddr */
271 BUS_SPACE_MAXADDR, /* highaddr */
272 NULL, NULL, /* filter, filterarg */
273 segsize, 1, /* maxsize, nsegments */
274 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
275 0, /* flags */
276 NULL, NULL, /* lockfunc, lockarg */
277 &sc->mlx_sg_dmat);
278 if (error != 0) {
279 device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
280 return(ENOMEM);
281 }
282
283 /*
284 * Allocate enough s/g maps for all commands and permanently map them into
285 * controller-visible space.
286 *
287 * XXX this assumes we can get enough space for all the s/g maps in one
288 * contiguous slab. We may need to switch to a more complex arrangement
289 * where we allocate in smaller chunks and keep a lookup table from slot
290 * to bus address.
291 */
292 error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable,
293 BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
294 if (error) {
295 device_printf(sc->mlx_dev, "can't allocate s/g table\n");
296 return(ENOMEM);
297 }
298 (void)bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable,
299 segsize, mlx_dma_map_sg, sc, 0);
300 return(0);
301 }
302
303 /********************************************************************************
304 * Initialise the controller and softc
305 */
306 int
mlx_attach(struct mlx_softc * sc)307 mlx_attach(struct mlx_softc *sc)
308 {
309 struct mlx_enquiry_old *meo;
310 int rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
311
312 debug_called(1);
313
314 /*
315 * Initialise per-controller queues.
316 */
317 TAILQ_INIT(&sc->mlx_work);
318 TAILQ_INIT(&sc->mlx_freecmds);
319 bioq_init(&sc->mlx_bioq);
320
321 /*
322 * Select accessor methods based on controller interface type.
323 */
324 switch(sc->mlx_iftype) {
325 case MLX_IFTYPE_2:
326 case MLX_IFTYPE_3:
327 sc->mlx_tryqueue = mlx_v3_tryqueue;
328 sc->mlx_findcomplete = mlx_v3_findcomplete;
329 sc->mlx_intaction = mlx_v3_intaction;
330 sc->mlx_fw_handshake = mlx_v3_fw_handshake;
331 break;
332 case MLX_IFTYPE_4:
333 sc->mlx_tryqueue = mlx_v4_tryqueue;
334 sc->mlx_findcomplete = mlx_v4_findcomplete;
335 sc->mlx_intaction = mlx_v4_intaction;
336 sc->mlx_fw_handshake = mlx_v4_fw_handshake;
337 break;
338 case MLX_IFTYPE_5:
339 sc->mlx_tryqueue = mlx_v5_tryqueue;
340 sc->mlx_findcomplete = mlx_v5_findcomplete;
341 sc->mlx_intaction = mlx_v5_intaction;
342 sc->mlx_fw_handshake = mlx_v5_fw_handshake;
343 break;
344 default:
345 return(ENXIO); /* should never happen */
346 }
347
348 /* disable interrupts before we start talking to the controller */
349 MLX_IO_LOCK(sc);
350 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
351 MLX_IO_UNLOCK(sc);
352
353 /*
354 * Wait for the controller to come ready, handshake with the firmware if required.
355 * This is typically only necessary on platforms where the controller BIOS does not
356 * run.
357 */
358 hsmsg = 0;
359 DELAY(1000);
360 while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2,
361 hsmsg == 0)) != 0) {
362 /* report first time around... */
363 if (hsmsg == 0) {
364 device_printf(sc->mlx_dev, "controller initialisation in progress...\n");
365 hsmsg = 1;
366 }
367 /* did we get a real message? */
368 if (hscode == 2) {
369 hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2);
370 /* fatal initialisation error? */
371 if (hscode != 0) {
372 return(ENXIO);
373 }
374 }
375 }
376 if (hsmsg == 1)
377 device_printf(sc->mlx_dev, "initialisation complete.\n");
378
379 /*
380 * Allocate and connect our interrupt.
381 */
382 rid = 0;
383 sc->mlx_irq = bus_alloc_resource_any(sc->mlx_dev, SYS_RES_IRQ, &rid,
384 RF_SHAREABLE | RF_ACTIVE);
385 if (sc->mlx_irq == NULL) {
386 device_printf(sc->mlx_dev, "can't allocate interrupt\n");
387 return(ENXIO);
388 }
389 error = bus_setup_intr(sc->mlx_dev, sc->mlx_irq, INTR_TYPE_BIO |
390 INTR_ENTROPY | INTR_MPSAFE, NULL, mlx_intr, sc, &sc->mlx_intr);
391 if (error) {
392 device_printf(sc->mlx_dev, "can't set up interrupt\n");
393 return(ENXIO);
394 }
395
396 /*
397 * Create DMA tag for mapping buffers into controller-addressable space.
398 */
399 error = bus_dma_tag_create(sc->mlx_parent_dmat, /* parent */
400 1, 0, /* align, boundary */
401 BUS_SPACE_MAXADDR, /* lowaddr */
402 BUS_SPACE_MAXADDR, /* highaddr */
403 NULL, NULL, /* filter, filterarg */
404 MLX_MAXPHYS, /* maxsize */
405 MLX_NSEG, /* nsegments */
406 BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
407 0, /* flags */
408 busdma_lock_mutex, /* lockfunc */
409 &sc->mlx_io_lock, /* lockarg */
410 &sc->mlx_buffer_dmat);
411 if (error != 0) {
412 device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
413 return(ENOMEM);
414 }
415
416 /*
417 * Create some initial scatter/gather mappings so we can run the probe
418 * commands.
419 */
420 error = mlx_sglist_map(sc);
421 if (error != 0) {
422 device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n");
423 return(error);
424 }
425
426 /*
427 * We don't (yet) know where the event log is up to.
428 */
429 sc->mlx_currevent = -1;
430
431 /*
432 * Obtain controller feature information
433 */
434 MLX_IO_LOCK(sc);
435 if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
436 MLX_IO_UNLOCK(sc);
437 device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
438 return(ENXIO);
439 }
440
441 /*
442 * Do quirk/feature related things.
443 */
444 fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
445 switch(sc->mlx_iftype) {
446 case MLX_IFTYPE_2:
447 /* These controllers don't report the firmware version in the ENQUIRY2 response */
448 if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) {
449 MLX_IO_UNLOCK(sc);
450 device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n");
451 return(ENXIO);
452 }
453 sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor;
454
455 /* XXX require 2.42 or better (PCI) */
456 if (meo->me_fwminor < 42) {
457 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
458 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 2.42 or later\n");
459 }
460 free(meo, M_DEVBUF);
461 break;
462 case MLX_IFTYPE_3:
463 /* XXX certify 3.52? */
464 if (fwminor < 51) {
465 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
466 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 3.51 or later\n");
467 }
468 break;
469 case MLX_IFTYPE_4:
470 /* XXX certify firmware versions? */
471 if (fwminor < 6) {
472 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
473 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
474 }
475 break;
476 case MLX_IFTYPE_5:
477 if (fwminor < 7) {
478 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
479 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
480 }
481 break;
482 default:
483 MLX_IO_UNLOCK(sc);
484 return(ENXIO); /* should never happen */
485 }
486 MLX_IO_UNLOCK(sc);
487
488 /*
489 * Create the final scatter/gather mappings now that we have characterised the controller.
490 */
491 error = mlx_sglist_map(sc);
492 if (error != 0) {
493 device_printf(sc->mlx_dev, "can't make final s/g list mapping\n");
494 return(error);
495 }
496
497 /*
498 * No user-requested background operation is in progress.
499 */
500 sc->mlx_background = 0;
501 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
502
503 /*
504 * Create the control device.
505 */
506 sc->mlx_dev_t = make_dev(&mlx_cdevsw, 0, UID_ROOT, GID_OPERATOR,
507 S_IRUSR | S_IWUSR, "mlx%d", device_get_unit(sc->mlx_dev));
508 sc->mlx_dev_t->si_drv1 = sc;
509
510 /*
511 * Start the timeout routine.
512 */
513 callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc);
514
515 /* print a little information about the controller */
516 mlx_describe_controller(sc);
517
518 return(0);
519 }
520
521 /********************************************************************************
522 * Locate disk resources and attach children to them.
523 */
524 void
mlx_startup(struct mlx_softc * sc)525 mlx_startup(struct mlx_softc *sc)
526 {
527 struct mlx_enq_sys_drive *mes;
528 struct mlx_sysdrive *dr;
529 int i, error;
530
531 debug_called(1);
532
533 /*
534 * Scan all the system drives and attach children for those that
535 * don't currently have them.
536 */
537 MLX_IO_LOCK(sc);
538 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
539 MLX_IO_UNLOCK(sc);
540 if (mes == NULL) {
541 device_printf(sc->mlx_dev, "error fetching drive status\n");
542 return;
543 }
544
545 /* iterate over drives returned */
546 MLX_CONFIG_LOCK(sc);
547 for (i = 0, dr = &sc->mlx_sysdrive[0];
548 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
549 i++, dr++) {
550 /* are we already attached to this drive? */
551 if (dr->ms_disk == 0) {
552 /* pick up drive information */
553 dr->ms_size = mes[i].sd_size;
554 dr->ms_raidlevel = mes[i].sd_raidlevel & 0xf;
555 dr->ms_state = mes[i].sd_state;
556
557 /* generate geometry information */
558 if (sc->mlx_geom == MLX_GEOM_128_32) {
559 dr->ms_heads = 128;
560 dr->ms_sectors = 32;
561 dr->ms_cylinders = dr->ms_size / (128 * 32);
562 } else { /* MLX_GEOM_255/63 */
563 dr->ms_heads = 255;
564 dr->ms_sectors = 63;
565 dr->ms_cylinders = dr->ms_size / (255 * 63);
566 }
567 dr->ms_disk = device_add_child(sc->mlx_dev, /*"mlxd"*/NULL, -1);
568 if (dr->ms_disk == 0)
569 device_printf(sc->mlx_dev, "device_add_child failed\n");
570 device_set_ivars(dr->ms_disk, dr);
571 }
572 }
573 free(mes, M_DEVBUF);
574 if ((error = bus_generic_attach(sc->mlx_dev)) != 0)
575 device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error);
576
577 /* mark controller back up */
578 MLX_IO_LOCK(sc);
579 sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
580
581 /* enable interrupts */
582 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
583 MLX_IO_UNLOCK(sc);
584 MLX_CONFIG_UNLOCK(sc);
585 }
586
587 /********************************************************************************
588 * Disconnect from the controller completely, in preparation for unload.
589 */
590 int
mlx_detach(device_t dev)591 mlx_detach(device_t dev)
592 {
593 struct mlx_softc *sc = device_get_softc(dev);
594 struct mlxd_softc *mlxd;
595 int i, error;
596
597 debug_called(1);
598
599 error = EBUSY;
600 MLX_CONFIG_LOCK(sc);
601 if (sc->mlx_state & MLX_STATE_OPEN)
602 goto out;
603
604 for (i = 0; i < MLX_MAXDRIVES; i++) {
605 if (sc->mlx_sysdrive[i].ms_disk != 0) {
606 mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
607 if (mlxd->mlxd_flags & MLXD_OPEN) { /* drive is mounted, abort detach */
608 device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n");
609 goto out;
610 }
611 }
612 }
613 if ((error = mlx_shutdown(dev)))
614 goto out;
615 MLX_CONFIG_UNLOCK(sc);
616
617 mlx_free(sc);
618
619 return (0);
620 out:
621 MLX_CONFIG_UNLOCK(sc);
622 return(error);
623 }
624
625 /********************************************************************************
626 * Bring the controller down to a dormant state and detach all child devices.
627 *
628 * This function is called before detach, system shutdown, or before performing
629 * an operation which may add or delete system disks. (Call mlx_startup to
630 * resume normal operation.)
631 *
632 * Note that we can assume that the bioq on the controller is empty, as we won't
633 * allow shutdown if any device is open.
634 */
635 int
mlx_shutdown(device_t dev)636 mlx_shutdown(device_t dev)
637 {
638 struct mlx_softc *sc = device_get_softc(dev);
639 int error;
640
641 MLX_CONFIG_LOCK(sc);
642 error = mlx_shutdown_locked(sc);
643 MLX_CONFIG_UNLOCK(sc);
644 return (error);
645 }
646
647 static int
mlx_shutdown_locked(struct mlx_softc * sc)648 mlx_shutdown_locked(struct mlx_softc *sc)
649 {
650 int i, error;
651
652 debug_called(1);
653
654 MLX_CONFIG_ASSERT_LOCKED(sc);
655
656 MLX_IO_LOCK(sc);
657 sc->mlx_state |= MLX_STATE_SHUTDOWN;
658 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
659
660 /* flush controller */
661 device_printf(sc->mlx_dev, "flushing cache...");
662 if (mlx_flush(sc)) {
663 printf("failed\n");
664 } else {
665 printf("done\n");
666 }
667 MLX_IO_UNLOCK(sc);
668
669 /* delete all our child devices */
670 for (i = 0; i < MLX_MAXDRIVES; i++) {
671 if (sc->mlx_sysdrive[i].ms_disk != 0) {
672 if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
673 return (error);
674 sc->mlx_sysdrive[i].ms_disk = 0;
675 }
676 }
677
678 return (0);
679 }
680
681 /********************************************************************************
682 * Bring the controller to a quiescent state, ready for system suspend.
683 */
684 int
mlx_suspend(device_t dev)685 mlx_suspend(device_t dev)
686 {
687 struct mlx_softc *sc = device_get_softc(dev);
688
689 debug_called(1);
690
691 MLX_IO_LOCK(sc);
692 sc->mlx_state |= MLX_STATE_SUSPEND;
693
694 /* flush controller */
695 device_printf(sc->mlx_dev, "flushing cache...");
696 printf("%s\n", mlx_flush(sc) ? "failed" : "done");
697
698 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
699 MLX_IO_UNLOCK(sc);
700
701 return(0);
702 }
703
704 /********************************************************************************
705 * Bring the controller back to a state ready for operation.
706 */
707 int
mlx_resume(device_t dev)708 mlx_resume(device_t dev)
709 {
710 struct mlx_softc *sc = device_get_softc(dev);
711
712 debug_called(1);
713
714 MLX_IO_LOCK(sc);
715 sc->mlx_state &= ~MLX_STATE_SUSPEND;
716 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
717 MLX_IO_UNLOCK(sc);
718
719 return(0);
720 }
721
722 /*******************************************************************************
723 * Take an interrupt, or be poked by other code to look for interrupt-worthy
724 * status.
725 */
726 void
mlx_intr(void * arg)727 mlx_intr(void *arg)
728 {
729 struct mlx_softc *sc = (struct mlx_softc *)arg;
730
731 debug_called(1);
732
733 /* collect finished commands, queue anything waiting */
734 MLX_IO_LOCK(sc);
735 mlx_done(sc, 1);
736 MLX_IO_UNLOCK(sc);
737 };
738
739 /*******************************************************************************
740 * Receive a buf structure from a child device and queue it on a particular
741 * disk resource, then poke the disk resource to start as much work as it can.
742 */
743 int
mlx_submit_buf(struct mlx_softc * sc,struct bio * bp)744 mlx_submit_buf(struct mlx_softc *sc, struct bio *bp)
745 {
746
747 debug_called(1);
748
749 MLX_IO_ASSERT_LOCKED(sc);
750 bioq_insert_tail(&sc->mlx_bioq, bp);
751 sc->mlx_waitbufs++;
752 mlx_startio(sc);
753 return(0);
754 }
755
756 /********************************************************************************
757 * Accept an open operation on the control device.
758 */
759 int
mlx_open(struct cdev * dev,int flags,int fmt,struct thread * td)760 mlx_open(struct cdev *dev, int flags, int fmt, struct thread *td)
761 {
762 struct mlx_softc *sc = dev->si_drv1;
763
764 MLX_CONFIG_LOCK(sc);
765 MLX_IO_LOCK(sc);
766 sc->mlx_state |= MLX_STATE_OPEN;
767 MLX_IO_UNLOCK(sc);
768 MLX_CONFIG_UNLOCK(sc);
769 return(0);
770 }
771
772 /********************************************************************************
773 * Accept the last close on the control device.
774 */
775 int
mlx_close(struct cdev * dev,int flags,int fmt,struct thread * td)776 mlx_close(struct cdev *dev, int flags, int fmt, struct thread *td)
777 {
778 struct mlx_softc *sc = dev->si_drv1;
779
780 MLX_CONFIG_LOCK(sc);
781 MLX_IO_LOCK(sc);
782 sc->mlx_state &= ~MLX_STATE_OPEN;
783 MLX_IO_UNLOCK(sc);
784 MLX_CONFIG_UNLOCK(sc);
785 return (0);
786 }
787
788 /********************************************************************************
789 * Handle controller-specific control operations.
790 */
791 int
mlx_ioctl(struct cdev * dev,u_long cmd,caddr_t addr,int32_t flag,struct thread * td)792 mlx_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
793 {
794 struct mlx_softc *sc = dev->si_drv1;
795 struct mlx_rebuild_request *rb = (struct mlx_rebuild_request *)addr;
796 struct mlx_rebuild_status *rs = (struct mlx_rebuild_status *)addr;
797 int *arg = (int *)addr;
798 struct mlx_pause *mp;
799 struct mlx_sysdrive *dr;
800 struct mlxd_softc *mlxd;
801 int i, error;
802
803 switch(cmd) {
804 /*
805 * Enumerate connected system drives; returns the first system drive's
806 * unit number if *arg is -1, or the next unit after *arg if it's
807 * a valid unit on this controller.
808 */
809 case MLX_NEXT_CHILD:
810 /* search system drives */
811 MLX_CONFIG_LOCK(sc);
812 for (i = 0; i < MLX_MAXDRIVES; i++) {
813 /* is this one attached? */
814 if (sc->mlx_sysdrive[i].ms_disk != 0) {
815 /* looking for the next one we come across? */
816 if (*arg == -1) {
817 *arg = device_get_unit(sc->mlx_sysdrive[i].ms_disk);
818 MLX_CONFIG_UNLOCK(sc);
819 return(0);
820 }
821 /* we want the one after this one */
822 if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
823 *arg = -1;
824 }
825 }
826 MLX_CONFIG_UNLOCK(sc);
827 return(ENOENT);
828
829 /*
830 * Scan the controller to see whether new drives have appeared.
831 */
832 case MLX_RESCAN_DRIVES:
833 mtx_lock(&Giant);
834 mlx_startup(sc);
835 mtx_unlock(&Giant);
836 return(0);
837
838 /*
839 * Disconnect from the specified drive; it may be about to go
840 * away.
841 */
842 case MLX_DETACH_DRIVE: /* detach one drive */
843 MLX_CONFIG_LOCK(sc);
844 if (((dr = mlx_findunit(sc, *arg)) == NULL) ||
845 ((mlxd = device_get_softc(dr->ms_disk)) == NULL)) {
846 MLX_CONFIG_UNLOCK(sc);
847 return(ENOENT);
848 }
849
850 device_printf(dr->ms_disk, "detaching...");
851 error = 0;
852 if (mlxd->mlxd_flags & MLXD_OPEN) {
853 error = EBUSY;
854 goto detach_out;
855 }
856
857 /* flush controller */
858 MLX_IO_LOCK(sc);
859 if (mlx_flush(sc)) {
860 MLX_IO_UNLOCK(sc);
861 error = EBUSY;
862 goto detach_out;
863 }
864 MLX_IO_UNLOCK(sc);
865
866 /* nuke drive */
867 if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
868 goto detach_out;
869 dr->ms_disk = 0;
870
871 detach_out:
872 MLX_CONFIG_UNLOCK(sc);
873 if (error) {
874 printf("failed\n");
875 } else {
876 printf("done\n");
877 }
878 return(error);
879
880 /*
881 * Pause one or more SCSI channels for a period of time, to assist
882 * in the process of hot-swapping devices.
883 *
884 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
885 * to do this right.
886 */
887 case MLX_PAUSE_CHANNEL: /* schedule a channel pause */
888 /* Does this command work on this firmware? */
889 if (!(sc->mlx_feature & MLX_FEAT_PAUSEWORKS))
890 return(EOPNOTSUPP);
891
892 /* check time values */
893 mp = (struct mlx_pause *)addr;
894 if ((mp->mp_when < 0) || (mp->mp_when > 3600))
895 return(EINVAL);
896 if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
897 return(EINVAL);
898
899 MLX_IO_LOCK(sc);
900 if ((mp->mp_which == MLX_PAUSE_CANCEL) && (sc->mlx_pause.mp_when != 0)) {
901 /* cancel a pending pause operation */
902 sc->mlx_pause.mp_which = 0;
903 } else {
904 /* fix for legal channels */
905 mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1);
906
907 /* check for a pause currently running */
908 if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0)) {
909 MLX_IO_UNLOCK(sc);
910 return(EBUSY);
911 }
912
913 /* looks ok, go with it */
914 sc->mlx_pause.mp_which = mp->mp_which;
915 sc->mlx_pause.mp_when = time_second + mp->mp_when;
916 sc->mlx_pause.mp_howlong = sc->mlx_pause.mp_when + mp->mp_howlong;
917 }
918 MLX_IO_UNLOCK(sc);
919 return(0);
920
921 /*
922 * Accept a command passthrough-style.
923 */
924 case MLX_COMMAND:
925 return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
926
927 /*
928 * Start a rebuild on a given SCSI disk
929 */
930 case MLX_REBUILDASYNC:
931 MLX_IO_LOCK(sc);
932 if (sc->mlx_background != 0) {
933 MLX_IO_UNLOCK(sc);
934 rb->rr_status = 0x0106;
935 return(EBUSY);
936 }
937 rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target);
938 switch (rb->rr_status) {
939 case 0:
940 error = 0;
941 break;
942 case 0x10000:
943 error = ENOMEM; /* couldn't set up the command */
944 break;
945 case 0x0002:
946 error = EBUSY;
947 break;
948 case 0x0104:
949 error = EIO;
950 break;
951 case 0x0105:
952 error = ERANGE;
953 break;
954 case 0x0106:
955 error = EBUSY;
956 break;
957 default:
958 error = EINVAL;
959 break;
960 }
961 if (error == 0)
962 sc->mlx_background = MLX_BACKGROUND_REBUILD;
963 MLX_IO_UNLOCK(sc);
964 return(error);
965
966 /*
967 * Get the status of the current rebuild or consistency check.
968 */
969 case MLX_REBUILDSTAT:
970 MLX_IO_LOCK(sc);
971 *rs = sc->mlx_rebuildstat;
972 MLX_IO_UNLOCK(sc);
973 return(0);
974
975 /*
976 * Return the per-controller system drive number matching the
977 * disk device number in (arg), if it happens to belong to us.
978 */
979 case MLX_GET_SYSDRIVE:
980 error = ENOENT;
981 MLX_CONFIG_LOCK(sc);
982 mtx_lock(&Giant);
983 mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg);
984 mtx_unlock(&Giant);
985 if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) &&
986 (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) {
987 error = 0;
988 *arg = mlxd->mlxd_drive - sc->mlx_sysdrive;
989 }
990 MLX_CONFIG_UNLOCK(sc);
991 return(error);
992
993 default:
994 return(ENOTTY);
995 }
996 }
997
998 /********************************************************************************
999 * Handle operations requested by a System Drive connected to this controller.
1000 */
1001 int
mlx_submit_ioctl(struct mlx_softc * sc,struct mlx_sysdrive * drive,u_long cmd,caddr_t addr,int32_t flag,struct thread * td)1002 mlx_submit_ioctl(struct mlx_softc *sc, struct mlx_sysdrive *drive, u_long cmd,
1003 caddr_t addr, int32_t flag, struct thread *td)
1004 {
1005 int *arg = (int *)addr;
1006 int error, result;
1007
1008 switch(cmd) {
1009 /*
1010 * Return the current status of this drive.
1011 */
1012 case MLXD_STATUS:
1013 MLX_IO_LOCK(sc);
1014 *arg = drive->ms_state;
1015 MLX_IO_UNLOCK(sc);
1016 return(0);
1017
1018 /*
1019 * Start a background consistency check on this drive.
1020 */
1021 case MLXD_CHECKASYNC: /* start a background consistency check */
1022 MLX_IO_LOCK(sc);
1023 if (sc->mlx_background != 0) {
1024 MLX_IO_UNLOCK(sc);
1025 *arg = 0x0106;
1026 return(EBUSY);
1027 }
1028 result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]);
1029 switch (result) {
1030 case 0:
1031 error = 0;
1032 break;
1033 case 0x10000:
1034 error = ENOMEM; /* couldn't set up the command */
1035 break;
1036 case 0x0002:
1037 error = EIO;
1038 break;
1039 case 0x0105:
1040 error = ERANGE;
1041 break;
1042 case 0x0106:
1043 error = EBUSY;
1044 break;
1045 default:
1046 error = EINVAL;
1047 break;
1048 }
1049 if (error == 0)
1050 sc->mlx_background = MLX_BACKGROUND_CHECK;
1051 MLX_IO_UNLOCK(sc);
1052 *arg = result;
1053 return(error);
1054
1055 }
1056 return(ENOIOCTL);
1057 }
1058
1059
1060 /********************************************************************************
1061 ********************************************************************************
1062 Status Monitoring
1063 ********************************************************************************
1064 ********************************************************************************/
1065
1066 /********************************************************************************
1067 * Fire off commands to periodically check the status of connected drives.
1068 */
1069 static void
mlx_periodic(void * data)1070 mlx_periodic(void *data)
1071 {
1072 struct mlx_softc *sc = (struct mlx_softc *)data;
1073
1074 debug_called(1);
1075 MLX_IO_ASSERT_LOCKED(sc);
1076
1077 /*
1078 * Run a bus pause?
1079 */
1080 if ((sc->mlx_pause.mp_which != 0) &&
1081 (sc->mlx_pause.mp_when > 0) &&
1082 (time_second >= sc->mlx_pause.mp_when)){
1083
1084 mlx_pause_action(sc); /* pause is running */
1085 sc->mlx_pause.mp_when = 0;
1086 sysbeep(500, SBT_1S);
1087
1088 /*
1089 * Bus pause still running?
1090 */
1091 } else if ((sc->mlx_pause.mp_which != 0) &&
1092 (sc->mlx_pause.mp_when == 0)) {
1093
1094 /* time to stop bus pause? */
1095 if (time_second >= sc->mlx_pause.mp_howlong) {
1096 mlx_pause_action(sc);
1097 sc->mlx_pause.mp_which = 0; /* pause is complete */
1098 sysbeep(500, SBT_1S);
1099 } else {
1100 sysbeep((time_second % 5) * 100 + 500, SBT_1S / 8);
1101 }
1102
1103 /*
1104 * Run normal periodic activities?
1105 */
1106 } else if (time_second > (sc->mlx_lastpoll + 10)) {
1107 sc->mlx_lastpoll = time_second;
1108
1109 /*
1110 * Check controller status.
1111 *
1112 * XXX Note that this may not actually launch a command in situations of high load.
1113 */
1114 mlx_enquire(sc, (sc->mlx_iftype == MLX_IFTYPE_2) ? MLX_CMD_ENQUIRY_OLD : MLX_CMD_ENQUIRY,
1115 imax(sizeof(struct mlx_enquiry), sizeof(struct mlx_enquiry_old)), mlx_periodic_enquiry);
1116
1117 /*
1118 * Check system drive status.
1119 *
1120 * XXX This might be better left to event-driven detection, eg. I/O to an offline
1121 * drive will detect it's offline, rebuilds etc. should detect the drive is back
1122 * online.
1123 */
1124 mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
1125 mlx_periodic_enquiry);
1126
1127 }
1128
1129 /* get drive rebuild/check status */
1130 /* XXX should check sc->mlx_background if this is only valid while in progress */
1131 mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
1132
1133 /* deal with possibly-missed interrupts and timed-out commands */
1134 mlx_done(sc, 1);
1135
1136 /* reschedule another poll next second or so */
1137 callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc);
1138 }
1139
1140 /********************************************************************************
1141 * Handle the result of an ENQUIRY command instigated by periodic status polling.
1142 */
1143 static void
mlx_periodic_enquiry(struct mlx_command * mc)1144 mlx_periodic_enquiry(struct mlx_command *mc)
1145 {
1146 struct mlx_softc *sc = mc->mc_sc;
1147
1148 debug_called(1);
1149 MLX_IO_ASSERT_LOCKED(sc);
1150
1151 /* Command completed OK? */
1152 if (mc->mc_status != 0) {
1153 device_printf(sc->mlx_dev, "periodic enquiry failed - %s\n", mlx_diagnose_command(mc));
1154 goto out;
1155 }
1156
1157 /* respond to command */
1158 switch(mc->mc_mailbox[0]) {
1159 /*
1160 * This is currently a bit fruitless, as we don't know how to extract the eventlog
1161 * pointer yet.
1162 */
1163 case MLX_CMD_ENQUIRY_OLD:
1164 {
1165 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1166 struct mlx_enquiry_old *meo = (struct mlx_enquiry_old *)mc->mc_data;
1167 int i;
1168
1169 /* convert data in-place to new format */
1170 for (i = (sizeof(me->me_dead) / sizeof(me->me_dead[0])) - 1; i >= 0; i--) {
1171 me->me_dead[i].dd_chan = meo->me_dead[i].dd_chan;
1172 me->me_dead[i].dd_targ = meo->me_dead[i].dd_targ;
1173 }
1174 me->me_misc_flags = 0;
1175 me->me_rebuild_count = meo->me_rebuild_count;
1176 me->me_dead_count = meo->me_dead_count;
1177 me->me_critical_sd_count = meo->me_critical_sd_count;
1178 me->me_event_log_seq_num = 0;
1179 me->me_offline_sd_count = meo->me_offline_sd_count;
1180 me->me_max_commands = meo->me_max_commands;
1181 me->me_rebuild_flag = meo->me_rebuild_flag;
1182 me->me_fwmajor = meo->me_fwmajor;
1183 me->me_fwminor = meo->me_fwminor;
1184 me->me_status_flags = meo->me_status_flags;
1185 me->me_flash_age = meo->me_flash_age;
1186 for (i = (sizeof(me->me_drvsize) / sizeof(me->me_drvsize[0])) - 1; i >= 0; i--) {
1187 if (i > ((sizeof(meo->me_drvsize) / sizeof(meo->me_drvsize[0])) - 1)) {
1188 me->me_drvsize[i] = 0; /* drive beyond supported range */
1189 } else {
1190 me->me_drvsize[i] = meo->me_drvsize[i];
1191 }
1192 }
1193 me->me_num_sys_drvs = meo->me_num_sys_drvs;
1194 }
1195 /* FALLTHROUGH */
1196
1197 /*
1198 * Generic controller status update. We could do more with this than just
1199 * checking the event log.
1200 */
1201 case MLX_CMD_ENQUIRY:
1202 {
1203 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1204
1205 if (sc->mlx_currevent == -1) {
1206 /* initialise our view of the event log */
1207 sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
1208 } else if ((me->me_event_log_seq_num != sc->mlx_lastevent) && !(sc->mlx_flags & MLX_EVENTLOG_BUSY)) {
1209 /* record where current events are up to */
1210 sc->mlx_currevent = me->me_event_log_seq_num;
1211 debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent);
1212
1213 /* mark the event log as busy */
1214 sc->mlx_flags |= MLX_EVENTLOG_BUSY;
1215
1216 /* drain new eventlog entries */
1217 mlx_periodic_eventlog_poll(sc);
1218 }
1219 break;
1220 }
1221 case MLX_CMD_ENQSYSDRIVE:
1222 {
1223 struct mlx_enq_sys_drive *mes = (struct mlx_enq_sys_drive *)mc->mc_data;
1224 struct mlx_sysdrive *dr;
1225 int i;
1226
1227 for (i = 0, dr = &sc->mlx_sysdrive[0];
1228 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
1229 i++) {
1230
1231 /* has state been changed by controller? */
1232 if (dr->ms_state != mes[i].sd_state) {
1233 switch(mes[i].sd_state) {
1234 case MLX_SYSD_OFFLINE:
1235 device_printf(dr->ms_disk, "drive offline\n");
1236 break;
1237 case MLX_SYSD_ONLINE:
1238 device_printf(dr->ms_disk, "drive online\n");
1239 break;
1240 case MLX_SYSD_CRITICAL:
1241 device_printf(dr->ms_disk, "drive critical\n");
1242 break;
1243 }
1244 /* save new state */
1245 dr->ms_state = mes[i].sd_state;
1246 }
1247 }
1248 break;
1249 }
1250 default:
1251 device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __func__, mc->mc_mailbox[0]);
1252 break;
1253 }
1254
1255 out:
1256 free(mc->mc_data, M_DEVBUF);
1257 mlx_releasecmd(mc);
1258 }
1259
1260 static void
mlx_eventlog_cb(void * arg,bus_dma_segment_t * segs,int nsegments,int error)1261 mlx_eventlog_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1262 {
1263 struct mlx_command *mc;
1264
1265 mc = (struct mlx_command *)arg;
1266 mlx_setup_dmamap(mc, segs, nsegments, error);
1267
1268 /* build the command to get one entry */
1269 mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1,
1270 mc->mc_sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1271 mc->mc_complete = mlx_periodic_eventlog_respond;
1272 mc->mc_private = mc;
1273
1274 /* start the command */
1275 if (mlx_start(mc) != 0) {
1276 mlx_releasecmd(mc);
1277 free(mc->mc_data, M_DEVBUF);
1278 mc->mc_data = NULL;
1279 }
1280
1281 }
1282
1283 /********************************************************************************
1284 * Instigate a poll for one event log message on (sc).
1285 * We only poll for one message at a time, to keep our command usage down.
1286 */
1287 static void
mlx_periodic_eventlog_poll(struct mlx_softc * sc)1288 mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1289 {
1290 struct mlx_command *mc;
1291 void *result = NULL;
1292 int error = 0;
1293
1294 debug_called(1);
1295 MLX_IO_ASSERT_LOCKED(sc);
1296
1297 /* get ourselves a command buffer */
1298 error = 1;
1299 if ((mc = mlx_alloccmd(sc)) == NULL)
1300 goto out;
1301
1302 /* allocate the response structure */
1303 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF,
1304 M_NOWAIT)) == NULL)
1305 goto out;
1306
1307 /* get a command slot */
1308 if (mlx_getslot(mc))
1309 goto out;
1310
1311 /* map the command so the controller can see it */
1312 mc->mc_data = result;
1313 mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1314 error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
1315 mc->mc_length, mlx_eventlog_cb, mc, BUS_DMA_NOWAIT);
1316
1317 out:
1318 if (error != 0) {
1319 if (mc != NULL)
1320 mlx_releasecmd(mc);
1321 if ((result != NULL) && (mc->mc_data != NULL))
1322 free(result, M_DEVBUF);
1323 }
1324 }
1325
1326 /********************************************************************************
1327 * Handle the result of polling for a log message, generate diagnostic output.
1328 * If this wasn't the last message waiting for us, we'll go collect another.
1329 */
1330 static char *mlx_sense_messages[] = {
1331 "because write recovery failed",
1332 "because of SCSI bus reset failure",
1333 "because of double check condition",
1334 "because it was removed",
1335 "because of gross error on SCSI chip",
1336 "because of bad tag returned from drive",
1337 "because of timeout on SCSI command",
1338 "because of reset SCSI command issued from system",
1339 "because busy or parity error count exceeded limit",
1340 "because of 'kill drive' command from system",
1341 "because of selection timeout",
1342 "due to SCSI phase sequence error",
1343 "due to unknown status"
1344 };
1345
1346 static void
mlx_periodic_eventlog_respond(struct mlx_command * mc)1347 mlx_periodic_eventlog_respond(struct mlx_command *mc)
1348 {
1349 struct mlx_softc *sc = mc->mc_sc;
1350 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data;
1351 char *reason;
1352
1353 debug_called(1);
1354 MLX_IO_ASSERT_LOCKED(sc);
1355
1356 sc->mlx_lastevent++; /* next message... */
1357 if (mc->mc_status == 0) {
1358
1359 /* handle event log message */
1360 switch(el->el_type) {
1361 /*
1362 * This is the only sort of message we understand at the moment.
1363 * The tests here are probably incomplete.
1364 */
1365 case MLX_LOGMSG_SENSE: /* sense data */
1366 /* Mylex vendor-specific message indicating a drive was killed? */
1367 if ((el->el_sensekey == 9) &&
1368 (el->el_asc == 0x80)) {
1369 if (el->el_asq < nitems(mlx_sense_messages)) {
1370 reason = mlx_sense_messages[el->el_asq];
1371 } else {
1372 reason = "for unknown reason";
1373 }
1374 device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1375 el->el_channel, el->el_target, reason);
1376 }
1377 /* SCSI drive was reset? */
1378 if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1379 device_printf(sc->mlx_dev, "physical drive %d:%d reset\n",
1380 el->el_channel, el->el_target);
1381 }
1382 /* SCSI drive error? */
1383 if (!((el->el_sensekey == 0) ||
1384 ((el->el_sensekey == 2) &&
1385 (el->el_asc == 0x04) &&
1386 ((el->el_asq == 0x01) ||
1387 (el->el_asq == 0x02))))) {
1388 device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1389 el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1390 device_printf(sc->mlx_dev, " info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1391 }
1392 break;
1393
1394 default:
1395 device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1396 break;
1397 }
1398 } else {
1399 device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1400 /* give up on all the outstanding messages, as we may have come unsynched */
1401 sc->mlx_lastevent = sc->mlx_currevent;
1402 }
1403
1404 /* dispose of command and data */
1405 free(mc->mc_data, M_DEVBUF);
1406 mlx_releasecmd(mc);
1407
1408 /* is there another message to obtain? */
1409 if (sc->mlx_lastevent != sc->mlx_currevent) {
1410 mlx_periodic_eventlog_poll(sc);
1411 } else {
1412 /* clear log-busy status */
1413 sc->mlx_flags &= ~MLX_EVENTLOG_BUSY;
1414 }
1415 }
1416
1417 /********************************************************************************
1418 * Handle check/rebuild operations in progress.
1419 */
1420 static void
mlx_periodic_rebuild(struct mlx_command * mc)1421 mlx_periodic_rebuild(struct mlx_command *mc)
1422 {
1423 struct mlx_softc *sc = mc->mc_sc;
1424 struct mlx_rebuild_status *mr = (struct mlx_rebuild_status *)mc->mc_data;
1425
1426 MLX_IO_ASSERT_LOCKED(sc);
1427 switch(mc->mc_status) {
1428 case 0: /* operation running, update stats */
1429 sc->mlx_rebuildstat = *mr;
1430
1431 /* spontaneous rebuild/check? */
1432 if (sc->mlx_background == 0) {
1433 sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS;
1434 device_printf(sc->mlx_dev, "background check/rebuild operation started\n");
1435 }
1436 break;
1437
1438 case 0x0105: /* nothing running, finalise stats and report */
1439 switch(sc->mlx_background) {
1440 case MLX_BACKGROUND_CHECK:
1441 device_printf(sc->mlx_dev, "consistency check completed\n"); /* XXX print drive? */
1442 break;
1443 case MLX_BACKGROUND_REBUILD:
1444 device_printf(sc->mlx_dev, "drive rebuild completed\n"); /* XXX print channel/target? */
1445 break;
1446 case MLX_BACKGROUND_SPONTANEOUS:
1447 default:
1448 /* if we have previously been non-idle, report the transition */
1449 if (sc->mlx_rebuildstat.rs_code != MLX_REBUILDSTAT_IDLE) {
1450 device_printf(sc->mlx_dev, "background check/rebuild operation completed\n");
1451 }
1452 }
1453 sc->mlx_background = 0;
1454 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
1455 break;
1456 }
1457 free(mc->mc_data, M_DEVBUF);
1458 mlx_releasecmd(mc);
1459 }
1460
1461 /********************************************************************************
1462 ********************************************************************************
1463 Channel Pause
1464 ********************************************************************************
1465 ********************************************************************************/
1466
1467 /********************************************************************************
1468 * It's time to perform a channel pause action for (sc), either start or stop
1469 * the pause.
1470 */
1471 static void
mlx_pause_action(struct mlx_softc * sc)1472 mlx_pause_action(struct mlx_softc *sc)
1473 {
1474 struct mlx_command *mc;
1475 int failsafe, i, command;
1476
1477 MLX_IO_ASSERT_LOCKED(sc);
1478
1479 /* What are we doing here? */
1480 if (sc->mlx_pause.mp_when == 0) {
1481 command = MLX_CMD_STARTCHANNEL;
1482 failsafe = 0;
1483
1484 } else {
1485 command = MLX_CMD_STOPCHANNEL;
1486
1487 /*
1488 * Channels will always start again after the failsafe period,
1489 * which is specified in multiples of 30 seconds.
1490 * This constrains us to a maximum pause of 450 seconds.
1491 */
1492 failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1493 if (failsafe > 0xf) {
1494 failsafe = 0xf;
1495 sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1496 }
1497 }
1498
1499 /* build commands for every channel requested */
1500 for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) {
1501 if ((1 << i) & sc->mlx_pause.mp_which) {
1502
1503 /* get ourselves a command buffer */
1504 if ((mc = mlx_alloccmd(sc)) == NULL)
1505 goto fail;
1506 /* get a command slot */
1507 mc->mc_flags |= MLX_CMD_PRIORITY;
1508 if (mlx_getslot(mc))
1509 goto fail;
1510
1511 /* build the command */
1512 mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1513 mc->mc_complete = mlx_pause_done;
1514 mc->mc_private = sc; /* XXX not needed */
1515 if (mlx_start(mc))
1516 goto fail;
1517 /* command submitted OK */
1518 return;
1519
1520 fail:
1521 device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1522 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1523 if (mc != NULL)
1524 mlx_releasecmd(mc);
1525 }
1526 }
1527 }
1528
1529 static void
mlx_pause_done(struct mlx_command * mc)1530 mlx_pause_done(struct mlx_command *mc)
1531 {
1532 struct mlx_softc *sc = mc->mc_sc;
1533 int command = mc->mc_mailbox[0];
1534 int channel = mc->mc_mailbox[2] & 0xf;
1535
1536 MLX_IO_ASSERT_LOCKED(sc);
1537 if (mc->mc_status != 0) {
1538 device_printf(sc->mlx_dev, "%s command failed - %s\n",
1539 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1540 } else if (command == MLX_CMD_STOPCHANNEL) {
1541 device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n",
1542 channel, (long)(sc->mlx_pause.mp_howlong - time_second));
1543 } else {
1544 device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1545 }
1546 mlx_releasecmd(mc);
1547 }
1548
1549 /********************************************************************************
1550 ********************************************************************************
1551 Command Submission
1552 ********************************************************************************
1553 ********************************************************************************/
1554
1555 static void
mlx_enquire_cb(void * arg,bus_dma_segment_t * segs,int nsegments,int error)1556 mlx_enquire_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1557 {
1558 struct mlx_softc *sc;
1559 struct mlx_command *mc;
1560
1561 mc = (struct mlx_command *)arg;
1562 if (error)
1563 return;
1564
1565 mlx_setup_dmamap(mc, segs, nsegments, error);
1566
1567 /* build an enquiry command */
1568 sc = mc->mc_sc;
1569 mlx_make_type2(mc, mc->mc_command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1570
1571 /* do we want a completion callback? */
1572 if (mc->mc_complete != NULL) {
1573 if ((error = mlx_start(mc)) != 0)
1574 return;
1575 } else {
1576 /* run the command in either polled or wait mode */
1577 if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) :
1578 mlx_poll_command(mc))
1579 return;
1580
1581 /* command completed OK? */
1582 if (mc->mc_status != 0) {
1583 device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n",
1584 mlx_diagnose_command(mc));
1585 return;
1586 }
1587 }
1588 }
1589
1590 /********************************************************************************
1591 * Perform an Enquiry command using a type-3 command buffer and a return a single
1592 * linear result buffer. If the completion function is specified, it will
1593 * be called with the completed command (and the result response will not be
1594 * valid until that point). Otherwise, the command will either be busy-waited
1595 * for (interrupts not enabled), or slept for.
1596 */
1597 static void *
mlx_enquire(struct mlx_softc * sc,int command,size_t bufsize,void (* complete)(struct mlx_command * mc))1598 mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1599 {
1600 struct mlx_command *mc;
1601 void *result;
1602 int error;
1603
1604 debug_called(1);
1605 MLX_IO_ASSERT_LOCKED(sc);
1606
1607 /* get ourselves a command buffer */
1608 error = 1;
1609 result = NULL;
1610 if ((mc = mlx_alloccmd(sc)) == NULL)
1611 goto out;
1612 /* allocate the response structure */
1613 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1614 goto out;
1615 /* get a command slot */
1616 mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1617 if (mlx_getslot(mc))
1618 goto out;
1619
1620 /* map the command so the controller can see it */
1621 mc->mc_data = result;
1622 mc->mc_length = bufsize;
1623 mc->mc_command = command;
1624
1625 if (complete != NULL) {
1626 mc->mc_complete = complete;
1627 mc->mc_private = mc;
1628 }
1629
1630 error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
1631 mc->mc_length, mlx_enquire_cb, mc, BUS_DMA_NOWAIT);
1632
1633 out:
1634 /* we got a command, but nobody else will free it */
1635 if ((mc != NULL) && (mc->mc_complete == NULL))
1636 mlx_releasecmd(mc);
1637 /* we got an error, and we allocated a result */
1638 if ((error != 0) && (result != NULL)) {
1639 free(result, M_DEVBUF);
1640 result = NULL;
1641 }
1642 return(result);
1643 }
1644
1645
1646 /********************************************************************************
1647 * Perform a Flush command on the nominated controller.
1648 *
1649 * May be called with interrupts enabled or disabled; will not return until
1650 * the flush operation completes or fails.
1651 */
1652 static int
mlx_flush(struct mlx_softc * sc)1653 mlx_flush(struct mlx_softc *sc)
1654 {
1655 struct mlx_command *mc;
1656 int error;
1657
1658 debug_called(1);
1659 MLX_IO_ASSERT_LOCKED(sc);
1660
1661 /* get ourselves a command buffer */
1662 error = 1;
1663 if ((mc = mlx_alloccmd(sc)) == NULL)
1664 goto out;
1665 /* get a command slot */
1666 if (mlx_getslot(mc))
1667 goto out;
1668
1669 /* build a flush command */
1670 mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1671
1672 /* can't assume that interrupts are going to work here, so play it safe */
1673 if (mlx_poll_command(mc))
1674 goto out;
1675
1676 /* command completed OK? */
1677 if (mc->mc_status != 0) {
1678 device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1679 goto out;
1680 }
1681
1682 error = 0; /* success */
1683 out:
1684 if (mc != NULL)
1685 mlx_releasecmd(mc);
1686 return(error);
1687 }
1688
1689 /********************************************************************************
1690 * Start a background consistency check on (drive).
1691 *
1692 * May be called with interrupts enabled or disabled; will return as soon as the
1693 * operation has started or been refused.
1694 */
1695 static int
mlx_check(struct mlx_softc * sc,int drive)1696 mlx_check(struct mlx_softc *sc, int drive)
1697 {
1698 struct mlx_command *mc;
1699 int error;
1700
1701 debug_called(1);
1702 MLX_IO_ASSERT_LOCKED(sc);
1703
1704 /* get ourselves a command buffer */
1705 error = 0x10000;
1706 if ((mc = mlx_alloccmd(sc)) == NULL)
1707 goto out;
1708 /* get a command slot */
1709 if (mlx_getslot(mc))
1710 goto out;
1711
1712 /* build a checkasync command, set the "fix it" flag */
1713 mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 0, 0);
1714
1715 /* start the command and wait for it to be returned */
1716 if (mlx_wait_command(mc))
1717 goto out;
1718
1719 /* command completed OK? */
1720 if (mc->mc_status != 0) {
1721 device_printf(sc->mlx_dev, "CHECK ASYNC failed - %s\n", mlx_diagnose_command(mc));
1722 } else {
1723 device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started");
1724 }
1725 error = mc->mc_status;
1726
1727 out:
1728 if (mc != NULL)
1729 mlx_releasecmd(mc);
1730 return(error);
1731 }
1732
1733 /********************************************************************************
1734 * Start a background rebuild of the physical drive at (channel),(target).
1735 *
1736 * May be called with interrupts enabled or disabled; will return as soon as the
1737 * operation has started or been refused.
1738 */
1739 static int
mlx_rebuild(struct mlx_softc * sc,int channel,int target)1740 mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1741 {
1742 struct mlx_command *mc;
1743 int error;
1744
1745 debug_called(1);
1746 MLX_IO_ASSERT_LOCKED(sc);
1747
1748 /* get ourselves a command buffer */
1749 error = 0x10000;
1750 if ((mc = mlx_alloccmd(sc)) == NULL)
1751 goto out;
1752 /* get a command slot */
1753 if (mlx_getslot(mc))
1754 goto out;
1755
1756 /* build a checkasync command, set the "fix it" flag */
1757 mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1758
1759 /* start the command and wait for it to be returned */
1760 if (mlx_wait_command(mc))
1761 goto out;
1762
1763 /* command completed OK? */
1764 if (mc->mc_status != 0) {
1765 device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1766 } else {
1767 device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target);
1768 }
1769 error = mc->mc_status;
1770
1771 out:
1772 if (mc != NULL)
1773 mlx_releasecmd(mc);
1774 return(error);
1775 }
1776
1777 /********************************************************************************
1778 * Run the command (mc) and return when it completes.
1779 *
1780 * Interrupts need to be enabled; returns nonzero on error.
1781 */
1782 static int
mlx_wait_command(struct mlx_command * mc)1783 mlx_wait_command(struct mlx_command *mc)
1784 {
1785 struct mlx_softc *sc = mc->mc_sc;
1786 int error, count;
1787
1788 debug_called(1);
1789 MLX_IO_ASSERT_LOCKED(sc);
1790
1791 mc->mc_complete = NULL;
1792 mc->mc_private = mc; /* wake us when you're done */
1793 if ((error = mlx_start(mc)) != 0)
1794 return(error);
1795
1796 count = 0;
1797 /* XXX better timeout? */
1798 while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1799 mtx_sleep(mc->mc_private, &sc->mlx_io_lock, PRIBIO | PCATCH, "mlxwcmd", hz);
1800 }
1801
1802 if (mc->mc_status != 0) {
1803 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1804 return(EIO);
1805 }
1806 return(0);
1807 }
1808
1809
1810 /********************************************************************************
1811 * Start the command (mc) and busy-wait for it to complete.
1812 *
1813 * Should only be used when interrupts can't be relied upon. Returns 0 on
1814 * success, nonzero on error.
1815 * Successfully completed commands are dequeued.
1816 */
1817 static int
mlx_poll_command(struct mlx_command * mc)1818 mlx_poll_command(struct mlx_command *mc)
1819 {
1820 struct mlx_softc *sc = mc->mc_sc;
1821 int error, count;
1822
1823 debug_called(1);
1824 MLX_IO_ASSERT_LOCKED(sc);
1825
1826 mc->mc_complete = NULL;
1827 mc->mc_private = NULL; /* we will poll for it */
1828 if ((error = mlx_start(mc)) != 0)
1829 return(error);
1830
1831 count = 0;
1832 do {
1833 /* poll for completion */
1834 mlx_done(mc->mc_sc, 1);
1835
1836 } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
1837 if (mc->mc_status != MLX_STATUS_BUSY) {
1838 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1839 return(0);
1840 }
1841 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1842 return(EIO);
1843 }
1844
1845 void
mlx_startio_cb(void * arg,bus_dma_segment_t * segs,int nsegments,int error)1846 mlx_startio_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1847 {
1848 struct mlx_command *mc;
1849 struct mlxd_softc *mlxd;
1850 struct mlx_softc *sc;
1851 struct bio *bp;
1852 int blkcount;
1853 int driveno;
1854 int cmd;
1855
1856 mc = (struct mlx_command *)arg;
1857 mlx_setup_dmamap(mc, segs, nsegments, error);
1858
1859 sc = mc->mc_sc;
1860 bp = mc->mc_private;
1861
1862 if (bp->bio_cmd == BIO_READ) {
1863 mc->mc_flags |= MLX_CMD_DATAIN;
1864 cmd = MLX_CMD_READSG;
1865 } else {
1866 mc->mc_flags |= MLX_CMD_DATAOUT;
1867 cmd = MLX_CMD_WRITESG;
1868 }
1869
1870 /* build a suitable I/O command (assumes 512-byte rounded transfers) */
1871 mlxd = bp->bio_disk->d_drv1;
1872 driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1873 blkcount = howmany(bp->bio_bcount, MLX_BLKSIZE);
1874
1875 if ((bp->bio_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1876 device_printf(sc->mlx_dev,
1877 "I/O beyond end of unit (%lld,%d > %lu)\n",
1878 (long long)bp->bio_pblkno, blkcount,
1879 (u_long)sc->mlx_sysdrive[driveno].ms_size);
1880
1881 /*
1882 * Build the I/O command. Note that the SG list type bits are set to zero,
1883 * denoting the format of SG list that we are using.
1884 */
1885 if (sc->mlx_iftype == MLX_IFTYPE_2) {
1886 mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD :
1887 MLX_CMD_READSG_OLD,
1888 blkcount & 0xff, /* xfer length low byte */
1889 bp->bio_pblkno, /* physical block number */
1890 driveno, /* target drive number */
1891 mc->mc_sgphys, /* location of SG list */
1892 mc->mc_nsgent & 0x3f); /* size of SG list */
1893 } else {
1894 mlx_make_type5(mc, cmd,
1895 blkcount & 0xff, /* xfer length low byte */
1896 (driveno << 3) | ((blkcount >> 8) & 0x07),
1897 /* target+length high 3 bits */
1898 bp->bio_pblkno, /* physical block number */
1899 mc->mc_sgphys, /* location of SG list */
1900 mc->mc_nsgent & 0x3f); /* size of SG list */
1901 }
1902
1903 /* try to give command to controller */
1904 if (mlx_start(mc) != 0) {
1905 /* fail the command */
1906 mc->mc_status = MLX_STATUS_WEDGED;
1907 mlx_completeio(mc);
1908 }
1909
1910 sc->mlx_state &= ~MLX_STATE_QFROZEN;
1911 }
1912
1913 /********************************************************************************
1914 * Pull as much work off the softc's work queue as possible and give it to the
1915 * controller. Leave a couple of slots free for emergencies.
1916 */
1917 static void
mlx_startio(struct mlx_softc * sc)1918 mlx_startio(struct mlx_softc *sc)
1919 {
1920 struct mlx_command *mc;
1921 struct bio *bp;
1922 int error;
1923
1924 MLX_IO_ASSERT_LOCKED(sc);
1925
1926 /* spin until something prevents us from doing any work */
1927 for (;;) {
1928 if (sc->mlx_state & MLX_STATE_QFROZEN)
1929 break;
1930
1931 /* see if there's work to be done */
1932 if ((bp = bioq_first(&sc->mlx_bioq)) == NULL)
1933 break;
1934 /* get a command */
1935 if ((mc = mlx_alloccmd(sc)) == NULL)
1936 break;
1937 /* get a slot for the command */
1938 if (mlx_getslot(mc) != 0) {
1939 mlx_releasecmd(mc);
1940 break;
1941 }
1942 /* get the buf containing our work */
1943 bioq_remove(&sc->mlx_bioq, bp);
1944 sc->mlx_waitbufs--;
1945
1946 /* connect the buf to the command */
1947 mc->mc_complete = mlx_completeio;
1948 mc->mc_private = bp;
1949 mc->mc_data = bp->bio_data;
1950 mc->mc_length = bp->bio_bcount;
1951
1952 /* map the command so the controller can work with it */
1953 error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
1954 mc->mc_length, mlx_startio_cb, mc, 0);
1955 if (error == EINPROGRESS) {
1956 sc->mlx_state |= MLX_STATE_QFROZEN;
1957 break;
1958 }
1959 }
1960 }
1961
1962 /********************************************************************************
1963 * Handle completion of an I/O command.
1964 */
1965 static void
mlx_completeio(struct mlx_command * mc)1966 mlx_completeio(struct mlx_command *mc)
1967 {
1968 struct mlx_softc *sc = mc->mc_sc;
1969 struct bio *bp = mc->mc_private;
1970 struct mlxd_softc *mlxd = bp->bio_disk->d_drv1;
1971
1972 MLX_IO_ASSERT_LOCKED(sc);
1973 if (mc->mc_status != MLX_STATUS_OK) { /* could be more verbose here? */
1974 bp->bio_error = EIO;
1975 bp->bio_flags |= BIO_ERROR;
1976
1977 switch(mc->mc_status) {
1978 case MLX_STATUS_RDWROFFLINE: /* system drive has gone offline */
1979 device_printf(mlxd->mlxd_dev, "drive offline\n");
1980 /* should signal this with a return code */
1981 mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1982 break;
1983
1984 default: /* other I/O error */
1985 device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1986 #if 0
1987 device_printf(sc->mlx_dev, " b_bcount %ld blkcount %ld b_pblkno %d\n",
1988 bp->bio_bcount, bp->bio_bcount / MLX_BLKSIZE, bp->bio_pblkno);
1989 device_printf(sc->mlx_dev, " %13D\n", mc->mc_mailbox, " ");
1990 #endif
1991 break;
1992 }
1993 }
1994 mlx_releasecmd(mc);
1995 mlxd_intr(bp);
1996 }
1997
1998 void
mlx_user_cb(void * arg,bus_dma_segment_t * segs,int nsegments,int error)1999 mlx_user_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
2000 {
2001 struct mlx_usercommand *mu;
2002 struct mlx_command *mc;
2003 struct mlx_dcdb *dcdb;
2004
2005 mc = (struct mlx_command *)arg;
2006 if (error)
2007 return;
2008
2009 mlx_setup_dmamap(mc, segs, nsegments, error);
2010
2011 mu = (struct mlx_usercommand *)mc->mc_private;
2012 dcdb = NULL;
2013
2014 /*
2015 * If this is a passthrough SCSI command, the DCDB is packed at the
2016 * beginning of the data area. Fix up the DCDB to point to the correct
2017 * physical address and override any bufptr supplied by the caller since
2018 * we know what it's meant to be.
2019 */
2020 if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) {
2021 dcdb = (struct mlx_dcdb *)mc->mc_data;
2022 dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb);
2023 mu->mu_bufptr = 8;
2024 }
2025
2026 /*
2027 * If there's a data buffer, fix up the command's buffer pointer.
2028 */
2029 if (mu->mu_datasize > 0) {
2030 mc->mc_mailbox[mu->mu_bufptr ] = mc->mc_dataphys & 0xff;
2031 mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8) & 0xff;
2032 mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff;
2033 mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff;
2034 }
2035 debug(0, "command fixup");
2036
2037 /* submit the command and wait */
2038 if (mlx_wait_command(mc) != 0)
2039 return;
2040
2041 }
2042
2043 /********************************************************************************
2044 * Take a command from user-space and try to run it.
2045 *
2046 * XXX Note that this can't perform very much in the way of error checking, and
2047 * as such, applications _must_ be considered trustworthy.
2048 * XXX Commands using S/G for data are not supported.
2049 */
2050 static int
mlx_user_command(struct mlx_softc * sc,struct mlx_usercommand * mu)2051 mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
2052 {
2053 struct mlx_command *mc;
2054 void *kbuf;
2055 int error;
2056
2057 debug_called(0);
2058
2059 kbuf = NULL;
2060 mc = NULL;
2061 error = ENOMEM;
2062
2063 /* get ourselves a command and copy in from user space */
2064 MLX_IO_LOCK(sc);
2065 if ((mc = mlx_alloccmd(sc)) == NULL) {
2066 MLX_IO_UNLOCK(sc);
2067 return(error);
2068 }
2069 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
2070 debug(0, "got command buffer");
2071
2072 /*
2073 * if we need a buffer for data transfer, allocate one and copy in its
2074 * initial contents
2075 */
2076 if (mu->mu_datasize > 0) {
2077 if (mu->mu_datasize > MLX_MAXPHYS) {
2078 error = EINVAL;
2079 goto out;
2080 }
2081 MLX_IO_UNLOCK(sc);
2082 if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) ||
2083 (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))) {
2084 MLX_IO_LOCK(sc);
2085 goto out;
2086 }
2087 MLX_IO_LOCK(sc);
2088 debug(0, "got kernel buffer");
2089 }
2090
2091 /* get a command slot */
2092 if (mlx_getslot(mc))
2093 goto out;
2094 debug(0, "got a slot");
2095
2096 if (mu->mu_datasize > 0) {
2097
2098 /* range check the pointer to physical buffer address */
2099 if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) -
2100 sizeof(u_int32_t)))) {
2101 error = EINVAL;
2102 goto out;
2103 }
2104 }
2105
2106 /* map the command so the controller can see it */
2107 mc->mc_data = kbuf;
2108 mc->mc_length = mu->mu_datasize;
2109 mc->mc_private = mu;
2110 error = bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data,
2111 mc->mc_length, mlx_user_cb, mc, BUS_DMA_NOWAIT);
2112 if (error)
2113 goto out;
2114
2115 /* copy out status and data */
2116 mu->mu_status = mc->mc_status;
2117 if (mu->mu_datasize > 0) {
2118 MLX_IO_UNLOCK(sc);
2119 error = copyout(kbuf, mu->mu_buf, mu->mu_datasize);
2120 MLX_IO_LOCK(sc);
2121 }
2122
2123 out:
2124 mlx_releasecmd(mc);
2125 MLX_IO_UNLOCK(sc);
2126 if (kbuf != NULL)
2127 free(kbuf, M_DEVBUF);
2128 return(error);
2129 }
2130
2131 /********************************************************************************
2132 ********************************************************************************
2133 Command I/O to Controller
2134 ********************************************************************************
2135 ********************************************************************************/
2136
2137 /********************************************************************************
2138 * Find a free command slot for (mc).
2139 *
2140 * Don't hand out a slot to a normal-priority command unless there are at least
2141 * 4 slots free for priority commands.
2142 */
2143 static int
mlx_getslot(struct mlx_command * mc)2144 mlx_getslot(struct mlx_command *mc)
2145 {
2146 struct mlx_softc *sc = mc->mc_sc;
2147 int slot, limit;
2148
2149 debug_called(1);
2150
2151 MLX_IO_ASSERT_LOCKED(sc);
2152
2153 /*
2154 * Enforce slot-usage limit, if we have the required information.
2155 */
2156 if (sc->mlx_enq2 != NULL) {
2157 limit = sc->mlx_enq2->me_max_commands;
2158 } else {
2159 limit = 2;
2160 }
2161 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4))
2162 return(EBUSY);
2163
2164 /*
2165 * Allocate an outstanding command slot
2166 *
2167 * XXX linear search is slow
2168 */
2169 for (slot = 0; slot < limit; slot++) {
2170 debug(2, "try slot %d", slot);
2171 if (sc->mlx_busycmd[slot] == NULL)
2172 break;
2173 }
2174 if (slot < limit) {
2175 sc->mlx_busycmd[slot] = mc;
2176 sc->mlx_busycmds++;
2177 }
2178
2179 /* out of slots? */
2180 if (slot >= limit)
2181 return(EBUSY);
2182
2183 debug(2, "got slot %d", slot);
2184 mc->mc_slot = slot;
2185 return(0);
2186 }
2187
2188 /********************************************************************************
2189 * Map/unmap (mc)'s data in the controller's addressable space.
2190 */
2191 static void
mlx_setup_dmamap(struct mlx_command * mc,bus_dma_segment_t * segs,int nsegments,int error)2192 mlx_setup_dmamap(struct mlx_command *mc, bus_dma_segment_t *segs, int nsegments,
2193 int error)
2194 {
2195 struct mlx_softc *sc = mc->mc_sc;
2196 struct mlx_sgentry *sg;
2197 int i;
2198
2199 debug_called(1);
2200
2201 /* XXX should be unnecessary */
2202 if (sc->mlx_enq2 && (nsegments > sc->mlx_enq2->me_max_sg))
2203 panic("MLX: too many s/g segments (%d, max %d)", nsegments,
2204 sc->mlx_enq2->me_max_sg);
2205
2206 /* get base address of s/g table */
2207 sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
2208
2209 /* save s/g table information in command */
2210 mc->mc_nsgent = nsegments;
2211 mc->mc_sgphys = sc->mlx_sgbusaddr +
2212 (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
2213 mc->mc_dataphys = segs[0].ds_addr;
2214
2215 /* populate s/g table */
2216 for (i = 0; i < nsegments; i++, sg++) {
2217 sg->sg_addr = segs[i].ds_addr;
2218 sg->sg_count = segs[i].ds_len;
2219 }
2220
2221 /* Make sure the buffers are visible on the bus. */
2222 if (mc->mc_flags & MLX_CMD_DATAIN)
2223 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap,
2224 BUS_DMASYNC_PREREAD);
2225 if (mc->mc_flags & MLX_CMD_DATAOUT)
2226 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap,
2227 BUS_DMASYNC_PREWRITE);
2228 }
2229
2230 static void
mlx_unmapcmd(struct mlx_command * mc)2231 mlx_unmapcmd(struct mlx_command *mc)
2232 {
2233 struct mlx_softc *sc = mc->mc_sc;
2234
2235 debug_called(1);
2236
2237 /* if the command involved data at all */
2238 if (mc->mc_data != NULL) {
2239
2240 if (mc->mc_flags & MLX_CMD_DATAIN)
2241 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
2242 if (mc->mc_flags & MLX_CMD_DATAOUT)
2243 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
2244
2245 bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
2246 }
2247 }
2248
2249 /********************************************************************************
2250 * Try to deliver (mc) to the controller.
2251 *
2252 * Can be called at any interrupt level, with or without interrupts enabled.
2253 */
2254 static int
mlx_start(struct mlx_command * mc)2255 mlx_start(struct mlx_command *mc)
2256 {
2257 struct mlx_softc *sc = mc->mc_sc;
2258 int i;
2259
2260 debug_called(1);
2261
2262 /* save the slot number as ident so we can handle this command when complete */
2263 mc->mc_mailbox[0x1] = mc->mc_slot;
2264
2265 /* mark the command as currently being processed */
2266 mc->mc_status = MLX_STATUS_BUSY;
2267
2268 /* set a default 60-second timeout XXX tunable? XXX not currently used */
2269 mc->mc_timeout = time_second + 60;
2270
2271 /* spin waiting for the mailbox */
2272 for (i = 100000; i > 0; i--) {
2273 if (sc->mlx_tryqueue(sc, mc)) {
2274 /* move command to work queue */
2275 TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
2276 return (0);
2277 } else if (i > 1)
2278 mlx_done(sc, 0);
2279 }
2280
2281 /*
2282 * We couldn't get the controller to take the command. Revoke the slot
2283 * that the command was given and return it with a bad status.
2284 */
2285 sc->mlx_busycmd[mc->mc_slot] = NULL;
2286 device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
2287 mc->mc_status = MLX_STATUS_WEDGED;
2288 mlx_complete(sc);
2289 return(EIO);
2290 }
2291
2292 /********************************************************************************
2293 * Poll the controller (sc) for completed commands.
2294 * Update command status and free slots for reuse. If any slots were freed,
2295 * new commands may be posted.
2296 *
2297 * Returns nonzero if one or more commands were completed.
2298 */
2299 static int
mlx_done(struct mlx_softc * sc,int startio)2300 mlx_done(struct mlx_softc *sc, int startio)
2301 {
2302 struct mlx_command *mc;
2303 int result;
2304 u_int8_t slot;
2305 u_int16_t status;
2306
2307 debug_called(2);
2308 MLX_IO_ASSERT_LOCKED(sc);
2309
2310 result = 0;
2311
2312 /* loop collecting completed commands */
2313 for (;;) {
2314 /* poll for a completed command's identifier and status */
2315 if (sc->mlx_findcomplete(sc, &slot, &status)) {
2316 result = 1;
2317 mc = sc->mlx_busycmd[slot]; /* find command */
2318 if (mc != NULL) { /* paranoia */
2319 if (mc->mc_status == MLX_STATUS_BUSY) {
2320 mc->mc_status = status; /* save status */
2321
2322 /* free slot for reuse */
2323 sc->mlx_busycmd[slot] = NULL;
2324 sc->mlx_busycmds--;
2325 } else {
2326 device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
2327 }
2328 } else {
2329 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
2330 }
2331 } else {
2332 break;
2333 }
2334 }
2335
2336 /* if we've completed any commands, try posting some more */
2337 if (result && startio)
2338 mlx_startio(sc);
2339
2340 /* handle completion and timeouts */
2341 mlx_complete(sc);
2342
2343 return(result);
2344 }
2345
2346 /********************************************************************************
2347 * Perform post-completion processing for commands on (sc).
2348 */
2349 static void
mlx_complete(struct mlx_softc * sc)2350 mlx_complete(struct mlx_softc *sc)
2351 {
2352 struct mlx_command *mc, *nc;
2353
2354 debug_called(2);
2355 MLX_IO_ASSERT_LOCKED(sc);
2356
2357 /* scan the list of busy/done commands */
2358 mc = TAILQ_FIRST(&sc->mlx_work);
2359 while (mc != NULL) {
2360 nc = TAILQ_NEXT(mc, mc_link);
2361
2362 /* Command has been completed in some fashion */
2363 if (mc->mc_status != MLX_STATUS_BUSY) {
2364
2365 /* unmap the command's data buffer */
2366 mlx_unmapcmd(mc);
2367 /*
2368 * Does the command have a completion handler?
2369 */
2370 if (mc->mc_complete != NULL) {
2371 /* remove from list and give to handler */
2372 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2373 mc->mc_complete(mc);
2374
2375 /*
2376 * Is there a sleeper waiting on this command?
2377 */
2378 } else if (mc->mc_private != NULL) { /* sleeping caller wants to know about it */
2379
2380 /* remove from list and wake up sleeper */
2381 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2382 wakeup_one(mc->mc_private);
2383
2384 /*
2385 * Leave the command for a caller that's polling for it.
2386 */
2387 } else {
2388 }
2389 }
2390 mc = nc;
2391 }
2392 }
2393
2394 /********************************************************************************
2395 ********************************************************************************
2396 Command Buffer Management
2397 ********************************************************************************
2398 ********************************************************************************/
2399
2400 /********************************************************************************
2401 * Get a new command buffer.
2402 *
2403 * This may return NULL in low-memory cases.
2404 *
2405 * Note that using malloc() is expensive (the command buffer is << 1 page) but
2406 * necessary if we are to be a loadable module before the zone allocator is fixed.
2407 *
2408 * If possible, we recycle a command buffer that's been used before.
2409 *
2410 * XXX Note that command buffers are not cleaned out - it is the caller's
2411 * responsibility to ensure that all required fields are filled in before
2412 * using a buffer.
2413 */
2414 static struct mlx_command *
mlx_alloccmd(struct mlx_softc * sc)2415 mlx_alloccmd(struct mlx_softc *sc)
2416 {
2417 struct mlx_command *mc;
2418 int error;
2419
2420 debug_called(1);
2421
2422 MLX_IO_ASSERT_LOCKED(sc);
2423 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2424 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2425
2426 /* allocate a new command buffer? */
2427 if (mc == NULL) {
2428 mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT | M_ZERO);
2429 if (mc != NULL) {
2430 mc->mc_sc = sc;
2431 error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2432 if (error) {
2433 free(mc, M_DEVBUF);
2434 return(NULL);
2435 }
2436 }
2437 }
2438 return(mc);
2439 }
2440
2441 /********************************************************************************
2442 * Release a command buffer for recycling.
2443 *
2444 * XXX It might be a good idea to limit the number of commands we save for reuse
2445 * if it's shown that this list bloats out massively.
2446 */
2447 static void
mlx_releasecmd(struct mlx_command * mc)2448 mlx_releasecmd(struct mlx_command *mc)
2449 {
2450
2451 debug_called(1);
2452
2453 MLX_IO_ASSERT_LOCKED(mc->mc_sc);
2454 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2455 }
2456
2457 /********************************************************************************
2458 * Permanently discard a command buffer.
2459 */
2460 static void
mlx_freecmd(struct mlx_command * mc)2461 mlx_freecmd(struct mlx_command *mc)
2462 {
2463 struct mlx_softc *sc = mc->mc_sc;
2464
2465 debug_called(1);
2466 bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2467 free(mc, M_DEVBUF);
2468 }
2469
2470
2471 /********************************************************************************
2472 ********************************************************************************
2473 Type 3 interface accessor methods
2474 ********************************************************************************
2475 ********************************************************************************/
2476
2477 /********************************************************************************
2478 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2479 * (the controller is not ready to take a command).
2480 */
2481 static int
mlx_v3_tryqueue(struct mlx_softc * sc,struct mlx_command * mc)2482 mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2483 {
2484 int i;
2485
2486 debug_called(2);
2487 MLX_IO_ASSERT_LOCKED(sc);
2488
2489 /* ready for our command? */
2490 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_FULL)) {
2491 /* copy mailbox data to window */
2492 for (i = 0; i < 13; i++)
2493 MLX_V3_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2494
2495 /* post command */
2496 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
2497 return(1);
2498 }
2499 return(0);
2500 }
2501
2502 /********************************************************************************
2503 * See if a command has been completed, if so acknowledge its completion
2504 * and recover the slot number and status code.
2505 */
2506 static int
mlx_v3_findcomplete(struct mlx_softc * sc,u_int8_t * slot,u_int16_t * status)2507 mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2508 {
2509
2510 debug_called(2);
2511 MLX_IO_ASSERT_LOCKED(sc);
2512
2513 /* status available? */
2514 if (MLX_V3_GET_ODBR(sc) & MLX_V3_ODB_SAVAIL) {
2515 *slot = MLX_V3_GET_STATUS_IDENT(sc); /* get command identifier */
2516 *status = MLX_V3_GET_STATUS(sc); /* get status */
2517
2518 /* acknowledge completion */
2519 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
2520 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2521 return(1);
2522 }
2523 return(0);
2524 }
2525
2526 /********************************************************************************
2527 * Enable/disable interrupts as requested. (No acknowledge required)
2528 */
2529 static void
mlx_v3_intaction(struct mlx_softc * sc,int action)2530 mlx_v3_intaction(struct mlx_softc *sc, int action)
2531 {
2532 debug_called(1);
2533 MLX_IO_ASSERT_LOCKED(sc);
2534
2535 switch(action) {
2536 case MLX_INTACTION_DISABLE:
2537 MLX_V3_PUT_IER(sc, 0);
2538 sc->mlx_state &= ~MLX_STATE_INTEN;
2539 break;
2540 case MLX_INTACTION_ENABLE:
2541 MLX_V3_PUT_IER(sc, 1);
2542 sc->mlx_state |= MLX_STATE_INTEN;
2543 break;
2544 }
2545 }
2546
2547 /********************************************************************************
2548 * Poll for firmware error codes during controller initialisation.
2549 * Returns 0 if initialisation is complete, 1 if still in progress but no
2550 * error has been fetched, 2 if an error has been retrieved.
2551 */
2552 static int
mlx_v3_fw_handshake(struct mlx_softc * sc,int * error,int * param1,int * param2,int first)2553 mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2,
2554 int first)
2555 {
2556 u_int8_t fwerror;
2557
2558 debug_called(2);
2559
2560 /* first time around, clear any hardware completion status */
2561 if (first) {
2562 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2563 DELAY(1000);
2564 }
2565
2566 /* init in progress? */
2567 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY))
2568 return(0);
2569
2570 /* test error value */
2571 fwerror = MLX_V3_GET_FWERROR(sc);
2572 if (!(fwerror & MLX_V3_FWERROR_PEND))
2573 return(1);
2574
2575 /* mask status pending bit, fetch status */
2576 *error = fwerror & ~MLX_V3_FWERROR_PEND;
2577 *param1 = MLX_V3_GET_FWERROR_PARAM1(sc);
2578 *param2 = MLX_V3_GET_FWERROR_PARAM2(sc);
2579
2580 /* acknowledge */
2581 MLX_V3_PUT_FWERROR(sc, 0);
2582
2583 return(2);
2584 }
2585
2586 /********************************************************************************
2587 ********************************************************************************
2588 Type 4 interface accessor methods
2589 ********************************************************************************
2590 ********************************************************************************/
2591
2592 /********************************************************************************
2593 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2594 * (the controller is not ready to take a command).
2595 */
2596 static int
mlx_v4_tryqueue(struct mlx_softc * sc,struct mlx_command * mc)2597 mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2598 {
2599 int i;
2600
2601 debug_called(2);
2602 MLX_IO_ASSERT_LOCKED(sc);
2603
2604 /* ready for our command? */
2605 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_FULL)) {
2606 /* copy mailbox data to window */
2607 for (i = 0; i < 13; i++)
2608 MLX_V4_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2609
2610 /* memory-mapped controller, so issue a write barrier to ensure the mailbox is filled */
2611 bus_barrier(sc->mlx_mem, MLX_V4_MAILBOX, MLX_V4_MAILBOX_LENGTH,
2612 BUS_SPACE_BARRIER_WRITE);
2613
2614 /* post command */
2615 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2616 return(1);
2617 }
2618 return(0);
2619 }
2620
2621 /********************************************************************************
2622 * See if a command has been completed, if so acknowledge its completion
2623 * and recover the slot number and status code.
2624 */
2625 static int
mlx_v4_findcomplete(struct mlx_softc * sc,u_int8_t * slot,u_int16_t * status)2626 mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2627 {
2628
2629 debug_called(2);
2630 MLX_IO_ASSERT_LOCKED(sc);
2631
2632 /* status available? */
2633 if (MLX_V4_GET_ODBR(sc) & MLX_V4_ODB_HWSAVAIL) {
2634 *slot = MLX_V4_GET_STATUS_IDENT(sc); /* get command identifier */
2635 *status = MLX_V4_GET_STATUS(sc); /* get status */
2636
2637 /* acknowledge completion */
2638 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
2639 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2640 return(1);
2641 }
2642 return(0);
2643 }
2644
2645 /********************************************************************************
2646 * Enable/disable interrupts as requested.
2647 */
2648 static void
mlx_v4_intaction(struct mlx_softc * sc,int action)2649 mlx_v4_intaction(struct mlx_softc *sc, int action)
2650 {
2651 debug_called(1);
2652 MLX_IO_ASSERT_LOCKED(sc);
2653
2654 switch(action) {
2655 case MLX_INTACTION_DISABLE:
2656 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK | MLX_V4_IER_DISINT);
2657 sc->mlx_state &= ~MLX_STATE_INTEN;
2658 break;
2659 case MLX_INTACTION_ENABLE:
2660 MLX_V4_PUT_IER(sc, MLX_V4_IER_MASK & ~MLX_V4_IER_DISINT);
2661 sc->mlx_state |= MLX_STATE_INTEN;
2662 break;
2663 }
2664 }
2665
2666 /********************************************************************************
2667 * Poll for firmware error codes during controller initialisation.
2668 * Returns 0 if initialisation is complete, 1 if still in progress but no
2669 * error has been fetched, 2 if an error has been retrieved.
2670 */
2671 static int
mlx_v4_fw_handshake(struct mlx_softc * sc,int * error,int * param1,int * param2,int first)2672 mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2,
2673 int first)
2674 {
2675 u_int8_t fwerror;
2676
2677 debug_called(2);
2678
2679 /* first time around, clear any hardware completion status */
2680 if (first) {
2681 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2682 DELAY(1000);
2683 }
2684
2685 /* init in progress? */
2686 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY))
2687 return(0);
2688
2689 /* test error value */
2690 fwerror = MLX_V4_GET_FWERROR(sc);
2691 if (!(fwerror & MLX_V4_FWERROR_PEND))
2692 return(1);
2693
2694 /* mask status pending bit, fetch status */
2695 *error = fwerror & ~MLX_V4_FWERROR_PEND;
2696 *param1 = MLX_V4_GET_FWERROR_PARAM1(sc);
2697 *param2 = MLX_V4_GET_FWERROR_PARAM2(sc);
2698
2699 /* acknowledge */
2700 MLX_V4_PUT_FWERROR(sc, 0);
2701
2702 return(2);
2703 }
2704
2705 /********************************************************************************
2706 ********************************************************************************
2707 Type 5 interface accessor methods
2708 ********************************************************************************
2709 ********************************************************************************/
2710
2711 /********************************************************************************
2712 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2713 * (the controller is not ready to take a command).
2714 */
2715 static int
mlx_v5_tryqueue(struct mlx_softc * sc,struct mlx_command * mc)2716 mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2717 {
2718 int i;
2719
2720 debug_called(2);
2721 MLX_IO_ASSERT_LOCKED(sc);
2722
2723 /* ready for our command? */
2724 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
2725 /* copy mailbox data to window */
2726 for (i = 0; i < 13; i++)
2727 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2728
2729 /* post command */
2730 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2731 return(1);
2732 }
2733 return(0);
2734 }
2735
2736 /********************************************************************************
2737 * See if a command has been completed, if so acknowledge its completion
2738 * and recover the slot number and status code.
2739 */
2740 static int
mlx_v5_findcomplete(struct mlx_softc * sc,u_int8_t * slot,u_int16_t * status)2741 mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2742 {
2743
2744 debug_called(2);
2745 MLX_IO_ASSERT_LOCKED(sc);
2746
2747 /* status available? */
2748 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
2749 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */
2750 *status = MLX_V5_GET_STATUS(sc); /* get status */
2751
2752 /* acknowledge completion */
2753 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);
2754 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2755 return(1);
2756 }
2757 return(0);
2758 }
2759
2760 /********************************************************************************
2761 * Enable/disable interrupts as requested.
2762 */
2763 static void
mlx_v5_intaction(struct mlx_softc * sc,int action)2764 mlx_v5_intaction(struct mlx_softc *sc, int action)
2765 {
2766 debug_called(1);
2767 MLX_IO_ASSERT_LOCKED(sc);
2768
2769 switch(action) {
2770 case MLX_INTACTION_DISABLE:
2771 MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT);
2772 sc->mlx_state &= ~MLX_STATE_INTEN;
2773 break;
2774 case MLX_INTACTION_ENABLE:
2775 MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT);
2776 sc->mlx_state |= MLX_STATE_INTEN;
2777 break;
2778 }
2779 }
2780
2781 /********************************************************************************
2782 * Poll for firmware error codes during controller initialisation.
2783 * Returns 0 if initialisation is complete, 1 if still in progress but no
2784 * error has been fetched, 2 if an error has been retrieved.
2785 */
2786 static int
mlx_v5_fw_handshake(struct mlx_softc * sc,int * error,int * param1,int * param2,int first)2787 mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2,
2788 int first)
2789 {
2790 u_int8_t fwerror;
2791
2792 debug_called(2);
2793
2794 /* first time around, clear any hardware completion status */
2795 if (first) {
2796 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2797 DELAY(1000);
2798 }
2799
2800 /* init in progress? */
2801 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE)
2802 return(0);
2803
2804 /* test for error value */
2805 fwerror = MLX_V5_GET_FWERROR(sc);
2806 if (!(fwerror & MLX_V5_FWERROR_PEND))
2807 return(1);
2808
2809 /* mask status pending bit, fetch status */
2810 *error = fwerror & ~MLX_V5_FWERROR_PEND;
2811 *param1 = MLX_V5_GET_FWERROR_PARAM1(sc);
2812 *param2 = MLX_V5_GET_FWERROR_PARAM2(sc);
2813
2814 /* acknowledge */
2815 MLX_V5_PUT_FWERROR(sc, 0xff);
2816
2817 return(2);
2818 }
2819
2820 /********************************************************************************
2821 ********************************************************************************
2822 Debugging
2823 ********************************************************************************
2824 ********************************************************************************/
2825
2826 /********************************************************************************
2827 * Return a status message describing (mc)
2828 */
2829 static char *mlx_status_messages[] = {
2830 "normal completion", /* 00 */
2831 "irrecoverable data error", /* 01 */
2832 "drive does not exist, or is offline", /* 02 */
2833 "attempt to write beyond end of drive", /* 03 */
2834 "bad data encountered", /* 04 */
2835 "invalid log entry request", /* 05 */
2836 "attempt to rebuild online drive", /* 06 */
2837 "new disk failed during rebuild", /* 07 */
2838 "invalid channel/target", /* 08 */
2839 "rebuild/check already in progress", /* 09 */
2840 "one or more disks are dead", /* 10 */
2841 "invalid or non-redundant drive", /* 11 */
2842 "channel is busy", /* 12 */
2843 "channel is not stopped", /* 13 */
2844 "rebuild successfully terminated", /* 14 */
2845 "unsupported command", /* 15 */
2846 "check condition received", /* 16 */
2847 "device is busy", /* 17 */
2848 "selection or command timeout", /* 18 */
2849 "command terminated abnormally", /* 19 */
2850 ""
2851 };
2852
2853 static struct
2854 {
2855 int command;
2856 u_int16_t status;
2857 int msg;
2858 } mlx_messages[] = {
2859 {MLX_CMD_READSG, 0x0001, 1},
2860 {MLX_CMD_READSG, 0x0002, 1},
2861 {MLX_CMD_READSG, 0x0105, 3},
2862 {MLX_CMD_READSG, 0x010c, 4},
2863 {MLX_CMD_WRITESG, 0x0001, 1},
2864 {MLX_CMD_WRITESG, 0x0002, 1},
2865 {MLX_CMD_WRITESG, 0x0105, 3},
2866 {MLX_CMD_READSG_OLD, 0x0001, 1},
2867 {MLX_CMD_READSG_OLD, 0x0002, 1},
2868 {MLX_CMD_READSG_OLD, 0x0105, 3},
2869 {MLX_CMD_WRITESG_OLD, 0x0001, 1},
2870 {MLX_CMD_WRITESG_OLD, 0x0002, 1},
2871 {MLX_CMD_WRITESG_OLD, 0x0105, 3},
2872 {MLX_CMD_LOGOP, 0x0105, 5},
2873 {MLX_CMD_REBUILDASYNC, 0x0002, 6},
2874 {MLX_CMD_REBUILDASYNC, 0x0004, 7},
2875 {MLX_CMD_REBUILDASYNC, 0x0105, 8},
2876 {MLX_CMD_REBUILDASYNC, 0x0106, 9},
2877 {MLX_CMD_REBUILDASYNC, 0x0107, 14},
2878 {MLX_CMD_CHECKASYNC, 0x0002, 10},
2879 {MLX_CMD_CHECKASYNC, 0x0105, 11},
2880 {MLX_CMD_CHECKASYNC, 0x0106, 9},
2881 {MLX_CMD_STOPCHANNEL, 0x0106, 12},
2882 {MLX_CMD_STOPCHANNEL, 0x0105, 8},
2883 {MLX_CMD_STARTCHANNEL, 0x0005, 13},
2884 {MLX_CMD_STARTCHANNEL, 0x0105, 8},
2885 {MLX_CMD_DIRECT_CDB, 0x0002, 16},
2886 {MLX_CMD_DIRECT_CDB, 0x0008, 17},
2887 {MLX_CMD_DIRECT_CDB, 0x000e, 18},
2888 {MLX_CMD_DIRECT_CDB, 0x000f, 19},
2889 {MLX_CMD_DIRECT_CDB, 0x0105, 8},
2890
2891 {0, 0x0104, 14},
2892 {-1, 0, 0}
2893 };
2894
2895 static char *
mlx_diagnose_command(struct mlx_command * mc)2896 mlx_diagnose_command(struct mlx_command *mc)
2897 {
2898 static char unkmsg[80];
2899 int i;
2900
2901 /* look up message in table */
2902 for (i = 0; mlx_messages[i].command != -1; i++)
2903 if (((mc->mc_mailbox[0] == mlx_messages[i].command) || (mlx_messages[i].command == 0)) &&
2904 (mc->mc_status == mlx_messages[i].status))
2905 return(mlx_status_messages[mlx_messages[i].msg]);
2906
2907 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2908 return(unkmsg);
2909 }
2910
2911 /*******************************************************************************
2912 * Print a string describing the controller (sc)
2913 */
2914 static struct
2915 {
2916 int hwid;
2917 char *name;
2918 } mlx_controller_names[] = {
2919 {0x01, "960P/PD"},
2920 {0x02, "960PL"},
2921 {0x10, "960PG"},
2922 {0x11, "960PJ"},
2923 {0x12, "960PR"},
2924 {0x13, "960PT"},
2925 {0x14, "960PTL0"},
2926 {0x15, "960PRL"},
2927 {0x16, "960PTL1"},
2928 {0x20, "1164PVX"},
2929 {-1, NULL}
2930 };
2931
2932 static void
mlx_describe_controller(struct mlx_softc * sc)2933 mlx_describe_controller(struct mlx_softc *sc)
2934 {
2935 static char buf[80];
2936 char *model;
2937 int i;
2938
2939 for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) {
2940 if ((sc->mlx_enq2->me_hardware_id & 0xff) == mlx_controller_names[i].hwid) {
2941 model = mlx_controller_names[i].name;
2942 break;
2943 }
2944 }
2945 if (model == NULL) {
2946 sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
2947 model = buf;
2948 }
2949 device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
2950 model,
2951 sc->mlx_enq2->me_actual_channels,
2952 sc->mlx_enq2->me_actual_channels > 1 ? "s" : "",
2953 sc->mlx_enq2->me_firmware_id & 0xff,
2954 (sc->mlx_enq2->me_firmware_id >> 8) & 0xff,
2955 (sc->mlx_enq2->me_firmware_id >> 24) & 0xff,
2956 (sc->mlx_enq2->me_firmware_id >> 16) & 0xff,
2957 sc->mlx_enq2->me_mem_size / (1024 * 1024));
2958
2959 if (bootverbose) {
2960 device_printf(sc->mlx_dev, " Hardware ID 0x%08x\n", sc->mlx_enq2->me_hardware_id);
2961 device_printf(sc->mlx_dev, " Firmware ID 0x%08x\n", sc->mlx_enq2->me_firmware_id);
2962 device_printf(sc->mlx_dev, " Configured/Actual channels %d/%d\n", sc->mlx_enq2->me_configured_channels,
2963 sc->mlx_enq2->me_actual_channels);
2964 device_printf(sc->mlx_dev, " Max Targets %d\n", sc->mlx_enq2->me_max_targets);
2965 device_printf(sc->mlx_dev, " Max Tags %d\n", sc->mlx_enq2->me_max_tags);
2966 device_printf(sc->mlx_dev, " Max System Drives %d\n", sc->mlx_enq2->me_max_sys_drives);
2967 device_printf(sc->mlx_dev, " Max Arms %d\n", sc->mlx_enq2->me_max_arms);
2968 device_printf(sc->mlx_dev, " Max Spans %d\n", sc->mlx_enq2->me_max_spans);
2969 device_printf(sc->mlx_dev, " DRAM/cache/flash/NVRAM size %d/%d/%d/%d\n", sc->mlx_enq2->me_mem_size,
2970 sc->mlx_enq2->me_cache_size, sc->mlx_enq2->me_flash_size, sc->mlx_enq2->me_nvram_size);
2971 device_printf(sc->mlx_dev, " DRAM type %d\n", sc->mlx_enq2->me_mem_type);
2972 device_printf(sc->mlx_dev, " Clock Speed %dns\n", sc->mlx_enq2->me_clock_speed);
2973 device_printf(sc->mlx_dev, " Hardware Speed %dns\n", sc->mlx_enq2->me_hardware_speed);
2974 device_printf(sc->mlx_dev, " Max Commands %d\n", sc->mlx_enq2->me_max_commands);
2975 device_printf(sc->mlx_dev, " Max SG Entries %d\n", sc->mlx_enq2->me_max_sg);
2976 device_printf(sc->mlx_dev, " Max DP %d\n", sc->mlx_enq2->me_max_dp);
2977 device_printf(sc->mlx_dev, " Max IOD %d\n", sc->mlx_enq2->me_max_iod);
2978 device_printf(sc->mlx_dev, " Max Comb %d\n", sc->mlx_enq2->me_max_comb);
2979 device_printf(sc->mlx_dev, " Latency %ds\n", sc->mlx_enq2->me_latency);
2980 device_printf(sc->mlx_dev, " SCSI Timeout %ds\n", sc->mlx_enq2->me_scsi_timeout);
2981 device_printf(sc->mlx_dev, " Min Free Lines %d\n", sc->mlx_enq2->me_min_freelines);
2982 device_printf(sc->mlx_dev, " Rate Constant %d\n", sc->mlx_enq2->me_rate_const);
2983 device_printf(sc->mlx_dev, " MAXBLK %d\n", sc->mlx_enq2->me_maxblk);
2984 device_printf(sc->mlx_dev, " Blocking Factor %d sectors\n", sc->mlx_enq2->me_blocking_factor);
2985 device_printf(sc->mlx_dev, " Cache Line Size %d blocks\n", sc->mlx_enq2->me_cacheline);
2986 device_printf(sc->mlx_dev, " SCSI Capability %s%dMHz, %d bit\n",
2987 sc->mlx_enq2->me_scsi_cap & (1<<4) ? "differential " : "",
2988 (1 << ((sc->mlx_enq2->me_scsi_cap >> 2) & 3)) * 10,
2989 8 << (sc->mlx_enq2->me_scsi_cap & 0x3));
2990 device_printf(sc->mlx_dev, " Firmware Build Number %d\n", sc->mlx_enq2->me_firmware_build);
2991 device_printf(sc->mlx_dev, " Fault Management Type %d\n", sc->mlx_enq2->me_fault_mgmt_type);
2992 device_printf(sc->mlx_dev, " Features %b\n", sc->mlx_enq2->me_firmware_features,
2993 "\20\4Background Init\3Read Ahead\2MORE\1Cluster\n");
2994
2995 }
2996 }
2997
2998 /*******************************************************************************
2999 * Emit a string describing the firmware handshake status code, and return a flag
3000 * indicating whether the code represents a fatal error.
3001 *
3002 * Error code interpretations are from the Linux driver, and don't directly match
3003 * the messages printed by Mylex's BIOS. This may change if documentation on the
3004 * codes is forthcoming.
3005 */
3006 static int
mlx_fw_message(struct mlx_softc * sc,int error,int param1,int param2)3007 mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2)
3008 {
3009 switch(error) {
3010 case 0x00:
3011 device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1);
3012 break;
3013 case 0x08:
3014 /* we could be neater about this and give some indication when we receive more of them */
3015 if (!(sc->mlx_flags & MLX_SPINUP_REPORTED)) {
3016 device_printf(sc->mlx_dev, "spinning up drives...\n");
3017 sc->mlx_flags |= MLX_SPINUP_REPORTED;
3018 }
3019 break;
3020 case 0x30:
3021 device_printf(sc->mlx_dev, "configuration checksum error\n");
3022 break;
3023 case 0x60:
3024 device_printf(sc->mlx_dev, "mirror race recovery failed\n");
3025 break;
3026 case 0x70:
3027 device_printf(sc->mlx_dev, "mirror race recovery in progress\n");
3028 break;
3029 case 0x90:
3030 device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1);
3031 break;
3032 case 0xa0:
3033 device_printf(sc->mlx_dev, "logical drive installation aborted\n");
3034 break;
3035 case 0xb0:
3036 device_printf(sc->mlx_dev, "mirror race on a critical system drive\n");
3037 break;
3038 case 0xd0:
3039 device_printf(sc->mlx_dev, "new controller configuration found\n");
3040 break;
3041 case 0xf0:
3042 device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n");
3043 return(1);
3044 default:
3045 device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2);
3046 break;
3047 }
3048 return(0);
3049 }
3050
3051 /********************************************************************************
3052 ********************************************************************************
3053 Utility Functions
3054 ********************************************************************************
3055 ********************************************************************************/
3056
3057 /********************************************************************************
3058 * Find the disk whose unit number is (unit) on this controller
3059 */
3060 static struct mlx_sysdrive *
mlx_findunit(struct mlx_softc * sc,int unit)3061 mlx_findunit(struct mlx_softc *sc, int unit)
3062 {
3063 int i;
3064
3065 /* search system drives */
3066 MLX_CONFIG_ASSERT_LOCKED(sc);
3067 for (i = 0; i < MLX_MAXDRIVES; i++) {
3068 /* is this one attached? */
3069 if (sc->mlx_sysdrive[i].ms_disk != 0) {
3070 /* is this the one? */
3071 if (unit == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
3072 return(&sc->mlx_sysdrive[i]);
3073 }
3074 }
3075 return(NULL);
3076 }
3077