2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 1999 Michael Smith
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 * Driver for the Mylex DAC960 family of RAID controllers.
35 #include <sys/param.h>
36 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/mutex.h>
41 #include <sys/kernel.h>
48 #include <machine/resource.h>
49 #include <machine/bus.h>
50 #include <machine/clock.h>
53 #include <geom/geom_disk.h>
55 #include <dev/mlx/mlxio.h>
56 #include <dev/mlx/mlxvar.h>
57 #include <dev/mlx/mlxreg.h>
59 static struct cdevsw mlx_cdevsw = {
60 .d_version = D_VERSION,
67 devclass_t mlx_devclass;
70 * Per-interface accessor methods
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);
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);
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);
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);
99 static void mlx_pause_action(struct mlx_softc *sc);
100 static void mlx_pause_done(struct mlx_command *mc);
103 * Command submission.
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);
123 * Command buffer allocation.
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);
130 * Command management.
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);
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);
152 static struct mlx_sysdrive *mlx_findunit(struct mlx_softc *sc, int unit);
154 /********************************************************************************
155 ********************************************************************************
157 ********************************************************************************
158 ********************************************************************************/
160 /********************************************************************************
161 * Free all of the resources associated with (sc)
163 * Should not be called if the controller is active.
166 mlx_free(struct mlx_softc *sc)
168 struct mlx_command *mc;
172 /* destroy control device */
173 if (sc->mlx_dev_t != NULL)
174 destroy_dev(sc->mlx_dev_t);
177 bus_teardown_intr(sc->mlx_dev, sc->mlx_irq, sc->mlx_intr);
179 /* cancel status timeout */
181 callout_stop(&sc->mlx_timeout);
183 /* throw away any command buffers */
184 while ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL) {
185 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
189 callout_drain(&sc->mlx_timeout);
191 /* destroy data-transfer DMA tag */
192 if (sc->mlx_buffer_dmat)
193 bus_dma_tag_destroy(sc->mlx_buffer_dmat);
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);
199 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
201 bus_dma_tag_destroy(sc->mlx_sg_dmat);
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);
207 /* destroy the parent DMA tag */
208 if (sc->mlx_parent_dmat)
209 bus_dma_tag_destroy(sc->mlx_parent_dmat);
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);
215 /* free controller enquiry data */
216 if (sc->mlx_enq2 != NULL)
217 free(sc->mlx_enq2, M_DEVBUF);
219 sx_destroy(&sc->mlx_config_lock);
220 mtx_destroy(&sc->mlx_io_lock);
223 /********************************************************************************
224 * Map the scatter/gather table into bus space
227 mlx_dma_map_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
229 struct mlx_softc *sc = (struct mlx_softc *)arg;
233 /* save base of s/g table's address in bus space */
234 sc->mlx_sgbusaddr = segs->ds_addr;
238 mlx_sglist_map(struct mlx_softc *sc)
245 /* destroy any existing mappings */
246 if (sc->mlx_sgbusaddr)
247 bus_dmamap_unload(sc->mlx_sg_dmat, sc->mlx_sg_dmamap);
249 bus_dmamem_free(sc->mlx_sg_dmat, sc->mlx_sgtable, sc->mlx_sg_dmamap);
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;
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
262 if (sc->mlx_enq2 == NULL) {
265 ncmd = sc->mlx_enq2->me_max_commands;
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 */
276 NULL, NULL, /* lockfunc, lockarg */
279 device_printf(sc->mlx_dev, "can't allocate scatter/gather DMA tag\n");
284 * Allocate enough s/g maps for all commands and permanently map them into
285 * controller-visible space.
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
292 error = bus_dmamem_alloc(sc->mlx_sg_dmat, (void **)&sc->mlx_sgtable,
293 BUS_DMA_NOWAIT, &sc->mlx_sg_dmamap);
295 device_printf(sc->mlx_dev, "can't allocate s/g table\n");
298 (void)bus_dmamap_load(sc->mlx_sg_dmat, sc->mlx_sg_dmamap, sc->mlx_sgtable,
299 segsize, mlx_dma_map_sg, sc, 0);
303 /********************************************************************************
304 * Initialise the controller and softc
307 mlx_attach(struct mlx_softc *sc)
309 struct mlx_enquiry_old *meo;
310 int rid, error, fwminor, hscode, hserror, hsparam1, hsparam2, hsmsg;
315 * Initialise per-controller queues.
317 TAILQ_INIT(&sc->mlx_work);
318 TAILQ_INIT(&sc->mlx_freecmds);
319 bioq_init(&sc->mlx_bioq);
322 * Select accessor methods based on controller interface type.
324 switch(sc->mlx_iftype) {
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;
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;
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;
345 return(ENXIO); /* should never happen */
348 /* disable interrupts before we start talking to the controller */
350 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
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
360 while ((hscode = sc->mlx_fw_handshake(sc, &hserror, &hsparam1, &hsparam2,
362 /* report first time around... */
364 device_printf(sc->mlx_dev, "controller initialisation in progress...\n");
367 /* did we get a real message? */
369 hscode = mlx_fw_message(sc, hserror, hsparam1, hsparam2);
370 /* fatal initialisation error? */
377 device_printf(sc->mlx_dev, "initialisation complete.\n");
380 * Allocate and connect our interrupt.
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");
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);
392 device_printf(sc->mlx_dev, "can't set up interrupt\n");
397 * Create DMA tag for mapping buffers into controller-addressable space.
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 */
408 busdma_lock_mutex, /* lockfunc */
409 &sc->mlx_io_lock, /* lockarg */
410 &sc->mlx_buffer_dmat);
412 device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
417 * Create some initial scatter/gather mappings so we can run the probe
420 error = mlx_sglist_map(sc);
422 device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n");
427 * We don't (yet) know where the event log is up to.
429 sc->mlx_currevent = -1;
432 * Obtain controller feature information
435 if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
437 device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
442 * Do quirk/feature related things.
444 fwminor = (sc->mlx_enq2->me_firmware_id >> 8) & 0xff;
445 switch(sc->mlx_iftype) {
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) {
450 device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n");
453 sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor;
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");
463 /* XXX certify 3.52? */
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");
470 /* XXX certify firmware versions? */
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");
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");
484 return(ENXIO); /* should never happen */
489 * Create the final scatter/gather mappings now that we have characterised the controller.
491 error = mlx_sglist_map(sc);
493 device_printf(sc->mlx_dev, "can't make final s/g list mapping\n");
498 * No user-requested background operation is in progress.
500 sc->mlx_background = 0;
501 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
504 * Create the control device.
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;
511 * Start the timeout routine.
513 callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc);
515 /* print a little information about the controller */
516 mlx_describe_controller(sc);
521 /********************************************************************************
522 * Locate disk resources and attach children to them.
525 mlx_startup(struct mlx_softc *sc)
527 struct mlx_enq_sys_drive *mes;
528 struct mlx_sysdrive *dr;
534 * Scan all the system drives and attach children for those that
535 * don't currently have them.
538 mes = mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(*mes) * MLX_MAXDRIVES, NULL);
541 device_printf(sc->mlx_dev, "error fetching drive status\n");
545 /* iterate over drives returned */
547 for (i = 0, dr = &sc->mlx_sysdrive[0];
548 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
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;
557 /* generate geometry information */
558 if (sc->mlx_geom == MLX_GEOM_128_32) {
561 dr->ms_cylinders = dr->ms_size / (128 * 32);
562 } else { /* MLX_GEOM_255/63 */
565 dr->ms_cylinders = dr->ms_size / (255 * 63);
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);
574 if ((error = bus_generic_attach(sc->mlx_dev)) != 0)
575 device_printf(sc->mlx_dev, "bus_generic_attach returned %d", error);
577 /* mark controller back up */
579 sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
581 /* enable interrupts */
582 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
584 MLX_CONFIG_UNLOCK(sc);
587 /********************************************************************************
588 * Disconnect from the controller completely, in preparation for unload.
591 mlx_detach(device_t dev)
593 struct mlx_softc *sc = device_get_softc(dev);
594 struct mlxd_softc *mlxd;
601 if (sc->mlx_state & MLX_STATE_OPEN)
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");
613 if ((error = mlx_shutdown(dev)))
615 MLX_CONFIG_UNLOCK(sc);
621 MLX_CONFIG_UNLOCK(sc);
625 /********************************************************************************
626 * Bring the controller down to a dormant state and detach all child devices.
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.)
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.
636 mlx_shutdown(device_t dev)
638 struct mlx_softc *sc = device_get_softc(dev);
642 error = mlx_shutdown_locked(sc);
643 MLX_CONFIG_UNLOCK(sc);
648 mlx_shutdown_locked(struct mlx_softc *sc)
654 MLX_CONFIG_ASSERT_LOCKED(sc);
657 sc->mlx_state |= MLX_STATE_SHUTDOWN;
658 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
660 /* flush controller */
661 device_printf(sc->mlx_dev, "flushing cache...");
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)
674 sc->mlx_sysdrive[i].ms_disk = 0;
681 /********************************************************************************
682 * Bring the controller to a quiescent state, ready for system suspend.
685 mlx_suspend(device_t dev)
687 struct mlx_softc *sc = device_get_softc(dev);
692 sc->mlx_state |= MLX_STATE_SUSPEND;
694 /* flush controller */
695 device_printf(sc->mlx_dev, "flushing cache...");
696 printf("%s\n", mlx_flush(sc) ? "failed" : "done");
698 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
704 /********************************************************************************
705 * Bring the controller back to a state ready for operation.
708 mlx_resume(device_t dev)
710 struct mlx_softc *sc = device_get_softc(dev);
715 sc->mlx_state &= ~MLX_STATE_SUSPEND;
716 sc->mlx_intaction(sc, MLX_INTACTION_ENABLE);
722 /*******************************************************************************
723 * Take an interrupt, or be poked by other code to look for interrupt-worthy
729 struct mlx_softc *sc = (struct mlx_softc *)arg;
733 /* collect finished commands, queue anything waiting */
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.
744 mlx_submit_buf(struct mlx_softc *sc, struct bio *bp)
749 MLX_IO_ASSERT_LOCKED(sc);
750 bioq_insert_tail(&sc->mlx_bioq, bp);
756 /********************************************************************************
757 * Accept an open operation on the control device.
760 mlx_open(struct cdev *dev, int flags, int fmt, struct thread *td)
762 struct mlx_softc *sc = dev->si_drv1;
766 sc->mlx_state |= MLX_STATE_OPEN;
768 MLX_CONFIG_UNLOCK(sc);
772 /********************************************************************************
773 * Accept the last close on the control device.
776 mlx_close(struct cdev *dev, int flags, int fmt, struct thread *td)
778 struct mlx_softc *sc = dev->si_drv1;
782 sc->mlx_state &= ~MLX_STATE_OPEN;
784 MLX_CONFIG_UNLOCK(sc);
788 /********************************************************************************
789 * Handle controller-specific control operations.
792 mlx_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
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;
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.
810 /* search system drives */
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? */
817 *arg = device_get_unit(sc->mlx_sysdrive[i].ms_disk);
818 MLX_CONFIG_UNLOCK(sc);
821 /* we want the one after this one */
822 if (*arg == device_get_unit(sc->mlx_sysdrive[i].ms_disk))
826 MLX_CONFIG_UNLOCK(sc);
830 * Scan the controller to see whether new drives have appeared.
832 case MLX_RESCAN_DRIVES:
839 * Disconnect from the specified drive; it may be about to go
842 case MLX_DETACH_DRIVE: /* detach one drive */
844 if (((dr = mlx_findunit(sc, *arg)) == NULL) ||
845 ((mlxd = device_get_softc(dr->ms_disk)) == NULL)) {
846 MLX_CONFIG_UNLOCK(sc);
850 device_printf(dr->ms_disk, "detaching...");
852 if (mlxd->mlxd_flags & MLXD_OPEN) {
857 /* flush controller */
867 if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
872 MLX_CONFIG_UNLOCK(sc);
881 * Pause one or more SCSI channels for a period of time, to assist
882 * in the process of hot-swapping devices.
884 * Note that at least the 3.51 firmware on the DAC960PL doesn't seem
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))
892 /* check time values */
893 mp = (struct mlx_pause *)addr;
894 if ((mp->mp_when < 0) || (mp->mp_when > 3600))
896 if ((mp->mp_howlong < 1) || (mp->mp_howlong > (0xf * 30)))
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;
904 /* fix for legal channels */
905 mp->mp_which &= ((1 << sc->mlx_enq2->me_actual_channels) -1);
907 /* check for a pause currently running */
908 if ((sc->mlx_pause.mp_which != 0) && (sc->mlx_pause.mp_when == 0)) {
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;
922 * Accept a command passthrough-style.
925 return(mlx_user_command(sc, (struct mlx_usercommand *)addr));
928 * Start a rebuild on a given SCSI disk
930 case MLX_REBUILDASYNC:
932 if (sc->mlx_background != 0) {
934 rb->rr_status = 0x0106;
937 rb->rr_status = mlx_rebuild(sc, rb->rr_channel, rb->rr_target);
938 switch (rb->rr_status) {
943 error = ENOMEM; /* couldn't set up the command */
962 sc->mlx_background = MLX_BACKGROUND_REBUILD;
967 * Get the status of the current rebuild or consistency check.
969 case MLX_REBUILDSTAT:
971 *rs = sc->mlx_rebuildstat;
976 * Return the per-controller system drive number matching the
977 * disk device number in (arg), if it happens to belong to us.
979 case MLX_GET_SYSDRIVE:
983 mlxd = (struct mlxd_softc *)devclass_get_softc(mlxd_devclass, *arg);
985 if ((mlxd != NULL) && (mlxd->mlxd_drive >= sc->mlx_sysdrive) &&
986 (mlxd->mlxd_drive < (sc->mlx_sysdrive + MLX_MAXDRIVES))) {
988 *arg = mlxd->mlxd_drive - sc->mlx_sysdrive;
990 MLX_CONFIG_UNLOCK(sc);
998 /********************************************************************************
999 * Handle operations requested by a System Drive connected to this controller.
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)
1005 int *arg = (int *)addr;
1010 * Return the current status of this drive.
1014 *arg = drive->ms_state;
1019 * Start a background consistency check on this drive.
1021 case MLXD_CHECKASYNC: /* start a background consistency check */
1023 if (sc->mlx_background != 0) {
1028 result = mlx_check(sc, drive - &sc->mlx_sysdrive[0]);
1034 error = ENOMEM; /* couldn't set up the command */
1050 sc->mlx_background = MLX_BACKGROUND_CHECK;
1060 /********************************************************************************
1061 ********************************************************************************
1063 ********************************************************************************
1064 ********************************************************************************/
1066 /********************************************************************************
1067 * Fire off commands to periodically check the status of connected drives.
1070 mlx_periodic(void *data)
1072 struct mlx_softc *sc = (struct mlx_softc *)data;
1075 MLX_IO_ASSERT_LOCKED(sc);
1080 if ((sc->mlx_pause.mp_which != 0) &&
1081 (sc->mlx_pause.mp_when > 0) &&
1082 (time_second >= sc->mlx_pause.mp_when)){
1084 mlx_pause_action(sc); /* pause is running */
1085 sc->mlx_pause.mp_when = 0;
1089 * Bus pause still running?
1091 } else if ((sc->mlx_pause.mp_which != 0) &&
1092 (sc->mlx_pause.mp_when == 0)) {
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 */
1100 sysbeep((time_second % 5) * 100 + 500, hz/8);
1104 * Run normal periodic activities?
1106 } else if (time_second > (sc->mlx_lastpoll + 10)) {
1107 sc->mlx_lastpoll = time_second;
1110 * Check controller status.
1112 * XXX Note that this may not actually launch a command in situations of high load.
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);
1118 * Check system drive status.
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
1124 mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
1125 mlx_periodic_enquiry);
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);
1133 /* deal with possibly-missed interrupts and timed-out commands */
1136 /* reschedule another poll next second or so */
1137 callout_reset(&sc->mlx_timeout, hz, mlx_periodic, sc);
1140 /********************************************************************************
1141 * Handle the result of an ENQUIRY command instigated by periodic status polling.
1144 mlx_periodic_enquiry(struct mlx_command *mc)
1146 struct mlx_softc *sc = mc->mc_sc;
1149 MLX_IO_ASSERT_LOCKED(sc);
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));
1157 /* respond to command */
1158 switch(mc->mc_mailbox[0]) {
1160 * This is currently a bit fruitless, as we don't know how to extract the eventlog
1163 case MLX_CMD_ENQUIRY_OLD:
1165 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
1166 struct mlx_enquiry_old *meo = (struct mlx_enquiry_old *)mc->mc_data;
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;
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 */
1190 me->me_drvsize[i] = meo->me_drvsize[i];
1193 me->me_num_sys_drvs = meo->me_num_sys_drvs;
1198 * Generic controller status update. We could do more with this than just
1199 * checking the event log.
1201 case MLX_CMD_ENQUIRY:
1203 struct mlx_enquiry *me = (struct mlx_enquiry *)mc->mc_data;
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);
1213 /* mark the event log as busy */
1214 sc->mlx_flags |= MLX_EVENTLOG_BUSY;
1216 /* drain new eventlog entries */
1217 mlx_periodic_eventlog_poll(sc);
1221 case MLX_CMD_ENQSYSDRIVE:
1223 struct mlx_enq_sys_drive *mes = (struct mlx_enq_sys_drive *)mc->mc_data;
1224 struct mlx_sysdrive *dr;
1227 for (i = 0, dr = &sc->mlx_sysdrive[0];
1228 (i < MLX_MAXDRIVES) && (mes[i].sd_size != 0xffffffff);
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");
1237 case MLX_SYSD_ONLINE:
1238 device_printf(dr->ms_disk, "drive online\n");
1240 case MLX_SYSD_CRITICAL:
1241 device_printf(dr->ms_disk, "drive critical\n");
1244 /* save new state */
1245 dr->ms_state = mes[i].sd_state;
1251 device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __func__, mc->mc_mailbox[0]);
1256 free(mc->mc_data, M_DEVBUF);
1261 mlx_eventlog_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1263 struct mlx_command *mc;
1265 mc = (struct mlx_command *)arg;
1266 mlx_setup_dmamap(mc, segs, nsegments, error);
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;
1274 /* start the command */
1275 if (mlx_start(mc) != 0) {
1277 free(mc->mc_data, M_DEVBUF);
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.
1288 mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1290 struct mlx_command *mc;
1291 void *result = NULL;
1295 MLX_IO_ASSERT_LOCKED(sc);
1297 /* get ourselves a command buffer */
1299 if ((mc = mlx_alloccmd(sc)) == NULL)
1302 /* allocate the response structure */
1303 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF,
1307 /* get a command slot */
1308 if (mlx_getslot(mc))
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);
1321 if ((result != NULL) && (mc->mc_data != NULL))
1322 free(result, M_DEVBUF);
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.
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"
1347 mlx_periodic_eventlog_respond(struct mlx_command *mc)
1349 struct mlx_softc *sc = mc->mc_sc;
1350 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data;
1354 MLX_IO_ASSERT_LOCKED(sc);
1356 sc->mlx_lastevent++; /* next message... */
1357 if (mc->mc_status == 0) {
1359 /* handle event log message */
1360 switch(el->el_type) {
1362 * This is the only sort of message we understand at the moment.
1363 * The tests here are probably incomplete.
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];
1372 reason = "for unknown reason";
1374 device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1375 el->el_channel, el->el_target, reason);
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);
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, ":");
1395 device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
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;
1404 /* dispose of command and data */
1405 free(mc->mc_data, M_DEVBUF);
1408 /* is there another message to obtain? */
1409 if (sc->mlx_lastevent != sc->mlx_currevent) {
1410 mlx_periodic_eventlog_poll(sc);
1412 /* clear log-busy status */
1413 sc->mlx_flags &= ~MLX_EVENTLOG_BUSY;
1417 /********************************************************************************
1418 * Handle check/rebuild operations in progress.
1421 mlx_periodic_rebuild(struct mlx_command *mc)
1423 struct mlx_softc *sc = mc->mc_sc;
1424 struct mlx_rebuild_status *mr = (struct mlx_rebuild_status *)mc->mc_data;
1426 MLX_IO_ASSERT_LOCKED(sc);
1427 switch(mc->mc_status) {
1428 case 0: /* operation running, update stats */
1429 sc->mlx_rebuildstat = *mr;
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");
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? */
1443 case MLX_BACKGROUND_REBUILD:
1444 device_printf(sc->mlx_dev, "drive rebuild completed\n"); /* XXX print channel/target? */
1446 case MLX_BACKGROUND_SPONTANEOUS:
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");
1453 sc->mlx_background = 0;
1454 sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
1457 free(mc->mc_data, M_DEVBUF);
1461 /********************************************************************************
1462 ********************************************************************************
1464 ********************************************************************************
1465 ********************************************************************************/
1467 /********************************************************************************
1468 * It's time to perform a channel pause action for (sc), either start or stop
1472 mlx_pause_action(struct mlx_softc *sc)
1474 struct mlx_command *mc;
1475 int failsafe, i, command;
1477 MLX_IO_ASSERT_LOCKED(sc);
1479 /* What are we doing here? */
1480 if (sc->mlx_pause.mp_when == 0) {
1481 command = MLX_CMD_STARTCHANNEL;
1485 command = MLX_CMD_STOPCHANNEL;
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.
1492 failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1493 if (failsafe > 0xf) {
1495 sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
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) {
1503 /* get ourselves a command buffer */
1504 if ((mc = mlx_alloccmd(sc)) == NULL)
1506 /* get a command slot */
1507 mc->mc_flags |= MLX_CMD_PRIORITY;
1508 if (mlx_getslot(mc))
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 */
1517 /* command submitted OK */
1521 device_printf(sc->mlx_dev, "%s failed for channel %d\n",
1522 command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1530 mlx_pause_done(struct mlx_command *mc)
1532 struct mlx_softc *sc = mc->mc_sc;
1533 int command = mc->mc_mailbox[0];
1534 int channel = mc->mc_mailbox[2] & 0xf;
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));
1544 device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1549 /********************************************************************************
1550 ********************************************************************************
1552 ********************************************************************************
1553 ********************************************************************************/
1556 mlx_enquire_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1558 struct mlx_softc *sc;
1559 struct mlx_command *mc;
1561 mc = (struct mlx_command *)arg;
1565 mlx_setup_dmamap(mc, segs, nsegments, error);
1567 /* build an enquiry command */
1569 mlx_make_type2(mc, mc->mc_command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1571 /* do we want a completion callback? */
1572 if (mc->mc_complete != NULL) {
1573 if ((error = mlx_start(mc)) != 0)
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))
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));
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.
1598 mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1600 struct mlx_command *mc;
1605 MLX_IO_ASSERT_LOCKED(sc);
1607 /* get ourselves a command buffer */
1610 if ((mc = mlx_alloccmd(sc)) == NULL)
1612 /* allocate the response structure */
1613 if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1615 /* get a command slot */
1616 mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1617 if (mlx_getslot(mc))
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;
1625 if (complete != NULL) {
1626 mc->mc_complete = complete;
1627 mc->mc_private = mc;
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);
1634 /* we got a command, but nobody else will free it */
1635 if ((mc != NULL) && (mc->mc_complete == NULL))
1637 /* we got an error, and we allocated a result */
1638 if ((error != 0) && (result != NULL)) {
1639 free(result, M_DEVBUF);
1646 /********************************************************************************
1647 * Perform a Flush command on the nominated controller.
1649 * May be called with interrupts enabled or disabled; will not return until
1650 * the flush operation completes or fails.
1653 mlx_flush(struct mlx_softc *sc)
1655 struct mlx_command *mc;
1659 MLX_IO_ASSERT_LOCKED(sc);
1661 /* get ourselves a command buffer */
1663 if ((mc = mlx_alloccmd(sc)) == NULL)
1665 /* get a command slot */
1666 if (mlx_getslot(mc))
1669 /* build a flush command */
1670 mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1672 /* can't assume that interrupts are going to work here, so play it safe */
1673 if (mlx_poll_command(mc))
1676 /* command completed OK? */
1677 if (mc->mc_status != 0) {
1678 device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1682 error = 0; /* success */
1689 /********************************************************************************
1690 * Start a background consistency check on (drive).
1692 * May be called with interrupts enabled or disabled; will return as soon as the
1693 * operation has started or been refused.
1696 mlx_check(struct mlx_softc *sc, int drive)
1698 struct mlx_command *mc;
1702 MLX_IO_ASSERT_LOCKED(sc);
1704 /* get ourselves a command buffer */
1706 if ((mc = mlx_alloccmd(sc)) == NULL)
1708 /* get a command slot */
1709 if (mlx_getslot(mc))
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);
1715 /* start the command and wait for it to be returned */
1716 if (mlx_wait_command(mc))
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));
1723 device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started");
1725 error = mc->mc_status;
1733 /********************************************************************************
1734 * Start a background rebuild of the physical drive at (channel),(target).
1736 * May be called with interrupts enabled or disabled; will return as soon as the
1737 * operation has started or been refused.
1740 mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1742 struct mlx_command *mc;
1746 MLX_IO_ASSERT_LOCKED(sc);
1748 /* get ourselves a command buffer */
1750 if ((mc = mlx_alloccmd(sc)) == NULL)
1752 /* get a command slot */
1753 if (mlx_getslot(mc))
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);
1759 /* start the command and wait for it to be returned */
1760 if (mlx_wait_command(mc))
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));
1767 device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target);
1769 error = mc->mc_status;
1777 /********************************************************************************
1778 * Run the command (mc) and return when it completes.
1780 * Interrupts need to be enabled; returns nonzero on error.
1783 mlx_wait_command(struct mlx_command *mc)
1785 struct mlx_softc *sc = mc->mc_sc;
1789 MLX_IO_ASSERT_LOCKED(sc);
1791 mc->mc_complete = NULL;
1792 mc->mc_private = mc; /* wake us when you're done */
1793 if ((error = mlx_start(mc)) != 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);
1802 if (mc->mc_status != 0) {
1803 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1810 /********************************************************************************
1811 * Start the command (mc) and busy-wait for it to complete.
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.
1818 mlx_poll_command(struct mlx_command *mc)
1820 struct mlx_softc *sc = mc->mc_sc;
1824 MLX_IO_ASSERT_LOCKED(sc);
1826 mc->mc_complete = NULL;
1827 mc->mc_private = NULL; /* we will poll for it */
1828 if ((error = mlx_start(mc)) != 0)
1833 /* poll for completion */
1834 mlx_done(mc->mc_sc, 1);
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);
1841 device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1846 mlx_startio_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1848 struct mlx_command *mc;
1849 struct mlxd_softc *mlxd;
1850 struct mlx_softc *sc;
1856 mc = (struct mlx_command *)arg;
1857 mlx_setup_dmamap(mc, segs, nsegments, error);
1860 bp = mc->mc_private;
1862 if (bp->bio_cmd == BIO_READ) {
1863 mc->mc_flags |= MLX_CMD_DATAIN;
1864 cmd = MLX_CMD_READSG;
1866 mc->mc_flags |= MLX_CMD_DATAOUT;
1867 cmd = MLX_CMD_WRITESG;
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);
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);
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.
1885 if (sc->mlx_iftype == MLX_IFTYPE_2) {
1886 mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_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 */
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 */
1903 /* try to give command to controller */
1904 if (mlx_start(mc) != 0) {
1905 /* fail the command */
1906 mc->mc_status = MLX_STATUS_WEDGED;
1910 sc->mlx_state &= ~MLX_STATE_QFROZEN;
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.
1918 mlx_startio(struct mlx_softc *sc)
1920 struct mlx_command *mc;
1924 MLX_IO_ASSERT_LOCKED(sc);
1926 /* spin until something prevents us from doing any work */
1928 if (sc->mlx_state & MLX_STATE_QFROZEN)
1931 /* see if there's work to be done */
1932 if ((bp = bioq_first(&sc->mlx_bioq)) == NULL)
1935 if ((mc = mlx_alloccmd(sc)) == NULL)
1937 /* get a slot for the command */
1938 if (mlx_getslot(mc) != 0) {
1942 /* get the buf containing our work */
1943 bioq_remove(&sc->mlx_bioq, bp);
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;
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;
1962 /********************************************************************************
1963 * Handle completion of an I/O command.
1966 mlx_completeio(struct mlx_command *mc)
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;
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;
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;
1984 default: /* other I/O error */
1985 device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
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, " ");
1999 mlx_user_cb(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
2001 struct mlx_usercommand *mu;
2002 struct mlx_command *mc;
2003 struct mlx_dcdb *dcdb;
2005 mc = (struct mlx_command *)arg;
2009 mlx_setup_dmamap(mc, segs, nsegments, error);
2011 mu = (struct mlx_usercommand *)mc->mc_private;
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.
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);
2027 * If there's a data buffer, fix up the command's buffer pointer.
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;
2035 debug(0, "command fixup");
2037 /* submit the command and wait */
2038 if (mlx_wait_command(mc) != 0)
2043 /********************************************************************************
2044 * Take a command from user-space and try to run it.
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.
2051 mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
2053 struct mlx_command *mc;
2063 /* get ourselves a command and copy in from user space */
2065 if ((mc = mlx_alloccmd(sc)) == NULL) {
2069 bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
2070 debug(0, "got command buffer");
2073 * if we need a buffer for data transfer, allocate one and copy in its
2076 if (mu->mu_datasize > 0) {
2077 if (mu->mu_datasize > MLX_MAXPHYS) {
2082 if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) ||
2083 (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize))) {
2088 debug(0, "got kernel buffer");
2091 /* get a command slot */
2092 if (mlx_getslot(mc))
2094 debug(0, "got a slot");
2096 if (mu->mu_datasize > 0) {
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)))) {
2106 /* map the command so the controller can see it */
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);
2115 /* copy out status and data */
2116 mu->mu_status = mc->mc_status;
2117 if (mu->mu_datasize > 0) {
2119 error = copyout(kbuf, mu->mu_buf, mu->mu_datasize);
2127 free(kbuf, M_DEVBUF);
2131 /********************************************************************************
2132 ********************************************************************************
2133 Command I/O to Controller
2134 ********************************************************************************
2135 ********************************************************************************/
2137 /********************************************************************************
2138 * Find a free command slot for (mc).
2140 * Don't hand out a slot to a normal-priority command unless there are at least
2141 * 4 slots free for priority commands.
2144 mlx_getslot(struct mlx_command *mc)
2146 struct mlx_softc *sc = mc->mc_sc;
2151 MLX_IO_ASSERT_LOCKED(sc);
2154 * Enforce slot-usage limit, if we have the required information.
2156 if (sc->mlx_enq2 != NULL) {
2157 limit = sc->mlx_enq2->me_max_commands;
2161 if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4))
2165 * Allocate an outstanding command slot
2167 * XXX linear search is slow
2169 for (slot = 0; slot < limit; slot++) {
2170 debug(2, "try slot %d", slot);
2171 if (sc->mlx_busycmd[slot] == NULL)
2175 sc->mlx_busycmd[slot] = mc;
2183 debug(2, "got slot %d", slot);
2188 /********************************************************************************
2189 * Map/unmap (mc)'s data in the controller's addressable space.
2192 mlx_setup_dmamap(struct mlx_command *mc, bus_dma_segment_t *segs, int nsegments,
2195 struct mlx_softc *sc = mc->mc_sc;
2196 struct mlx_sgentry *sg;
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);
2206 /* get base address of s/g table */
2207 sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
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;
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;
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);
2231 mlx_unmapcmd(struct mlx_command *mc)
2233 struct mlx_softc *sc = mc->mc_sc;
2237 /* if the command involved data at all */
2238 if (mc->mc_data != NULL) {
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);
2245 bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
2249 /********************************************************************************
2250 * Try to deliver (mc) to the controller.
2252 * Can be called at any interrupt level, with or without interrupts enabled.
2255 mlx_start(struct mlx_command *mc)
2257 struct mlx_softc *sc = mc->mc_sc;
2262 /* save the slot number as ident so we can handle this command when complete */
2263 mc->mc_mailbox[0x1] = mc->mc_slot;
2265 /* mark the command as currently being processed */
2266 mc->mc_status = MLX_STATUS_BUSY;
2268 /* set a default 60-second timeout XXX tunable? XXX not currently used */
2269 mc->mc_timeout = time_second + 60;
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);
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.
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;
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.
2297 * Returns nonzero if one or more commands were completed.
2300 mlx_done(struct mlx_softc *sc, int startio)
2302 struct mlx_command *mc;
2308 MLX_IO_ASSERT_LOCKED(sc);
2312 /* loop collecting completed commands */
2314 /* poll for a completed command's identifier and status */
2315 if (sc->mlx_findcomplete(sc, &slot, &status)) {
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 */
2322 /* free slot for reuse */
2323 sc->mlx_busycmd[slot] = NULL;
2326 device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
2329 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
2336 /* if we've completed any commands, try posting some more */
2337 if (result && startio)
2340 /* handle completion and timeouts */
2346 /********************************************************************************
2347 * Perform post-completion processing for commands on (sc).
2350 mlx_complete(struct mlx_softc *sc)
2352 struct mlx_command *mc, *nc;
2355 MLX_IO_ASSERT_LOCKED(sc);
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);
2362 /* Command has been completed in some fashion */
2363 if (mc->mc_status != MLX_STATUS_BUSY) {
2365 /* unmap the command's data buffer */
2368 * Does the command have a completion handler?
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);
2376 * Is there a sleeper waiting on this command?
2378 } else if (mc->mc_private != NULL) { /* sleeping caller wants to know about it */
2380 /* remove from list and wake up sleeper */
2381 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2382 wakeup_one(mc->mc_private);
2385 * Leave the command for a caller that's polling for it.
2394 /********************************************************************************
2395 ********************************************************************************
2396 Command Buffer Management
2397 ********************************************************************************
2398 ********************************************************************************/
2400 /********************************************************************************
2401 * Get a new command buffer.
2403 * This may return NULL in low-memory cases.
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.
2408 * If possible, we recycle a command buffer that's been used before.
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
2414 static struct mlx_command *
2415 mlx_alloccmd(struct mlx_softc *sc)
2417 struct mlx_command *mc;
2422 MLX_IO_ASSERT_LOCKED(sc);
2423 if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2424 TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2426 /* allocate a new command buffer? */
2428 mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT | M_ZERO);
2431 error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2441 /********************************************************************************
2442 * Release a command buffer for recycling.
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.
2448 mlx_releasecmd(struct mlx_command *mc)
2453 MLX_IO_ASSERT_LOCKED(mc->mc_sc);
2454 TAILQ_INSERT_HEAD(&mc->mc_sc->mlx_freecmds, mc, mc_link);
2457 /********************************************************************************
2458 * Permanently discard a command buffer.
2461 mlx_freecmd(struct mlx_command *mc)
2463 struct mlx_softc *sc = mc->mc_sc;
2466 bus_dmamap_destroy(sc->mlx_buffer_dmat, mc->mc_dmamap);
2471 /********************************************************************************
2472 ********************************************************************************
2473 Type 3 interface accessor methods
2474 ********************************************************************************
2475 ********************************************************************************/
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).
2482 mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2487 MLX_IO_ASSERT_LOCKED(sc);
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]);
2496 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_FULL);
2502 /********************************************************************************
2503 * See if a command has been completed, if so acknowledge its completion
2504 * and recover the slot number and status code.
2507 mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2511 MLX_IO_ASSERT_LOCKED(sc);
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 */
2518 /* acknowledge completion */
2519 MLX_V3_PUT_ODBR(sc, MLX_V3_ODB_SAVAIL);
2520 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2526 /********************************************************************************
2527 * Enable/disable interrupts as requested. (No acknowledge required)
2530 mlx_v3_intaction(struct mlx_softc *sc, int action)
2533 MLX_IO_ASSERT_LOCKED(sc);
2536 case MLX_INTACTION_DISABLE:
2537 MLX_V3_PUT_IER(sc, 0);
2538 sc->mlx_state &= ~MLX_STATE_INTEN;
2540 case MLX_INTACTION_ENABLE:
2541 MLX_V3_PUT_IER(sc, 1);
2542 sc->mlx_state |= MLX_STATE_INTEN;
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.
2553 mlx_v3_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2,
2560 /* first time around, clear any hardware completion status */
2562 MLX_V3_PUT_IDBR(sc, MLX_V3_IDB_SACK);
2566 /* init in progress? */
2567 if (!(MLX_V3_GET_IDBR(sc) & MLX_V3_IDB_INIT_BUSY))
2570 /* test error value */
2571 fwerror = MLX_V3_GET_FWERROR(sc);
2572 if (!(fwerror & MLX_V3_FWERROR_PEND))
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);
2581 MLX_V3_PUT_FWERROR(sc, 0);
2586 /********************************************************************************
2587 ********************************************************************************
2588 Type 4 interface accessor methods
2589 ********************************************************************************
2590 ********************************************************************************/
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).
2597 mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2602 MLX_IO_ASSERT_LOCKED(sc);
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]);
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);
2615 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_HWMBOX_CMD);
2621 /********************************************************************************
2622 * See if a command has been completed, if so acknowledge its completion
2623 * and recover the slot number and status code.
2626 mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2630 MLX_IO_ASSERT_LOCKED(sc);
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 */
2637 /* acknowledge completion */
2638 MLX_V4_PUT_ODBR(sc, MLX_V4_ODB_HWMBOX_ACK);
2639 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2645 /********************************************************************************
2646 * Enable/disable interrupts as requested.
2649 mlx_v4_intaction(struct mlx_softc *sc, int action)
2652 MLX_IO_ASSERT_LOCKED(sc);
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;
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;
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.
2672 mlx_v4_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2,
2679 /* first time around, clear any hardware completion status */
2681 MLX_V4_PUT_IDBR(sc, MLX_V4_IDB_SACK);
2685 /* init in progress? */
2686 if (!(MLX_V4_GET_IDBR(sc) & MLX_V4_IDB_INIT_BUSY))
2689 /* test error value */
2690 fwerror = MLX_V4_GET_FWERROR(sc);
2691 if (!(fwerror & MLX_V4_FWERROR_PEND))
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);
2700 MLX_V4_PUT_FWERROR(sc, 0);
2705 /********************************************************************************
2706 ********************************************************************************
2707 Type 5 interface accessor methods
2708 ********************************************************************************
2709 ********************************************************************************/
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).
2716 mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2721 MLX_IO_ASSERT_LOCKED(sc);
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]);
2730 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2736 /********************************************************************************
2737 * See if a command has been completed, if so acknowledge its completion
2738 * and recover the slot number and status code.
2741 mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2745 MLX_IO_ASSERT_LOCKED(sc);
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 */
2752 /* acknowledge completion */
2753 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);
2754 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2760 /********************************************************************************
2761 * Enable/disable interrupts as requested.
2764 mlx_v5_intaction(struct mlx_softc *sc, int action)
2767 MLX_IO_ASSERT_LOCKED(sc);
2770 case MLX_INTACTION_DISABLE:
2771 MLX_V5_PUT_IER(sc, 0xff & MLX_V5_IER_DISINT);
2772 sc->mlx_state &= ~MLX_STATE_INTEN;
2774 case MLX_INTACTION_ENABLE:
2775 MLX_V5_PUT_IER(sc, 0xff & ~MLX_V5_IER_DISINT);
2776 sc->mlx_state |= MLX_STATE_INTEN;
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.
2787 mlx_v5_fw_handshake(struct mlx_softc *sc, int *error, int *param1, int *param2,
2794 /* first time around, clear any hardware completion status */
2796 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2800 /* init in progress? */
2801 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_INIT_DONE)
2804 /* test for error value */
2805 fwerror = MLX_V5_GET_FWERROR(sc);
2806 if (!(fwerror & MLX_V5_FWERROR_PEND))
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);
2815 MLX_V5_PUT_FWERROR(sc, 0xff);
2820 /********************************************************************************
2821 ********************************************************************************
2823 ********************************************************************************
2824 ********************************************************************************/
2826 /********************************************************************************
2827 * Return a status message describing (mc)
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 */
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},
2896 mlx_diagnose_command(struct mlx_command *mc)
2898 static char unkmsg[80];
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]);
2907 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2911 /*******************************************************************************
2912 * Print a string describing the controller (sc)
2918 } mlx_controller_names[] = {
2933 mlx_describe_controller(struct mlx_softc *sc)
2935 static char buf[80];
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;
2945 if (model == NULL) {
2946 sprintf(buf, " model 0x%x", sc->mlx_enq2->me_hardware_id & 0xff);
2949 device_printf(sc->mlx_dev, "DAC%s, %d channel%s, firmware %d.%02d-%c-%02d, %dMB RAM\n",
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));
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");
2998 /*******************************************************************************
2999 * Emit a string describing the firmware handshake status code, and return a flag
3000 * indicating whether the code represents a fatal error.
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.
3007 mlx_fw_message(struct mlx_softc *sc, int error, int param1, int param2)
3011 device_printf(sc->mlx_dev, "physical drive %d:%d not responding\n", param2, param1);
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;
3021 device_printf(sc->mlx_dev, "configuration checksum error\n");
3024 device_printf(sc->mlx_dev, "mirror race recovery failed\n");
3027 device_printf(sc->mlx_dev, "mirror race recovery in progress\n");
3030 device_printf(sc->mlx_dev, "physical drive %d:%d COD mismatch\n", param2, param1);
3033 device_printf(sc->mlx_dev, "logical drive installation aborted\n");
3036 device_printf(sc->mlx_dev, "mirror race on a critical system drive\n");
3039 device_printf(sc->mlx_dev, "new controller configuration found\n");
3042 device_printf(sc->mlx_dev, "FATAL MEMORY PARITY ERROR\n");
3045 device_printf(sc->mlx_dev, "unknown firmware initialisation error %02x:%02x:%02x\n", error, param1, param2);
3051 /********************************************************************************
3052 ********************************************************************************
3054 ********************************************************************************
3055 ********************************************************************************/
3057 /********************************************************************************
3058 * Find the disk whose unit number is (unit) on this controller
3060 static struct mlx_sysdrive *
3061 mlx_findunit(struct mlx_softc *sc, int unit)
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]);