1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2000, 2001 Michael Smith
5 * Copyright (c) 2000 BSDi
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 *	$FreeBSD$
30 */
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/malloc.h>
35#include <sys/kernel.h>
36#include <sys/bus.h>
37#include <sys/conf.h>
38#include <sys/ctype.h>
39#include <sys/ioccom.h>
40#include <sys/stat.h>
41
42#include <machine/bus.h>
43#include <machine/resource.h>
44#include <sys/rman.h>
45
46#include <cam/cam.h>
47#include <cam/cam_ccb.h>
48#include <cam/cam_periph.h>
49#include <cam/cam_sim.h>
50#include <cam/cam_xpt_sim.h>
51#include <cam/scsi/scsi_all.h>
52#include <cam/scsi/scsi_message.h>
53
54#include <dev/pci/pcireg.h>
55#include <dev/pci/pcivar.h>
56
57#include <dev/mly/mlyreg.h>
58#include <dev/mly/mlyio.h>
59#include <dev/mly/mlyvar.h>
60#include <dev/mly/mly_tables.h>
61
62static int	mly_probe(device_t dev);
63static int	mly_attach(device_t dev);
64static int	mly_pci_attach(struct mly_softc *sc);
65static int	mly_detach(device_t dev);
66static int	mly_shutdown(device_t dev);
67static void	mly_intr(void *arg);
68
69static int	mly_sg_map(struct mly_softc *sc);
70static void	mly_sg_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
71static int	mly_mmbox_map(struct mly_softc *sc);
72static void	mly_mmbox_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error);
73static void	mly_free(struct mly_softc *sc);
74
75static int	mly_get_controllerinfo(struct mly_softc *sc);
76static void	mly_scan_devices(struct mly_softc *sc);
77static void	mly_rescan_btl(struct mly_softc *sc, int bus, int target);
78static void	mly_complete_rescan(struct mly_command *mc);
79static int	mly_get_eventstatus(struct mly_softc *sc);
80static int	mly_enable_mmbox(struct mly_softc *sc);
81static int	mly_flush(struct mly_softc *sc);
82static int	mly_ioctl(struct mly_softc *sc, struct mly_command_ioctl *ioctl, void **data,
83			  size_t datasize, u_int8_t *status, void *sense_buffer, size_t *sense_length);
84static void	mly_check_event(struct mly_softc *sc);
85static void	mly_fetch_event(struct mly_softc *sc);
86static void	mly_complete_event(struct mly_command *mc);
87static void	mly_process_event(struct mly_softc *sc, struct mly_event *me);
88static void	mly_periodic(void *data);
89
90static int	mly_immediate_command(struct mly_command *mc);
91static int	mly_start(struct mly_command *mc);
92static void	mly_done(struct mly_softc *sc);
93static void	mly_complete(struct mly_softc *sc);
94static void	mly_complete_handler(void *context, int pending);
95
96static int	mly_alloc_command(struct mly_softc *sc, struct mly_command **mcp);
97static void	mly_release_command(struct mly_command *mc);
98static void	mly_alloc_commands_map(void *arg, bus_dma_segment_t *segs, int nseg, int error);
99static int	mly_alloc_commands(struct mly_softc *sc);
100static void	mly_release_commands(struct mly_softc *sc);
101static void	mly_map_command(struct mly_command *mc);
102static void	mly_unmap_command(struct mly_command *mc);
103
104static int	mly_cam_attach(struct mly_softc *sc);
105static void	mly_cam_detach(struct mly_softc *sc);
106static void	mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target);
107static void	mly_cam_action(struct cam_sim *sim, union ccb *ccb);
108static int	mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio);
109static void	mly_cam_poll(struct cam_sim *sim);
110static void	mly_cam_complete(struct mly_command *mc);
111static struct cam_periph *mly_find_periph(struct mly_softc *sc, int bus, int target);
112static int	mly_name_device(struct mly_softc *sc, int bus, int target);
113
114static int	mly_fwhandshake(struct mly_softc *sc);
115
116static void	mly_describe_controller(struct mly_softc *sc);
117#ifdef MLY_DEBUG
118static void	mly_printstate(struct mly_softc *sc);
119static void	mly_print_command(struct mly_command *mc);
120static void	mly_print_packet(struct mly_command *mc);
121static void	mly_panic(struct mly_softc *sc, char *reason);
122static void	mly_timeout(void *arg);
123#endif
124void		mly_print_controller(int controller);
125
126
127static d_open_t		mly_user_open;
128static d_close_t	mly_user_close;
129static d_ioctl_t	mly_user_ioctl;
130static int	mly_user_command(struct mly_softc *sc, struct mly_user_command *uc);
131static int	mly_user_health(struct mly_softc *sc, struct mly_user_health *uh);
132
133#define MLY_CMD_TIMEOUT		20
134
135static device_method_t mly_methods[] = {
136    /* Device interface */
137    DEVMETHOD(device_probe,	mly_probe),
138    DEVMETHOD(device_attach,	mly_attach),
139    DEVMETHOD(device_detach,	mly_detach),
140    DEVMETHOD(device_shutdown,	mly_shutdown),
141    { 0, 0 }
142};
143
144static driver_t mly_pci_driver = {
145	"mly",
146	mly_methods,
147	sizeof(struct mly_softc)
148};
149
150static devclass_t	mly_devclass;
151DRIVER_MODULE(mly, pci, mly_pci_driver, mly_devclass, 0, 0);
152MODULE_DEPEND(mly, pci, 1, 1, 1);
153MODULE_DEPEND(mly, cam, 1, 1, 1);
154
155static struct cdevsw mly_cdevsw = {
156	.d_version =	D_VERSION,
157	.d_open =	mly_user_open,
158	.d_close =	mly_user_close,
159	.d_ioctl =	mly_user_ioctl,
160	.d_name =	"mly",
161};
162
163/********************************************************************************
164 ********************************************************************************
165                                                                 Device Interface
166 ********************************************************************************
167 ********************************************************************************/
168
169static struct mly_ident
170{
171    u_int16_t		vendor;
172    u_int16_t		device;
173    u_int16_t		subvendor;
174    u_int16_t		subdevice;
175    int			hwif;
176    char		*desc;
177} mly_identifiers[] = {
178    {0x1069, 0xba56, 0x1069, 0x0040, MLY_HWIF_STRONGARM, "Mylex eXtremeRAID 2000"},
179    {0x1069, 0xba56, 0x1069, 0x0030, MLY_HWIF_STRONGARM, "Mylex eXtremeRAID 3000"},
180    {0x1069, 0x0050, 0x1069, 0x0050, MLY_HWIF_I960RX,    "Mylex AcceleRAID 352"},
181    {0x1069, 0x0050, 0x1069, 0x0052, MLY_HWIF_I960RX,    "Mylex AcceleRAID 170"},
182    {0x1069, 0x0050, 0x1069, 0x0054, MLY_HWIF_I960RX,    "Mylex AcceleRAID 160"},
183    {0, 0, 0, 0, 0, 0}
184};
185
186/********************************************************************************
187 * Compare the provided PCI device with the list we support.
188 */
189static int
190mly_probe(device_t dev)
191{
192    struct mly_ident	*m;
193
194    debug_called(1);
195
196    for (m = mly_identifiers; m->vendor != 0; m++) {
197	if ((m->vendor == pci_get_vendor(dev)) &&
198	    (m->device == pci_get_device(dev)) &&
199	    ((m->subvendor == 0) || ((m->subvendor == pci_get_subvendor(dev)) &&
200				     (m->subdevice == pci_get_subdevice(dev))))) {
201
202	    device_set_desc(dev, m->desc);
203	    return(BUS_PROBE_DEFAULT);	/* allow room to be overridden */
204	}
205    }
206    return(ENXIO);
207}
208
209/********************************************************************************
210 * Initialise the controller and softc
211 */
212static int
213mly_attach(device_t dev)
214{
215    struct mly_softc	*sc = device_get_softc(dev);
216    int			error;
217
218    debug_called(1);
219
220    sc->mly_dev = dev;
221    mtx_init(&sc->mly_lock, "mly", NULL, MTX_DEF);
222    callout_init_mtx(&sc->mly_periodic, &sc->mly_lock, 0);
223
224#ifdef MLY_DEBUG
225    callout_init_mtx(&sc->mly_timeout, &sc->mly_lock, 0);
226    if (device_get_unit(sc->mly_dev) == 0)
227	mly_softc0 = sc;
228#endif
229
230    /*
231     * Do PCI-specific initialisation.
232     */
233    if ((error = mly_pci_attach(sc)) != 0)
234	goto out;
235
236    /*
237     * Initialise per-controller queues.
238     */
239    mly_initq_free(sc);
240    mly_initq_busy(sc);
241    mly_initq_complete(sc);
242
243    /*
244     * Initialise command-completion task.
245     */
246    TASK_INIT(&sc->mly_task_complete, 0, mly_complete_handler, sc);
247
248    /* disable interrupts before we start talking to the controller */
249    MLY_MASK_INTERRUPTS(sc);
250
251    /*
252     * Wait for the controller to come ready, handshake with the firmware if required.
253     * This is typically only necessary on platforms where the controller BIOS does not
254     * run.
255     */
256    if ((error = mly_fwhandshake(sc)))
257	goto out;
258
259    /*
260     * Allocate initial command buffers.
261     */
262    if ((error = mly_alloc_commands(sc)))
263	goto out;
264
265    /*
266     * Obtain controller feature information
267     */
268    MLY_LOCK(sc);
269    error = mly_get_controllerinfo(sc);
270    MLY_UNLOCK(sc);
271    if (error)
272	goto out;
273
274    /*
275     * Reallocate command buffers now we know how many we want.
276     */
277    mly_release_commands(sc);
278    if ((error = mly_alloc_commands(sc)))
279	goto out;
280
281    /*
282     * Get the current event counter for health purposes, populate the initial
283     * health status buffer.
284     */
285    MLY_LOCK(sc);
286    error = mly_get_eventstatus(sc);
287
288    /*
289     * Enable memory-mailbox mode.
290     */
291    if (error == 0)
292	error = mly_enable_mmbox(sc);
293    MLY_UNLOCK(sc);
294    if (error)
295	goto out;
296
297    /*
298     * Attach to CAM.
299     */
300    if ((error = mly_cam_attach(sc)))
301	goto out;
302
303    /*
304     * Print a little information about the controller
305     */
306    mly_describe_controller(sc);
307
308    /*
309     * Mark all attached devices for rescan.
310     */
311    MLY_LOCK(sc);
312    mly_scan_devices(sc);
313
314    /*
315     * Instigate the first status poll immediately.  Rescan completions won't
316     * happen until interrupts are enabled, which should still be before
317     * the SCSI subsystem gets to us, courtesy of the "SCSI settling delay".
318     */
319    mly_periodic((void *)sc);
320    MLY_UNLOCK(sc);
321
322    /*
323     * Create the control device.
324     */
325    sc->mly_dev_t = make_dev(&mly_cdevsw, 0, UID_ROOT, GID_OPERATOR,
326			     S_IRUSR | S_IWUSR, "mly%d", device_get_unit(sc->mly_dev));
327    sc->mly_dev_t->si_drv1 = sc;
328
329    /* enable interrupts now */
330    MLY_UNMASK_INTERRUPTS(sc);
331
332#ifdef MLY_DEBUG
333    callout_reset(&sc->mly_timeout, MLY_CMD_TIMEOUT * hz, mly_timeout, sc);
334#endif
335
336 out:
337    if (error != 0)
338	mly_free(sc);
339    return(error);
340}
341
342/********************************************************************************
343 * Perform PCI-specific initialisation.
344 */
345static int
346mly_pci_attach(struct mly_softc *sc)
347{
348    int			i, error;
349
350    debug_called(1);
351
352    /* assume failure is 'not configured' */
353    error = ENXIO;
354
355    /*
356     * Verify that the adapter is correctly set up in PCI space.
357     */
358    pci_enable_busmaster(sc->mly_dev);
359
360    /*
361     * Allocate the PCI register window.
362     */
363    sc->mly_regs_rid = PCIR_BAR(0);	/* first base address register */
364    if ((sc->mly_regs_resource = bus_alloc_resource_any(sc->mly_dev,
365	    SYS_RES_MEMORY, &sc->mly_regs_rid, RF_ACTIVE)) == NULL) {
366	mly_printf(sc, "can't allocate register window\n");
367	goto fail;
368    }
369
370    /*
371     * Allocate and connect our interrupt.
372     */
373    sc->mly_irq_rid = 0;
374    if ((sc->mly_irq = bus_alloc_resource_any(sc->mly_dev, SYS_RES_IRQ,
375		    &sc->mly_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
376	mly_printf(sc, "can't allocate interrupt\n");
377	goto fail;
378    }
379    if (bus_setup_intr(sc->mly_dev, sc->mly_irq, INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE, NULL, mly_intr, sc, &sc->mly_intr)) {
380	mly_printf(sc, "can't set up interrupt\n");
381	goto fail;
382    }
383
384    /* assume failure is 'out of memory' */
385    error = ENOMEM;
386
387    /*
388     * Allocate the parent bus DMA tag appropriate for our PCI interface.
389     *
390     * Note that all of these controllers are 64-bit capable.
391     */
392    if (bus_dma_tag_create(bus_get_dma_tag(sc->mly_dev),/* PCI parent */
393			   1, 0, 			/* alignment, boundary */
394			   BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
395			   BUS_SPACE_MAXADDR, 		/* highaddr */
396			   NULL, NULL, 			/* filter, filterarg */
397			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsize */
398			   BUS_SPACE_UNRESTRICTED,	/* nsegments */
399			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
400			   BUS_DMA_ALLOCNOW,		/* flags */
401			   NULL,			/* lockfunc */
402			   NULL,			/* lockarg */
403			   &sc->mly_parent_dmat)) {
404	mly_printf(sc, "can't allocate parent DMA tag\n");
405	goto fail;
406    }
407
408    /*
409     * Create DMA tag for mapping buffers into controller-addressable space.
410     */
411    if (bus_dma_tag_create(sc->mly_parent_dmat, 	/* parent */
412			   1, 0, 			/* alignment, boundary */
413			   BUS_SPACE_MAXADDR,		/* lowaddr */
414			   BUS_SPACE_MAXADDR, 		/* highaddr */
415			   NULL, NULL, 			/* filter, filterarg */
416			   DFLTPHYS,			/* maxsize */
417			   MLY_MAX_SGENTRIES,		/* nsegments */
418			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
419			   0,				/* flags */
420			   busdma_lock_mutex,		/* lockfunc */
421			   &sc->mly_lock,		/* lockarg */
422			   &sc->mly_buffer_dmat)) {
423	mly_printf(sc, "can't allocate buffer DMA tag\n");
424	goto fail;
425    }
426
427    /*
428     * Initialise the DMA tag for command packets.
429     */
430    if (bus_dma_tag_create(sc->mly_parent_dmat,		/* parent */
431			   1, 0, 			/* alignment, boundary */
432			   BUS_SPACE_MAXADDR,		/* lowaddr */
433			   BUS_SPACE_MAXADDR, 		/* highaddr */
434			   NULL, NULL, 			/* filter, filterarg */
435			   sizeof(union mly_command_packet) * MLY_MAX_COMMANDS, 1,	/* maxsize, nsegments */
436			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
437			   BUS_DMA_ALLOCNOW,		/* flags */
438			   NULL, NULL,			/* lockfunc, lockarg */
439			   &sc->mly_packet_dmat)) {
440	mly_printf(sc, "can't allocate command packet DMA tag\n");
441	goto fail;
442    }
443
444    /*
445     * Detect the hardware interface version
446     */
447    for (i = 0; mly_identifiers[i].vendor != 0; i++) {
448	if ((mly_identifiers[i].vendor == pci_get_vendor(sc->mly_dev)) &&
449	    (mly_identifiers[i].device == pci_get_device(sc->mly_dev))) {
450	    sc->mly_hwif = mly_identifiers[i].hwif;
451	    switch(sc->mly_hwif) {
452	    case MLY_HWIF_I960RX:
453		debug(1, "set hardware up for i960RX");
454		sc->mly_doorbell_true = 0x00;
455		sc->mly_command_mailbox =  MLY_I960RX_COMMAND_MAILBOX;
456		sc->mly_status_mailbox =   MLY_I960RX_STATUS_MAILBOX;
457		sc->mly_idbr =             MLY_I960RX_IDBR;
458		sc->mly_odbr =             MLY_I960RX_ODBR;
459		sc->mly_error_status =     MLY_I960RX_ERROR_STATUS;
460		sc->mly_interrupt_status = MLY_I960RX_INTERRUPT_STATUS;
461		sc->mly_interrupt_mask =   MLY_I960RX_INTERRUPT_MASK;
462		break;
463	    case MLY_HWIF_STRONGARM:
464		debug(1, "set hardware up for StrongARM");
465		sc->mly_doorbell_true = 0xff;		/* doorbell 'true' is 0 */
466		sc->mly_command_mailbox =  MLY_STRONGARM_COMMAND_MAILBOX;
467		sc->mly_status_mailbox =   MLY_STRONGARM_STATUS_MAILBOX;
468		sc->mly_idbr =             MLY_STRONGARM_IDBR;
469		sc->mly_odbr =             MLY_STRONGARM_ODBR;
470		sc->mly_error_status =     MLY_STRONGARM_ERROR_STATUS;
471		sc->mly_interrupt_status = MLY_STRONGARM_INTERRUPT_STATUS;
472		sc->mly_interrupt_mask =   MLY_STRONGARM_INTERRUPT_MASK;
473		break;
474	    }
475	    break;
476	}
477    }
478
479    /*
480     * Create the scatter/gather mappings.
481     */
482    if ((error = mly_sg_map(sc)))
483	goto fail;
484
485    /*
486     * Allocate and map the memory mailbox
487     */
488    if ((error = mly_mmbox_map(sc)))
489	goto fail;
490
491    error = 0;
492
493fail:
494    return(error);
495}
496
497/********************************************************************************
498 * Shut the controller down and detach all our resources.
499 */
500static int
501mly_detach(device_t dev)
502{
503    int			error;
504
505    if ((error = mly_shutdown(dev)) != 0)
506	return(error);
507
508    mly_free(device_get_softc(dev));
509    return(0);
510}
511
512/********************************************************************************
513 * Bring the controller to a state where it can be safely left alone.
514 *
515 * Note that it should not be necessary to wait for any outstanding commands,
516 * as they should be completed prior to calling here.
517 *
518 * XXX this applies for I/O, but not status polls; we should beware of
519 *     the case where a status command is running while we detach.
520 */
521static int
522mly_shutdown(device_t dev)
523{
524    struct mly_softc	*sc = device_get_softc(dev);
525
526    debug_called(1);
527
528    MLY_LOCK(sc);
529    if (sc->mly_state & MLY_STATE_OPEN) {
530	MLY_UNLOCK(sc);
531	return(EBUSY);
532    }
533
534    /* kill the periodic event */
535    callout_stop(&sc->mly_periodic);
536#ifdef MLY_DEBUG
537    callout_stop(&sc->mly_timeout);
538#endif
539
540    /* flush controller */
541    mly_printf(sc, "flushing cache...");
542    printf("%s\n", mly_flush(sc) ? "failed" : "done");
543
544    MLY_MASK_INTERRUPTS(sc);
545    MLY_UNLOCK(sc);
546
547    return(0);
548}
549
550/*******************************************************************************
551 * Take an interrupt, or be poked by other code to look for interrupt-worthy
552 * status.
553 */
554static void
555mly_intr(void *arg)
556{
557    struct mly_softc	*sc = (struct mly_softc *)arg;
558
559    debug_called(2);
560
561    MLY_LOCK(sc);
562    mly_done(sc);
563    MLY_UNLOCK(sc);
564};
565
566/********************************************************************************
567 ********************************************************************************
568                                                Bus-dependant Resource Management
569 ********************************************************************************
570 ********************************************************************************/
571
572/********************************************************************************
573 * Allocate memory for the scatter/gather tables
574 */
575static int
576mly_sg_map(struct mly_softc *sc)
577{
578    size_t	segsize;
579
580    debug_called(1);
581
582    /*
583     * Create a single tag describing a region large enough to hold all of
584     * the s/g lists we will need.
585     */
586    segsize = sizeof(struct mly_sg_entry) * MLY_MAX_COMMANDS *MLY_MAX_SGENTRIES;
587    if (bus_dma_tag_create(sc->mly_parent_dmat,		/* parent */
588			   1, 0, 			/* alignment,boundary */
589			   BUS_SPACE_MAXADDR,		/* lowaddr */
590			   BUS_SPACE_MAXADDR, 		/* highaddr */
591			   NULL, NULL, 			/* filter, filterarg */
592			   segsize, 1,			/* maxsize, nsegments */
593			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
594			   BUS_DMA_ALLOCNOW,		/* flags */
595			   NULL, NULL,			/* lockfunc, lockarg */
596			   &sc->mly_sg_dmat)) {
597	mly_printf(sc, "can't allocate scatter/gather DMA tag\n");
598	return(ENOMEM);
599    }
600
601    /*
602     * Allocate enough s/g maps for all commands and permanently map them into
603     * controller-visible space.
604     *
605     * XXX this assumes we can get enough space for all the s/g maps in one
606     * contiguous slab.
607     */
608    if (bus_dmamem_alloc(sc->mly_sg_dmat, (void **)&sc->mly_sg_table,
609			 BUS_DMA_NOWAIT, &sc->mly_sg_dmamap)) {
610	mly_printf(sc, "can't allocate s/g table\n");
611	return(ENOMEM);
612    }
613    if (bus_dmamap_load(sc->mly_sg_dmat, sc->mly_sg_dmamap, sc->mly_sg_table,
614			segsize, mly_sg_map_helper, sc, BUS_DMA_NOWAIT) != 0)
615	return (ENOMEM);
616    return(0);
617}
618
619/********************************************************************************
620 * Save the physical address of the base of the s/g table.
621 */
622static void
623mly_sg_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
624{
625    struct mly_softc	*sc = (struct mly_softc *)arg;
626
627    debug_called(1);
628
629    /* save base of s/g table's address in bus space */
630    sc->mly_sg_busaddr = segs->ds_addr;
631}
632
633/********************************************************************************
634 * Allocate memory for the memory-mailbox interface
635 */
636static int
637mly_mmbox_map(struct mly_softc *sc)
638{
639
640    /*
641     * Create a DMA tag for a single contiguous region large enough for the
642     * memory mailbox structure.
643     */
644    if (bus_dma_tag_create(sc->mly_parent_dmat,		/* parent */
645			   1, 0, 			/* alignment,boundary */
646			   BUS_SPACE_MAXADDR,		/* lowaddr */
647			   BUS_SPACE_MAXADDR, 		/* highaddr */
648			   NULL, NULL, 			/* filter, filterarg */
649			   sizeof(struct mly_mmbox), 1,	/* maxsize, nsegments */
650			   BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
651			   BUS_DMA_ALLOCNOW,		/* flags */
652			   NULL, NULL,			/* lockfunc, lockarg */
653			   &sc->mly_mmbox_dmat)) {
654	mly_printf(sc, "can't allocate memory mailbox DMA tag\n");
655	return(ENOMEM);
656    }
657
658    /*
659     * Allocate the buffer
660     */
661    if (bus_dmamem_alloc(sc->mly_mmbox_dmat, (void **)&sc->mly_mmbox, BUS_DMA_NOWAIT, &sc->mly_mmbox_dmamap)) {
662	mly_printf(sc, "can't allocate memory mailbox\n");
663	return(ENOMEM);
664    }
665    if (bus_dmamap_load(sc->mly_mmbox_dmat, sc->mly_mmbox_dmamap, sc->mly_mmbox,
666			sizeof(struct mly_mmbox), mly_mmbox_map_helper, sc,
667			BUS_DMA_NOWAIT) != 0)
668	return (ENOMEM);
669    bzero(sc->mly_mmbox, sizeof(*sc->mly_mmbox));
670    return(0);
671
672}
673
674/********************************************************************************
675 * Save the physical address of the memory mailbox
676 */
677static void
678mly_mmbox_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
679{
680    struct mly_softc	*sc = (struct mly_softc *)arg;
681
682    debug_called(1);
683
684    sc->mly_mmbox_busaddr = segs->ds_addr;
685}
686
687/********************************************************************************
688 * Free all of the resources associated with (sc)
689 *
690 * Should not be called if the controller is active.
691 */
692static void
693mly_free(struct mly_softc *sc)
694{
695
696    debug_called(1);
697
698    /* Remove the management device */
699    destroy_dev(sc->mly_dev_t);
700
701    if (sc->mly_intr)
702	bus_teardown_intr(sc->mly_dev, sc->mly_irq, sc->mly_intr);
703    callout_drain(&sc->mly_periodic);
704#ifdef MLY_DEBUG
705    callout_drain(&sc->mly_timeout);
706#endif
707
708    /* detach from CAM */
709    mly_cam_detach(sc);
710
711    /* release command memory */
712    mly_release_commands(sc);
713
714    /* throw away the controllerinfo structure */
715    if (sc->mly_controllerinfo != NULL)
716	free(sc->mly_controllerinfo, M_DEVBUF);
717
718    /* throw away the controllerparam structure */
719    if (sc->mly_controllerparam != NULL)
720	free(sc->mly_controllerparam, M_DEVBUF);
721
722    /* destroy data-transfer DMA tag */
723    if (sc->mly_buffer_dmat)
724	bus_dma_tag_destroy(sc->mly_buffer_dmat);
725
726    /* free and destroy DMA memory and tag for s/g lists */
727    if (sc->mly_sg_table) {
728	bus_dmamap_unload(sc->mly_sg_dmat, sc->mly_sg_dmamap);
729	bus_dmamem_free(sc->mly_sg_dmat, sc->mly_sg_table, sc->mly_sg_dmamap);
730    }
731    if (sc->mly_sg_dmat)
732	bus_dma_tag_destroy(sc->mly_sg_dmat);
733
734    /* free and destroy DMA memory and tag for memory mailbox */
735    if (sc->mly_mmbox) {
736	bus_dmamap_unload(sc->mly_mmbox_dmat, sc->mly_mmbox_dmamap);
737	bus_dmamem_free(sc->mly_mmbox_dmat, sc->mly_mmbox, sc->mly_mmbox_dmamap);
738    }
739    if (sc->mly_mmbox_dmat)
740	bus_dma_tag_destroy(sc->mly_mmbox_dmat);
741
742    /* disconnect the interrupt handler */
743    if (sc->mly_irq != NULL)
744	bus_release_resource(sc->mly_dev, SYS_RES_IRQ, sc->mly_irq_rid, sc->mly_irq);
745
746    /* destroy the parent DMA tag */
747    if (sc->mly_parent_dmat)
748	bus_dma_tag_destroy(sc->mly_parent_dmat);
749
750    /* release the register window mapping */
751    if (sc->mly_regs_resource != NULL)
752	bus_release_resource(sc->mly_dev, SYS_RES_MEMORY, sc->mly_regs_rid, sc->mly_regs_resource);
753
754    mtx_destroy(&sc->mly_lock);
755}
756
757/********************************************************************************
758 ********************************************************************************
759                                                                 Command Wrappers
760 ********************************************************************************
761 ********************************************************************************/
762
763/********************************************************************************
764 * Fill in the mly_controllerinfo and mly_controllerparam fields in the softc.
765 */
766static int
767mly_get_controllerinfo(struct mly_softc *sc)
768{
769    struct mly_command_ioctl	mci;
770    u_int8_t			status;
771    int				error;
772
773    debug_called(1);
774
775    if (sc->mly_controllerinfo != NULL)
776	free(sc->mly_controllerinfo, M_DEVBUF);
777
778    /* build the getcontrollerinfo ioctl and send it */
779    bzero(&mci, sizeof(mci));
780    sc->mly_controllerinfo = NULL;
781    mci.sub_ioctl = MDACIOCTL_GETCONTROLLERINFO;
782    if ((error = mly_ioctl(sc, &mci, (void **)&sc->mly_controllerinfo, sizeof(*sc->mly_controllerinfo),
783			   &status, NULL, NULL)))
784	return(error);
785    if (status != 0)
786	return(EIO);
787
788    if (sc->mly_controllerparam != NULL)
789	free(sc->mly_controllerparam, M_DEVBUF);
790
791    /* build the getcontrollerparameter ioctl and send it */
792    bzero(&mci, sizeof(mci));
793    sc->mly_controllerparam = NULL;
794    mci.sub_ioctl = MDACIOCTL_GETCONTROLLERPARAMETER;
795    if ((error = mly_ioctl(sc, &mci, (void **)&sc->mly_controllerparam, sizeof(*sc->mly_controllerparam),
796			   &status, NULL, NULL)))
797	return(error);
798    if (status != 0)
799	return(EIO);
800
801    return(0);
802}
803
804/********************************************************************************
805 * Schedule all possible devices for a rescan.
806 *
807 */
808static void
809mly_scan_devices(struct mly_softc *sc)
810{
811    int		bus, target;
812
813    debug_called(1);
814
815    /*
816     * Clear any previous BTL information.
817     */
818    bzero(&sc->mly_btl, sizeof(sc->mly_btl));
819
820    /*
821     * Mark all devices as requiring a rescan, and let the next
822     * periodic scan collect them.
823     */
824    for (bus = 0; bus < sc->mly_cam_channels; bus++)
825	if (MLY_BUS_IS_VALID(sc, bus))
826	    for (target = 0; target < MLY_MAX_TARGETS; target++)
827		sc->mly_btl[bus][target].mb_flags = MLY_BTL_RESCAN;
828
829}
830
831/********************************************************************************
832 * Rescan a device, possibly as a consequence of getting an event which suggests
833 * that it may have changed.
834 *
835 * If we suffer resource starvation, we can abandon the rescan as we'll be
836 * retried.
837 */
838static void
839mly_rescan_btl(struct mly_softc *sc, int bus, int target)
840{
841    struct mly_command		*mc;
842    struct mly_command_ioctl	*mci;
843
844    debug_called(1);
845
846    /* check that this bus is valid */
847    if (!MLY_BUS_IS_VALID(sc, bus))
848	return;
849
850    /* get a command */
851    if (mly_alloc_command(sc, &mc))
852	return;
853
854    /* set up the data buffer */
855    if ((mc->mc_data = malloc(sizeof(union mly_devinfo), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
856	mly_release_command(mc);
857	return;
858    }
859    mc->mc_flags |= MLY_CMD_DATAIN;
860    mc->mc_complete = mly_complete_rescan;
861
862    /*
863     * Build the ioctl.
864     */
865    mci = (struct mly_command_ioctl *)&mc->mc_packet->ioctl;
866    mci->opcode = MDACMD_IOCTL;
867    mci->addr.phys.controller = 0;
868    mci->timeout.value = 30;
869    mci->timeout.scale = MLY_TIMEOUT_SECONDS;
870    if (MLY_BUS_IS_VIRTUAL(sc, bus)) {
871	mc->mc_length = mci->data_size = sizeof(struct mly_ioctl_getlogdevinfovalid);
872	mci->sub_ioctl = MDACIOCTL_GETLOGDEVINFOVALID;
873	mci->addr.log.logdev = MLY_LOGDEV_ID(sc, bus, target);
874	debug(1, "logical device %d", mci->addr.log.logdev);
875    } else {
876	mc->mc_length = mci->data_size = sizeof(struct mly_ioctl_getphysdevinfovalid);
877	mci->sub_ioctl = MDACIOCTL_GETPHYSDEVINFOVALID;
878	mci->addr.phys.lun = 0;
879	mci->addr.phys.target = target;
880	mci->addr.phys.channel = bus;
881	debug(1, "physical device %d:%d", mci->addr.phys.channel, mci->addr.phys.target);
882    }
883
884    /*
885     * Dispatch the command.  If we successfully send the command, clear the rescan
886     * bit.
887     */
888    if (mly_start(mc) != 0) {
889	mly_release_command(mc);
890    } else {
891	sc->mly_btl[bus][target].mb_flags &= ~MLY_BTL_RESCAN;	/* success */
892    }
893}
894
895/********************************************************************************
896 * Handle the completion of a rescan operation
897 */
898static void
899mly_complete_rescan(struct mly_command *mc)
900{
901    struct mly_softc				*sc = mc->mc_sc;
902    struct mly_ioctl_getlogdevinfovalid		*ldi;
903    struct mly_ioctl_getphysdevinfovalid	*pdi;
904    struct mly_command_ioctl			*mci;
905    struct mly_btl				btl, *btlp;
906    int						bus, target, rescan;
907
908    debug_called(1);
909
910    /*
911     * Recover the bus and target from the command.  We need these even in
912     * the case where we don't have a useful response.
913     */
914    mci = (struct mly_command_ioctl *)&mc->mc_packet->ioctl;
915    if (mci->sub_ioctl == MDACIOCTL_GETLOGDEVINFOVALID) {
916	bus = MLY_LOGDEV_BUS(sc, mci->addr.log.logdev);
917	target = MLY_LOGDEV_TARGET(sc, mci->addr.log.logdev);
918    } else {
919	bus = mci->addr.phys.channel;
920	target = mci->addr.phys.target;
921    }
922    /* XXX validate bus/target? */
923
924    /* the default result is 'no device' */
925    bzero(&btl, sizeof(btl));
926
927    /* if the rescan completed OK, we have possibly-new BTL data */
928    if (mc->mc_status == 0) {
929	if (mc->mc_length == sizeof(*ldi)) {
930	    ldi = (struct mly_ioctl_getlogdevinfovalid *)mc->mc_data;
931	    if ((MLY_LOGDEV_BUS(sc, ldi->logical_device_number) != bus) ||
932		(MLY_LOGDEV_TARGET(sc, ldi->logical_device_number) != target)) {
933		mly_printf(sc, "WARNING: BTL rescan for %d:%d returned data for %d:%d instead\n",
934			   bus, target, MLY_LOGDEV_BUS(sc, ldi->logical_device_number),
935			   MLY_LOGDEV_TARGET(sc, ldi->logical_device_number));
936		/* XXX what can we do about this? */
937	    }
938	    btl.mb_flags = MLY_BTL_LOGICAL;
939	    btl.mb_type = ldi->raid_level;
940	    btl.mb_state = ldi->state;
941	    debug(1, "BTL rescan for %d returns %s, %s", ldi->logical_device_number,
942		  mly_describe_code(mly_table_device_type, ldi->raid_level),
943		  mly_describe_code(mly_table_device_state, ldi->state));
944	} else if (mc->mc_length == sizeof(*pdi)) {
945	    pdi = (struct mly_ioctl_getphysdevinfovalid *)mc->mc_data;
946	    if ((pdi->channel != bus) || (pdi->target != target)) {
947		mly_printf(sc, "WARNING: BTL rescan for %d:%d returned data for %d:%d instead\n",
948			   bus, target, pdi->channel, pdi->target);
949		/* XXX what can we do about this? */
950	    }
951	    btl.mb_flags = MLY_BTL_PHYSICAL;
952	    btl.mb_type = MLY_DEVICE_TYPE_PHYSICAL;
953	    btl.mb_state = pdi->state;
954	    btl.mb_speed = pdi->speed;
955	    btl.mb_width = pdi->width;
956	    if (pdi->state != MLY_DEVICE_STATE_UNCONFIGURED)
957		sc->mly_btl[bus][target].mb_flags |= MLY_BTL_PROTECTED;
958	    debug(1, "BTL rescan for %d:%d returns %s", bus, target,
959		  mly_describe_code(mly_table_device_state, pdi->state));
960	} else {
961	    mly_printf(sc, "BTL rescan result invalid\n");
962	}
963    }
964
965    free(mc->mc_data, M_DEVBUF);
966    mly_release_command(mc);
967
968    /*
969     * Decide whether we need to rescan the device.
970     */
971    rescan = 0;
972
973    /* device type changes (usually between 'nothing' and 'something') */
974    btlp = &sc->mly_btl[bus][target];
975    if (btl.mb_flags != btlp->mb_flags) {
976	debug(1, "flags changed, rescanning");
977	rescan = 1;
978    }
979
980    /* XXX other reasons? */
981
982    /*
983     * Update BTL information.
984     */
985    *btlp = btl;
986
987    /*
988     * Perform CAM rescan if required.
989     */
990    if (rescan)
991	mly_cam_rescan_btl(sc, bus, target);
992}
993
994/********************************************************************************
995 * Get the current health status and set the 'next event' counter to suit.
996 */
997static int
998mly_get_eventstatus(struct mly_softc *sc)
999{
1000    struct mly_command_ioctl	mci;
1001    struct mly_health_status	*mh;
1002    u_int8_t			status;
1003    int				error;
1004
1005    /* build the gethealthstatus ioctl and send it */
1006    bzero(&mci, sizeof(mci));
1007    mh = NULL;
1008    mci.sub_ioctl = MDACIOCTL_GETHEALTHSTATUS;
1009
1010    if ((error = mly_ioctl(sc, &mci, (void **)&mh, sizeof(*mh), &status, NULL, NULL)))
1011	return(error);
1012    if (status != 0)
1013	return(EIO);
1014
1015    /* get the event counter */
1016    sc->mly_event_change = mh->change_counter;
1017    sc->mly_event_waiting = mh->next_event;
1018    sc->mly_event_counter = mh->next_event;
1019
1020    /* save the health status into the memory mailbox */
1021    bcopy(mh, &sc->mly_mmbox->mmm_health.status, sizeof(*mh));
1022
1023    debug(1, "initial change counter %d, event counter %d", mh->change_counter, mh->next_event);
1024
1025    free(mh, M_DEVBUF);
1026    return(0);
1027}
1028
1029/********************************************************************************
1030 * Enable the memory mailbox mode.
1031 */
1032static int
1033mly_enable_mmbox(struct mly_softc *sc)
1034{
1035    struct mly_command_ioctl	mci;
1036    u_int8_t			*sp, status;
1037    int				error;
1038
1039    debug_called(1);
1040
1041    /* build the ioctl and send it */
1042    bzero(&mci, sizeof(mci));
1043    mci.sub_ioctl = MDACIOCTL_SETMEMORYMAILBOX;
1044    /* set buffer addresses */
1045    mci.param.setmemorymailbox.command_mailbox_physaddr =
1046	sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_command);
1047    mci.param.setmemorymailbox.status_mailbox_physaddr =
1048	sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_status);
1049    mci.param.setmemorymailbox.health_buffer_physaddr =
1050	sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_health);
1051
1052    /* set buffer sizes - abuse of data_size field is revolting */
1053    sp = (u_int8_t *)&mci.data_size;
1054    sp[0] = ((sizeof(union mly_command_packet) * MLY_MMBOX_COMMANDS) / 1024);
1055    sp[1] = (sizeof(union mly_status_packet) * MLY_MMBOX_STATUS) / 1024;
1056    mci.param.setmemorymailbox.health_buffer_size = sizeof(union mly_health_region) / 1024;
1057
1058    debug(1, "memory mailbox at %p (0x%llx/%d 0x%llx/%d 0x%llx/%d", sc->mly_mmbox,
1059	  mci.param.setmemorymailbox.command_mailbox_physaddr, sp[0],
1060	  mci.param.setmemorymailbox.status_mailbox_physaddr, sp[1],
1061	  mci.param.setmemorymailbox.health_buffer_physaddr,
1062	  mci.param.setmemorymailbox.health_buffer_size);
1063
1064    if ((error = mly_ioctl(sc, &mci, NULL, 0, &status, NULL, NULL)))
1065	return(error);
1066    if (status != 0)
1067	return(EIO);
1068    sc->mly_state |= MLY_STATE_MMBOX_ACTIVE;
1069    debug(1, "memory mailbox active");
1070    return(0);
1071}
1072
1073/********************************************************************************
1074 * Flush all pending I/O from the controller.
1075 */
1076static int
1077mly_flush(struct mly_softc *sc)
1078{
1079    struct mly_command_ioctl	mci;
1080    u_int8_t			status;
1081    int				error;
1082
1083    debug_called(1);
1084
1085    /* build the ioctl */
1086    bzero(&mci, sizeof(mci));
1087    mci.sub_ioctl = MDACIOCTL_FLUSHDEVICEDATA;
1088    mci.param.deviceoperation.operation_device = MLY_OPDEVICE_PHYSICAL_CONTROLLER;
1089
1090    /* pass it off to the controller */
1091    if ((error = mly_ioctl(sc, &mci, NULL, 0, &status, NULL, NULL)))
1092	return(error);
1093
1094    return((status == 0) ? 0 : EIO);
1095}
1096
1097/********************************************************************************
1098 * Perform an ioctl command.
1099 *
1100 * If (data) is not NULL, the command requires data transfer.  If (*data) is NULL
1101 * the command requires data transfer from the controller, and we will allocate
1102 * a buffer for it.  If (*data) is not NULL, the command requires data transfer
1103 * to the controller.
1104 *
1105 * XXX passing in the whole ioctl structure is ugly.  Better ideas?
1106 *
1107 * XXX we don't even try to handle the case where datasize > 4k.  We should.
1108 */
1109static int
1110mly_ioctl(struct mly_softc *sc, struct mly_command_ioctl *ioctl, void **data, size_t datasize,
1111	  u_int8_t *status, void *sense_buffer, size_t *sense_length)
1112{
1113    struct mly_command		*mc;
1114    struct mly_command_ioctl	*mci;
1115    int				error;
1116
1117    debug_called(1);
1118    MLY_ASSERT_LOCKED(sc);
1119
1120    mc = NULL;
1121    if (mly_alloc_command(sc, &mc)) {
1122	error = ENOMEM;
1123	goto out;
1124    }
1125
1126    /* copy the ioctl structure, but save some important fields and then fixup */
1127    mci = &mc->mc_packet->ioctl;
1128    ioctl->sense_buffer_address = mci->sense_buffer_address;
1129    ioctl->maximum_sense_size = mci->maximum_sense_size;
1130    *mci = *ioctl;
1131    mci->opcode = MDACMD_IOCTL;
1132    mci->timeout.value = 30;
1133    mci->timeout.scale = MLY_TIMEOUT_SECONDS;
1134
1135    /* handle the data buffer */
1136    if (data != NULL) {
1137	if (*data == NULL) {
1138	    /* allocate data buffer */
1139	    if ((mc->mc_data = malloc(datasize, M_DEVBUF, M_NOWAIT)) == NULL) {
1140		error = ENOMEM;
1141		goto out;
1142	    }
1143	    mc->mc_flags |= MLY_CMD_DATAIN;
1144	} else {
1145	    mc->mc_data = *data;
1146	    mc->mc_flags |= MLY_CMD_DATAOUT;
1147	}
1148	mc->mc_length = datasize;
1149	mc->mc_packet->generic.data_size = datasize;
1150    }
1151
1152    /* run the command */
1153    if ((error = mly_immediate_command(mc)))
1154	goto out;
1155
1156    /* clean up and return any data */
1157    *status = mc->mc_status;
1158    if ((mc->mc_sense > 0) && (sense_buffer != NULL)) {
1159	bcopy(mc->mc_packet, sense_buffer, mc->mc_sense);
1160	*sense_length = mc->mc_sense;
1161	goto out;
1162    }
1163
1164    /* should we return a data pointer? */
1165    if ((data != NULL) && (*data == NULL))
1166	*data = mc->mc_data;
1167
1168    /* command completed OK */
1169    error = 0;
1170
1171out:
1172    if (mc != NULL) {
1173	/* do we need to free a data buffer we allocated? */
1174	if (error && (mc->mc_data != NULL) && (*data == NULL))
1175	    free(mc->mc_data, M_DEVBUF);
1176	mly_release_command(mc);
1177    }
1178    return(error);
1179}
1180
1181/********************************************************************************
1182 * Check for event(s) outstanding in the controller.
1183 */
1184static void
1185mly_check_event(struct mly_softc *sc)
1186{
1187
1188    /*
1189     * The controller may have updated the health status information,
1190     * so check for it here.  Note that the counters are all in host memory,
1191     * so this check is very cheap.  Also note that we depend on checking on
1192     * completion
1193     */
1194    if (sc->mly_mmbox->mmm_health.status.change_counter != sc->mly_event_change) {
1195	sc->mly_event_change = sc->mly_mmbox->mmm_health.status.change_counter;
1196	debug(1, "event change %d, event status update, %d -> %d", sc->mly_event_change,
1197	      sc->mly_event_waiting, sc->mly_mmbox->mmm_health.status.next_event);
1198	sc->mly_event_waiting = sc->mly_mmbox->mmm_health.status.next_event;
1199
1200	/* wake up anyone that might be interested in this */
1201	wakeup(&sc->mly_event_change);
1202    }
1203    if (sc->mly_event_counter != sc->mly_event_waiting)
1204    mly_fetch_event(sc);
1205}
1206
1207/********************************************************************************
1208 * Fetch one event from the controller.
1209 *
1210 * If we fail due to resource starvation, we'll be retried the next time a
1211 * command completes.
1212 */
1213static void
1214mly_fetch_event(struct mly_softc *sc)
1215{
1216    struct mly_command		*mc;
1217    struct mly_command_ioctl	*mci;
1218    u_int32_t			event;
1219
1220    debug_called(1);
1221
1222    /* get a command */
1223    if (mly_alloc_command(sc, &mc))
1224	return;
1225
1226    /* set up the data buffer */
1227    if ((mc->mc_data = malloc(sizeof(struct mly_event), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) {
1228	mly_release_command(mc);
1229	return;
1230    }
1231    mc->mc_length = sizeof(struct mly_event);
1232    mc->mc_flags |= MLY_CMD_DATAIN;
1233    mc->mc_complete = mly_complete_event;
1234
1235    /*
1236     * Get an event number to fetch.  It's possible that we've raced with another
1237     * context for the last event, in which case there will be no more events.
1238     */
1239    if (sc->mly_event_counter == sc->mly_event_waiting) {
1240	mly_release_command(mc);
1241	return;
1242    }
1243    event = sc->mly_event_counter++;
1244
1245    /*
1246     * Build the ioctl.
1247     *
1248     * At this point we are committed to sending this request, as it
1249     * will be the only one constructed for this particular event number.
1250     */
1251    mci = (struct mly_command_ioctl *)&mc->mc_packet->ioctl;
1252    mci->opcode = MDACMD_IOCTL;
1253    mci->data_size = sizeof(struct mly_event);
1254    mci->addr.phys.lun = (event >> 16) & 0xff;
1255    mci->addr.phys.target = (event >> 24) & 0xff;
1256    mci->addr.phys.channel = 0;
1257    mci->addr.phys.controller = 0;
1258    mci->timeout.value = 30;
1259    mci->timeout.scale = MLY_TIMEOUT_SECONDS;
1260    mci->sub_ioctl = MDACIOCTL_GETEVENT;
1261    mci->param.getevent.sequence_number_low = event & 0xffff;
1262
1263    debug(1, "fetch event %u", event);
1264
1265    /*
1266     * Submit the command.
1267     *
1268     * Note that failure of mly_start() will result in this event never being
1269     * fetched.
1270     */
1271    if (mly_start(mc) != 0) {
1272	mly_printf(sc, "couldn't fetch event %u\n", event);
1273	mly_release_command(mc);
1274    }
1275}
1276
1277/********************************************************************************
1278 * Handle the completion of an event poll.
1279 */
1280static void
1281mly_complete_event(struct mly_command *mc)
1282{
1283    struct mly_softc	*sc = mc->mc_sc;
1284    struct mly_event	*me = (struct mly_event *)mc->mc_data;
1285
1286    debug_called(1);
1287
1288    /*
1289     * If the event was successfully fetched, process it.
1290     */
1291    if (mc->mc_status == SCSI_STATUS_OK) {
1292	mly_process_event(sc, me);
1293	free(me, M_DEVBUF);
1294    }
1295    mly_release_command(mc);
1296
1297    /*
1298     * Check for another event.
1299     */
1300    mly_check_event(sc);
1301}
1302
1303/********************************************************************************
1304 * Process a controller event.
1305 */
1306static void
1307mly_process_event(struct mly_softc *sc, struct mly_event *me)
1308{
1309    struct scsi_sense_data_fixed *ssd;
1310    char			 *fp, *tp;
1311    int				 bus, target, event, class, action;
1312
1313    ssd = (struct scsi_sense_data_fixed *)&me->sense[0];
1314
1315    /*
1316     * Errors can be reported using vendor-unique sense data.  In this case, the
1317     * event code will be 0x1c (Request sense data present), the sense key will
1318     * be 0x09 (vendor specific), the MSB of the ASC will be set, and the
1319     * actual event code will be a 16-bit value comprised of the ASCQ (low byte)
1320     * and low seven bits of the ASC (low seven bits of the high byte).
1321     */
1322    if ((me->code == 0x1c) &&
1323	((ssd->flags & SSD_KEY) == SSD_KEY_Vendor_Specific) &&
1324	(ssd->add_sense_code & 0x80)) {
1325	event = ((int)(ssd->add_sense_code & ~0x80) << 8) + ssd->add_sense_code_qual;
1326    } else {
1327	event = me->code;
1328    }
1329
1330    /* look up event, get codes */
1331    fp = mly_describe_code(mly_table_event, event);
1332
1333    debug(1, "Event %d  code 0x%x", me->sequence_number, me->code);
1334
1335    /* quiet event? */
1336    class = fp[0];
1337    if (isupper(class) && bootverbose)
1338	class = tolower(class);
1339
1340    /* get action code, text string */
1341    action = fp[1];
1342    tp = &fp[2];
1343
1344    /*
1345     * Print some information about the event.
1346     *
1347     * This code uses a table derived from the corresponding portion of the Linux
1348     * driver, and thus the parser is very similar.
1349     */
1350    switch(class) {
1351    case 'p':		/* error on physical device */
1352	mly_printf(sc, "physical device %d:%d %s\n", me->channel, me->target, tp);
1353	if (action == 'r')
1354	    sc->mly_btl[me->channel][me->target].mb_flags |= MLY_BTL_RESCAN;
1355	break;
1356    case 'l':		/* error on logical unit */
1357    case 'm':		/* message about logical unit */
1358	bus = MLY_LOGDEV_BUS(sc, me->lun);
1359	target = MLY_LOGDEV_TARGET(sc, me->lun);
1360	mly_name_device(sc, bus, target);
1361	mly_printf(sc, "logical device %d (%s) %s\n", me->lun, sc->mly_btl[bus][target].mb_name, tp);
1362	if (action == 'r')
1363	    sc->mly_btl[bus][target].mb_flags |= MLY_BTL_RESCAN;
1364	break;
1365    case 's':		/* report of sense data */
1366	if (((ssd->flags & SSD_KEY) == SSD_KEY_NO_SENSE) ||
1367	    (((ssd->flags & SSD_KEY) == SSD_KEY_NOT_READY) &&
1368	     (ssd->add_sense_code == 0x04) &&
1369	     ((ssd->add_sense_code_qual == 0x01) || (ssd->add_sense_code_qual == 0x02))))
1370	    break;	/* ignore NO_SENSE or NOT_READY in one case */
1371
1372	mly_printf(sc, "physical device %d:%d %s\n", me->channel, me->target, tp);
1373	mly_printf(sc, "  sense key %d  asc %02x  ascq %02x\n",
1374		      ssd->flags & SSD_KEY, ssd->add_sense_code, ssd->add_sense_code_qual);
1375	mly_printf(sc, "  info %4D  csi %4D\n", ssd->info, "", ssd->cmd_spec_info, "");
1376	if (action == 'r')
1377	    sc->mly_btl[me->channel][me->target].mb_flags |= MLY_BTL_RESCAN;
1378	break;
1379    case 'e':
1380	mly_printf(sc, tp, me->target, me->lun);
1381	printf("\n");
1382	break;
1383    case 'c':
1384	mly_printf(sc, "controller %s\n", tp);
1385	break;
1386    case '?':
1387	mly_printf(sc, "%s - %d\n", tp, me->code);
1388	break;
1389    default:	/* probably a 'noisy' event being ignored */
1390	break;
1391    }
1392}
1393
1394/********************************************************************************
1395 * Perform periodic activities.
1396 */
1397static void
1398mly_periodic(void *data)
1399{
1400    struct mly_softc	*sc = (struct mly_softc *)data;
1401    int			bus, target;
1402
1403    debug_called(2);
1404    MLY_ASSERT_LOCKED(sc);
1405
1406    /*
1407     * Scan devices.
1408     */
1409    for (bus = 0; bus < sc->mly_cam_channels; bus++) {
1410	if (MLY_BUS_IS_VALID(sc, bus)) {
1411	    for (target = 0; target < MLY_MAX_TARGETS; target++) {
1412
1413		/* ignore the controller in this scan */
1414		if (target == sc->mly_controllerparam->initiator_id)
1415		    continue;
1416
1417		/* perform device rescan? */
1418		if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_RESCAN)
1419		    mly_rescan_btl(sc, bus, target);
1420	    }
1421	}
1422    }
1423
1424    /* check for controller events */
1425    mly_check_event(sc);
1426
1427    /* reschedule ourselves */
1428    callout_schedule(&sc->mly_periodic, MLY_PERIODIC_INTERVAL * hz);
1429}
1430
1431/********************************************************************************
1432 ********************************************************************************
1433                                                               Command Processing
1434 ********************************************************************************
1435 ********************************************************************************/
1436
1437/********************************************************************************
1438 * Run a command and wait for it to complete.
1439 *
1440 */
1441static int
1442mly_immediate_command(struct mly_command *mc)
1443{
1444    struct mly_softc	*sc = mc->mc_sc;
1445    int			error;
1446
1447    debug_called(1);
1448
1449    MLY_ASSERT_LOCKED(sc);
1450    if ((error = mly_start(mc))) {
1451	return(error);
1452    }
1453
1454    if (sc->mly_state & MLY_STATE_INTERRUPTS_ON) {
1455	/* sleep on the command */
1456	while(!(mc->mc_flags & MLY_CMD_COMPLETE)) {
1457	    mtx_sleep(mc, &sc->mly_lock, PRIBIO, "mlywait", 0);
1458	}
1459    } else {
1460	/* spin and collect status while we do */
1461	while(!(mc->mc_flags & MLY_CMD_COMPLETE)) {
1462	    mly_done(mc->mc_sc);
1463	}
1464    }
1465    return(0);
1466}
1467
1468/********************************************************************************
1469 * Deliver a command to the controller.
1470 *
1471 * XXX it would be good to just queue commands that we can't submit immediately
1472 *     and send them later, but we probably want a wrapper for that so that
1473 *     we don't hang on a failed submission for an immediate command.
1474 */
1475static int
1476mly_start(struct mly_command *mc)
1477{
1478    struct mly_softc		*sc = mc->mc_sc;
1479    union mly_command_packet	*pkt;
1480
1481    debug_called(2);
1482    MLY_ASSERT_LOCKED(sc);
1483
1484    /*
1485     * Set the command up for delivery to the controller.
1486     */
1487    mly_map_command(mc);
1488    mc->mc_packet->generic.command_id = mc->mc_slot;
1489
1490#ifdef MLY_DEBUG
1491    mc->mc_timestamp = time_second;
1492#endif
1493
1494    /*
1495     * Do we have to use the hardware mailbox?
1496     */
1497    if (!(sc->mly_state & MLY_STATE_MMBOX_ACTIVE)) {
1498	/*
1499	 * Check to see if the controller is ready for us.
1500	 */
1501	if (MLY_IDBR_TRUE(sc, MLY_HM_CMDSENT)) {
1502	    return(EBUSY);
1503	}
1504	mc->mc_flags |= MLY_CMD_BUSY;
1505
1506	/*
1507	 * It's ready, send the command.
1508	 */
1509	MLY_SET_MBOX(sc, sc->mly_command_mailbox, &mc->mc_packetphys);
1510	MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_CMDSENT);
1511
1512    } else {	/* use memory-mailbox mode */
1513
1514	pkt = &sc->mly_mmbox->mmm_command[sc->mly_mmbox_command_index];
1515
1516	/* check to see if the next index is free yet */
1517	if (pkt->mmbox.flag != 0) {
1518	    return(EBUSY);
1519	}
1520	mc->mc_flags |= MLY_CMD_BUSY;
1521
1522	/* copy in new command */
1523	bcopy(mc->mc_packet->mmbox.data, pkt->mmbox.data, sizeof(pkt->mmbox.data));
1524	/* barrier to ensure completion of previous write before we write the flag */
1525	bus_barrier(sc->mly_regs_resource, 0, 0, BUS_SPACE_BARRIER_WRITE);
1526	/* copy flag last */
1527	pkt->mmbox.flag = mc->mc_packet->mmbox.flag;
1528	/* barrier to ensure completion of previous write before we notify the controller */
1529	bus_barrier(sc->mly_regs_resource, 0, 0, BUS_SPACE_BARRIER_WRITE);
1530
1531	/* signal controller, update index */
1532	MLY_SET_REG(sc, sc->mly_idbr, MLY_AM_CMDSENT);
1533	sc->mly_mmbox_command_index = (sc->mly_mmbox_command_index + 1) % MLY_MMBOX_COMMANDS;
1534    }
1535
1536    mly_enqueue_busy(mc);
1537    return(0);
1538}
1539
1540/********************************************************************************
1541 * Pick up command status from the controller, schedule a completion event
1542 */
1543static void
1544mly_done(struct mly_softc *sc)
1545{
1546    struct mly_command		*mc;
1547    union mly_status_packet	*sp;
1548    u_int16_t			slot;
1549    int				worked;
1550
1551    MLY_ASSERT_LOCKED(sc);
1552    worked = 0;
1553
1554    /* pick up hardware-mailbox commands */
1555    if (MLY_ODBR_TRUE(sc, MLY_HM_STSREADY)) {
1556	slot = MLY_GET_REG2(sc, sc->mly_status_mailbox);
1557	if (slot < MLY_SLOT_MAX) {
1558	    mc = &sc->mly_command[slot - MLY_SLOT_START];
1559	    mc->mc_status = MLY_GET_REG(sc, sc->mly_status_mailbox + 2);
1560	    mc->mc_sense = MLY_GET_REG(sc, sc->mly_status_mailbox + 3);
1561	    mc->mc_resid = MLY_GET_REG4(sc, sc->mly_status_mailbox + 4);
1562	    mly_remove_busy(mc);
1563	    mc->mc_flags &= ~MLY_CMD_BUSY;
1564	    mly_enqueue_complete(mc);
1565	    worked = 1;
1566	} else {
1567	    /* slot 0xffff may mean "extremely bogus command" */
1568	    mly_printf(sc, "got HM completion for illegal slot %u\n", slot);
1569	}
1570	/* unconditionally acknowledge status */
1571	MLY_SET_REG(sc, sc->mly_odbr, MLY_HM_STSREADY);
1572	MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_STSACK);
1573    }
1574
1575    /* pick up memory-mailbox commands */
1576    if (MLY_ODBR_TRUE(sc, MLY_AM_STSREADY)) {
1577	for (;;) {
1578	    sp = &sc->mly_mmbox->mmm_status[sc->mly_mmbox_status_index];
1579
1580	    /* check for more status */
1581	    if (sp->mmbox.flag == 0)
1582		break;
1583
1584	    /* get slot number */
1585	    slot = sp->status.command_id;
1586	    if (slot < MLY_SLOT_MAX) {
1587		mc = &sc->mly_command[slot - MLY_SLOT_START];
1588		mc->mc_status = sp->status.status;
1589		mc->mc_sense = sp->status.sense_length;
1590		mc->mc_resid = sp->status.residue;
1591		mly_remove_busy(mc);
1592		mc->mc_flags &= ~MLY_CMD_BUSY;
1593		mly_enqueue_complete(mc);
1594		worked = 1;
1595	    } else {
1596		/* slot 0xffff may mean "extremely bogus command" */
1597		mly_printf(sc, "got AM completion for illegal slot %u at %d\n",
1598			   slot, sc->mly_mmbox_status_index);
1599	    }
1600
1601	    /* clear and move to next index */
1602	    sp->mmbox.flag = 0;
1603	    sc->mly_mmbox_status_index = (sc->mly_mmbox_status_index + 1) % MLY_MMBOX_STATUS;
1604	}
1605	/* acknowledge that we have collected status value(s) */
1606	MLY_SET_REG(sc, sc->mly_odbr, MLY_AM_STSREADY);
1607    }
1608
1609    if (worked) {
1610	if (sc->mly_state & MLY_STATE_INTERRUPTS_ON)
1611	    taskqueue_enqueue(taskqueue_thread, &sc->mly_task_complete);
1612	else
1613	    mly_complete(sc);
1614    }
1615}
1616
1617/********************************************************************************
1618 * Process completed commands
1619 */
1620static void
1621mly_complete_handler(void *context, int pending)
1622{
1623    struct mly_softc	*sc = (struct mly_softc *)context;
1624
1625    MLY_LOCK(sc);
1626    mly_complete(sc);
1627    MLY_UNLOCK(sc);
1628}
1629
1630static void
1631mly_complete(struct mly_softc *sc)
1632{
1633    struct mly_command	*mc;
1634    void	        (* mc_complete)(struct mly_command *mc);
1635
1636    debug_called(2);
1637
1638    /*
1639     * Spin pulling commands off the completed queue and processing them.
1640     */
1641    while ((mc = mly_dequeue_complete(sc)) != NULL) {
1642
1643	/*
1644	 * Free controller resources, mark command complete.
1645	 *
1646	 * Note that as soon as we mark the command complete, it may be freed
1647	 * out from under us, so we need to save the mc_complete field in
1648	 * order to later avoid dereferencing mc.  (We would not expect to
1649	 * have a polling/sleeping consumer with mc_complete != NULL).
1650	 */
1651	mly_unmap_command(mc);
1652	mc_complete = mc->mc_complete;
1653	mc->mc_flags |= MLY_CMD_COMPLETE;
1654
1655	/*
1656	 * Call completion handler or wake up sleeping consumer.
1657	 */
1658	if (mc_complete != NULL) {
1659	    mc_complete(mc);
1660	} else {
1661	    wakeup(mc);
1662	}
1663    }
1664
1665    /*
1666     * XXX if we are deferring commands due to controller-busy status, we should
1667     *     retry submitting them here.
1668     */
1669}
1670
1671/********************************************************************************
1672 ********************************************************************************
1673                                                        Command Buffer Management
1674 ********************************************************************************
1675 ********************************************************************************/
1676
1677/********************************************************************************
1678 * Allocate a command.
1679 */
1680static int
1681mly_alloc_command(struct mly_softc *sc, struct mly_command **mcp)
1682{
1683    struct mly_command	*mc;
1684
1685    debug_called(3);
1686
1687    if ((mc = mly_dequeue_free(sc)) == NULL)
1688	return(ENOMEM);
1689
1690    *mcp = mc;
1691    return(0);
1692}
1693
1694/********************************************************************************
1695 * Release a command back to the freelist.
1696 */
1697static void
1698mly_release_command(struct mly_command *mc)
1699{
1700    debug_called(3);
1701
1702    /*
1703     * Fill in parts of the command that may cause confusion if
1704     * a consumer doesn't when we are later allocated.
1705     */
1706    mc->mc_data = NULL;
1707    mc->mc_flags = 0;
1708    mc->mc_complete = NULL;
1709    mc->mc_private = NULL;
1710
1711    /*
1712     * By default, we set up to overwrite the command packet with
1713     * sense information.
1714     */
1715    mc->mc_packet->generic.sense_buffer_address = mc->mc_packetphys;
1716    mc->mc_packet->generic.maximum_sense_size = sizeof(union mly_command_packet);
1717
1718    mly_enqueue_free(mc);
1719}
1720
1721/********************************************************************************
1722 * Map helper for command allocation.
1723 */
1724static void
1725mly_alloc_commands_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1726{
1727    struct mly_softc	*sc = (struct mly_softc *)arg;
1728
1729    debug_called(1);
1730
1731    sc->mly_packetphys = segs[0].ds_addr;
1732}
1733
1734/********************************************************************************
1735 * Allocate and initialise command and packet structures.
1736 *
1737 * If the controller supports fewer than MLY_MAX_COMMANDS commands, limit our
1738 * allocation to that number.  If we don't yet know how many commands the
1739 * controller supports, allocate a very small set (suitable for initialisation
1740 * purposes only).
1741 */
1742static int
1743mly_alloc_commands(struct mly_softc *sc)
1744{
1745    struct mly_command		*mc;
1746    int				i, ncmd;
1747
1748    if (sc->mly_controllerinfo == NULL) {
1749	ncmd = 4;
1750    } else {
1751	ncmd = min(MLY_MAX_COMMANDS, sc->mly_controllerinfo->maximum_parallel_commands);
1752    }
1753
1754    /*
1755     * Allocate enough space for all the command packets in one chunk and
1756     * map them permanently into controller-visible space.
1757     */
1758    if (bus_dmamem_alloc(sc->mly_packet_dmat, (void **)&sc->mly_packet,
1759			 BUS_DMA_NOWAIT, &sc->mly_packetmap)) {
1760	return(ENOMEM);
1761    }
1762    if (bus_dmamap_load(sc->mly_packet_dmat, sc->mly_packetmap, sc->mly_packet,
1763			ncmd * sizeof(union mly_command_packet),
1764			mly_alloc_commands_map, sc, BUS_DMA_NOWAIT) != 0)
1765	return (ENOMEM);
1766
1767    for (i = 0; i < ncmd; i++) {
1768	mc = &sc->mly_command[i];
1769	bzero(mc, sizeof(*mc));
1770	mc->mc_sc = sc;
1771	mc->mc_slot = MLY_SLOT_START + i;
1772	mc->mc_packet = sc->mly_packet + i;
1773	mc->mc_packetphys = sc->mly_packetphys + (i * sizeof(union mly_command_packet));
1774	if (!bus_dmamap_create(sc->mly_buffer_dmat, 0, &mc->mc_datamap))
1775	    mly_release_command(mc);
1776    }
1777    return(0);
1778}
1779
1780/********************************************************************************
1781 * Free all the storage held by commands.
1782 *
1783 * Must be called with all commands on the free list.
1784 */
1785static void
1786mly_release_commands(struct mly_softc *sc)
1787{
1788    struct mly_command	*mc;
1789
1790    /* throw away command buffer DMA maps */
1791    while (mly_alloc_command(sc, &mc) == 0)
1792	bus_dmamap_destroy(sc->mly_buffer_dmat, mc->mc_datamap);
1793
1794    /* release the packet storage */
1795    if (sc->mly_packet != NULL) {
1796	bus_dmamap_unload(sc->mly_packet_dmat, sc->mly_packetmap);
1797	bus_dmamem_free(sc->mly_packet_dmat, sc->mly_packet, sc->mly_packetmap);
1798	sc->mly_packet = NULL;
1799    }
1800}
1801
1802
1803/********************************************************************************
1804 * Command-mapping helper function - populate this command's s/g table
1805 * with the s/g entries for its data.
1806 */
1807static void
1808mly_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1809{
1810    struct mly_command		*mc = (struct mly_command *)arg;
1811    struct mly_softc		*sc = mc->mc_sc;
1812    struct mly_command_generic	*gen = &(mc->mc_packet->generic);
1813    struct mly_sg_entry		*sg;
1814    int				i, tabofs;
1815
1816    debug_called(2);
1817
1818    /* can we use the transfer structure directly? */
1819    if (nseg <= 2) {
1820	sg = &gen->transfer.direct.sg[0];
1821	gen->command_control.extended_sg_table = 0;
1822    } else {
1823	tabofs = ((mc->mc_slot - MLY_SLOT_START) * MLY_MAX_SGENTRIES);
1824	sg = sc->mly_sg_table + tabofs;
1825	gen->transfer.indirect.entries[0] = nseg;
1826	gen->transfer.indirect.table_physaddr[0] = sc->mly_sg_busaddr + (tabofs * sizeof(struct mly_sg_entry));
1827	gen->command_control.extended_sg_table = 1;
1828    }
1829
1830    /* copy the s/g table */
1831    for (i = 0; i < nseg; i++) {
1832	sg[i].physaddr = segs[i].ds_addr;
1833	sg[i].length = segs[i].ds_len;
1834    }
1835
1836}
1837
1838#if 0
1839/********************************************************************************
1840 * Command-mapping helper function - save the cdb's physical address.
1841 *
1842 * We don't support 'large' SCSI commands at this time, so this is unused.
1843 */
1844static void
1845mly_map_command_cdb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1846{
1847    struct mly_command			*mc = (struct mly_command *)arg;
1848
1849    debug_called(2);
1850
1851    /* XXX can we safely assume that a CDB will never cross a page boundary? */
1852    if ((segs[0].ds_addr % PAGE_SIZE) >
1853	((segs[0].ds_addr + mc->mc_packet->scsi_large.cdb_length) % PAGE_SIZE))
1854	panic("cdb crosses page boundary");
1855
1856    /* fix up fields in the command packet */
1857    mc->mc_packet->scsi_large.cdb_physaddr = segs[0].ds_addr;
1858}
1859#endif
1860
1861/********************************************************************************
1862 * Map a command into controller-visible space
1863 */
1864static void
1865mly_map_command(struct mly_command *mc)
1866{
1867    struct mly_softc	*sc = mc->mc_sc;
1868
1869    debug_called(2);
1870
1871    /* don't map more than once */
1872    if (mc->mc_flags & MLY_CMD_MAPPED)
1873	return;
1874
1875    /* does the command have a data buffer? */
1876    if (mc->mc_data != NULL) {
1877	if (mc->mc_flags & MLY_CMD_CCB)
1878		bus_dmamap_load_ccb(sc->mly_buffer_dmat, mc->mc_datamap,
1879				mc->mc_data, mly_map_command_sg, mc, 0);
1880	else
1881		bus_dmamap_load(sc->mly_buffer_dmat, mc->mc_datamap,
1882				mc->mc_data, mc->mc_length,
1883				mly_map_command_sg, mc, 0);
1884	if (mc->mc_flags & MLY_CMD_DATAIN)
1885	    bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_PREREAD);
1886	if (mc->mc_flags & MLY_CMD_DATAOUT)
1887	    bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_PREWRITE);
1888    }
1889    mc->mc_flags |= MLY_CMD_MAPPED;
1890}
1891
1892/********************************************************************************
1893 * Unmap a command from controller-visible space
1894 */
1895static void
1896mly_unmap_command(struct mly_command *mc)
1897{
1898    struct mly_softc	*sc = mc->mc_sc;
1899
1900    debug_called(2);
1901
1902    if (!(mc->mc_flags & MLY_CMD_MAPPED))
1903	return;
1904
1905    /* does the command have a data buffer? */
1906    if (mc->mc_data != NULL) {
1907	if (mc->mc_flags & MLY_CMD_DATAIN)
1908	    bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_POSTREAD);
1909	if (mc->mc_flags & MLY_CMD_DATAOUT)
1910	    bus_dmamap_sync(sc->mly_buffer_dmat, mc->mc_datamap, BUS_DMASYNC_POSTWRITE);
1911
1912	bus_dmamap_unload(sc->mly_buffer_dmat, mc->mc_datamap);
1913    }
1914    mc->mc_flags &= ~MLY_CMD_MAPPED;
1915}
1916
1917
1918/********************************************************************************
1919 ********************************************************************************
1920                                                                    CAM interface
1921 ********************************************************************************
1922 ********************************************************************************/
1923
1924/********************************************************************************
1925 * Attach the physical and virtual SCSI busses to CAM.
1926 *
1927 * Physical bus numbering starts from 0, virtual bus numbering from one greater
1928 * than the highest physical bus.  Physical busses are only registered if
1929 * the kernel environment variable "hw.mly.register_physical_channels" is set.
1930 *
1931 * When we refer to a "bus", we are referring to the bus number registered with
1932 * the SIM, whereas a "channel" is a channel number given to the adapter.  In order
1933 * to keep things simple, we map these 1:1, so "bus" and "channel" may be used
1934 * interchangeably.
1935 */
1936static int
1937mly_cam_attach(struct mly_softc *sc)
1938{
1939    struct cam_devq	*devq;
1940    int			chn, i;
1941
1942    debug_called(1);
1943
1944    /*
1945     * Allocate a devq for all our channels combined.
1946     */
1947    if ((devq = cam_simq_alloc(sc->mly_controllerinfo->maximum_parallel_commands)) == NULL) {
1948	mly_printf(sc, "can't allocate CAM SIM queue\n");
1949	return(ENOMEM);
1950    }
1951
1952    /*
1953     * If physical channel registration has been requested, register these first.
1954     * Note that we enable tagged command queueing for physical channels.
1955     */
1956    if (testenv("hw.mly.register_physical_channels")) {
1957	chn = 0;
1958	for (i = 0; i < sc->mly_controllerinfo->physical_channels_present; i++, chn++) {
1959
1960	    if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action, mly_cam_poll, "mly", sc,
1961						      device_get_unit(sc->mly_dev),
1962						      &sc->mly_lock,
1963						      sc->mly_controllerinfo->maximum_parallel_commands,
1964						      1, devq)) == NULL) {
1965		return(ENOMEM);
1966	    }
1967	    MLY_LOCK(sc);
1968	    if (xpt_bus_register(sc->mly_cam_sim[chn], sc->mly_dev, chn)) {
1969		MLY_UNLOCK(sc);
1970		mly_printf(sc, "CAM XPT phsyical channel registration failed\n");
1971		return(ENXIO);
1972	    }
1973	    MLY_UNLOCK(sc);
1974	    debug(1, "registered physical channel %d", chn);
1975	}
1976    }
1977
1978    /*
1979     * Register our virtual channels, with bus numbers matching channel numbers.
1980     */
1981    chn = sc->mly_controllerinfo->physical_channels_present;
1982    for (i = 0; i < sc->mly_controllerinfo->virtual_channels_present; i++, chn++) {
1983	if ((sc->mly_cam_sim[chn] = cam_sim_alloc(mly_cam_action, mly_cam_poll, "mly", sc,
1984						  device_get_unit(sc->mly_dev),
1985						  &sc->mly_lock,
1986						  sc->mly_controllerinfo->maximum_parallel_commands,
1987						  0, devq)) == NULL) {
1988	    return(ENOMEM);
1989	}
1990	MLY_LOCK(sc);
1991	if (xpt_bus_register(sc->mly_cam_sim[chn], sc->mly_dev, chn)) {
1992	    MLY_UNLOCK(sc);
1993	    mly_printf(sc, "CAM XPT virtual channel registration failed\n");
1994	    return(ENXIO);
1995	}
1996	MLY_UNLOCK(sc);
1997	debug(1, "registered virtual channel %d", chn);
1998    }
1999
2000    /*
2001     * This is the total number of channels that (might have been) registered with
2002     * CAM.  Some may not have been; check the mly_cam_sim array to be certain.
2003     */
2004    sc->mly_cam_channels = sc->mly_controllerinfo->physical_channels_present +
2005	sc->mly_controllerinfo->virtual_channels_present;
2006
2007    return(0);
2008}
2009
2010/********************************************************************************
2011 * Detach from CAM
2012 */
2013static void
2014mly_cam_detach(struct mly_softc *sc)
2015{
2016    int		i;
2017
2018    debug_called(1);
2019
2020    MLY_LOCK(sc);
2021    for (i = 0; i < sc->mly_cam_channels; i++) {
2022	if (sc->mly_cam_sim[i] != NULL) {
2023	    xpt_bus_deregister(cam_sim_path(sc->mly_cam_sim[i]));
2024	    cam_sim_free(sc->mly_cam_sim[i], 0);
2025	}
2026    }
2027    MLY_UNLOCK(sc);
2028    if (sc->mly_cam_devq != NULL)
2029	cam_simq_free(sc->mly_cam_devq);
2030}
2031
2032/************************************************************************
2033 * Rescan a device.
2034 */
2035static void
2036mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target)
2037{
2038    union ccb	*ccb;
2039
2040    debug_called(1);
2041
2042    if ((ccb = xpt_alloc_ccb()) == NULL) {
2043	mly_printf(sc, "rescan failed (can't allocate CCB)\n");
2044	return;
2045    }
2046    if (xpt_create_path(&ccb->ccb_h.path, NULL,
2047	    cam_sim_path(sc->mly_cam_sim[bus]), target, 0) != CAM_REQ_CMP) {
2048	mly_printf(sc, "rescan failed (can't create path)\n");
2049	xpt_free_ccb(ccb);
2050	return;
2051    }
2052    debug(1, "rescan target %d:%d", bus, target);
2053    xpt_rescan(ccb);
2054}
2055
2056/********************************************************************************
2057 * Handle an action requested by CAM
2058 */
2059static void
2060mly_cam_action(struct cam_sim *sim, union ccb *ccb)
2061{
2062    struct mly_softc	*sc = cam_sim_softc(sim);
2063
2064    debug_called(2);
2065    MLY_ASSERT_LOCKED(sc);
2066
2067    switch (ccb->ccb_h.func_code) {
2068
2069	/* perform SCSI I/O */
2070    case XPT_SCSI_IO:
2071	if (!mly_cam_action_io(sim, (struct ccb_scsiio *)&ccb->csio))
2072	    return;
2073	break;
2074
2075	/* perform geometry calculations */
2076    case XPT_CALC_GEOMETRY:
2077    {
2078	struct ccb_calc_geometry	*ccg = &ccb->ccg;
2079        u_int32_t			secs_per_cylinder;
2080
2081	debug(2, "XPT_CALC_GEOMETRY %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
2082
2083	if (sc->mly_controllerparam->bios_geometry == MLY_BIOSGEOM_8G) {
2084	    ccg->heads = 255;
2085            ccg->secs_per_track = 63;
2086	} else {				/* MLY_BIOSGEOM_2G */
2087	    ccg->heads = 128;
2088            ccg->secs_per_track = 32;
2089	}
2090	secs_per_cylinder = ccg->heads * ccg->secs_per_track;
2091        ccg->cylinders = ccg->volume_size / secs_per_cylinder;
2092        ccb->ccb_h.status = CAM_REQ_CMP;
2093        break;
2094    }
2095
2096	/* handle path attribute inquiry */
2097    case XPT_PATH_INQ:
2098    {
2099	struct ccb_pathinq	*cpi = &ccb->cpi;
2100
2101	debug(2, "XPT_PATH_INQ %d:%d:%d", cam_sim_bus(sim), ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
2102
2103	cpi->version_num = 1;
2104	cpi->hba_inquiry = PI_TAG_ABLE;		/* XXX extra flags for physical channels? */
2105	cpi->target_sprt = 0;
2106	cpi->hba_misc = 0;
2107	cpi->max_target = MLY_MAX_TARGETS - 1;
2108	cpi->max_lun = MLY_MAX_LUNS - 1;
2109	cpi->initiator_id = sc->mly_controllerparam->initiator_id;
2110	strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
2111	strlcpy(cpi->hba_vid, "Mylex", HBA_IDLEN);
2112	strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
2113	cpi->unit_number = cam_sim_unit(sim);
2114	cpi->bus_id = cam_sim_bus(sim);
2115	cpi->base_transfer_speed = 132 * 1024;	/* XXX what to set this to? */
2116	cpi->transport = XPORT_SPI;
2117	cpi->transport_version = 2;
2118	cpi->protocol = PROTO_SCSI;
2119	cpi->protocol_version = SCSI_REV_2;
2120	ccb->ccb_h.status = CAM_REQ_CMP;
2121	break;
2122    }
2123
2124    case XPT_GET_TRAN_SETTINGS:
2125    {
2126	struct ccb_trans_settings	*cts = &ccb->cts;
2127	int				bus, target;
2128	struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi;
2129	struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi;
2130
2131	cts->protocol = PROTO_SCSI;
2132	cts->protocol_version = SCSI_REV_2;
2133	cts->transport = XPORT_SPI;
2134	cts->transport_version = 2;
2135
2136	scsi->flags = 0;
2137	scsi->valid = 0;
2138	spi->flags = 0;
2139	spi->valid = 0;
2140
2141	bus = cam_sim_bus(sim);
2142	target = cts->ccb_h.target_id;
2143	debug(2, "XPT_GET_TRAN_SETTINGS %d:%d", bus, target);
2144	/* logical device? */
2145	if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_LOGICAL) {
2146	    /* nothing special for these */
2147	/* physical device? */
2148	} else if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_PHYSICAL) {
2149	    /* allow CAM to try tagged transactions */
2150	    scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
2151	    scsi->valid |= CTS_SCSI_VALID_TQ;
2152
2153	    /* convert speed (MHz) to usec */
2154	    if (sc->mly_btl[bus][target].mb_speed == 0) {
2155		spi->sync_period = 1000000 / 5;
2156	    } else {
2157		spi->sync_period = 1000000 / sc->mly_btl[bus][target].mb_speed;
2158	    }
2159
2160	    /* convert bus width to CAM internal encoding */
2161	    switch (sc->mly_btl[bus][target].mb_width) {
2162	    case 32:
2163		spi->bus_width = MSG_EXT_WDTR_BUS_32_BIT;
2164		break;
2165	    case 16:
2166		spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
2167		break;
2168	    case 8:
2169	    default:
2170		spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT;
2171		break;
2172	    }
2173	    spi->valid |= CTS_SPI_VALID_SYNC_RATE | CTS_SPI_VALID_BUS_WIDTH;
2174
2175	    /* not a device, bail out */
2176	} else {
2177	    cts->ccb_h.status = CAM_REQ_CMP_ERR;
2178	    break;
2179	}
2180
2181	/* disconnect always OK */
2182	spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
2183	spi->valid |= CTS_SPI_VALID_DISC;
2184
2185	cts->ccb_h.status = CAM_REQ_CMP;
2186	break;
2187    }
2188
2189    default:		/* we can't do this */
2190	debug(2, "unspported func_code = 0x%x", ccb->ccb_h.func_code);
2191	ccb->ccb_h.status = CAM_REQ_INVALID;
2192	break;
2193    }
2194
2195    xpt_done(ccb);
2196}
2197
2198/********************************************************************************
2199 * Handle an I/O operation requested by CAM
2200 */
2201static int
2202mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio)
2203{
2204    struct mly_softc			*sc = cam_sim_softc(sim);
2205    struct mly_command			*mc;
2206    struct mly_command_scsi_small	*ss;
2207    int					bus, target;
2208    int					error;
2209
2210    bus = cam_sim_bus(sim);
2211    target = csio->ccb_h.target_id;
2212
2213    debug(2, "XPT_SCSI_IO %d:%d:%d", bus, target, csio->ccb_h.target_lun);
2214
2215    /* validate bus number */
2216    if (!MLY_BUS_IS_VALID(sc, bus)) {
2217	debug(0, " invalid bus %d", bus);
2218	csio->ccb_h.status = CAM_REQ_CMP_ERR;
2219    }
2220
2221    /*  check for I/O attempt to a protected device */
2222    if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_PROTECTED) {
2223	debug(2, "  device protected");
2224	csio->ccb_h.status = CAM_REQ_CMP_ERR;
2225    }
2226
2227    /* check for I/O attempt to nonexistent device */
2228    if (!(sc->mly_btl[bus][target].mb_flags & (MLY_BTL_LOGICAL | MLY_BTL_PHYSICAL))) {
2229	debug(2, "  device %d:%d does not exist", bus, target);
2230	csio->ccb_h.status = CAM_REQ_CMP_ERR;
2231    }
2232
2233    /* XXX increase if/when we support large SCSI commands */
2234    if (csio->cdb_len > MLY_CMD_SCSI_SMALL_CDB) {
2235	debug(0, "  command too large (%d > %d)", csio->cdb_len, MLY_CMD_SCSI_SMALL_CDB);
2236	csio->ccb_h.status = CAM_REQ_CMP_ERR;
2237    }
2238
2239    /* check that the CDB pointer is not to a physical address */
2240    if ((csio->ccb_h.flags & CAM_CDB_POINTER) && (csio->ccb_h.flags & CAM_CDB_PHYS)) {
2241	debug(0, "  CDB pointer is to physical address");
2242	csio->ccb_h.status = CAM_REQ_CMP_ERR;
2243    }
2244
2245    /* abandon aborted ccbs or those that have failed validation */
2246    if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
2247	debug(2, "abandoning CCB due to abort/validation failure");
2248	return(EINVAL);
2249    }
2250
2251    /*
2252     * Get a command, or push the ccb back to CAM and freeze the queue.
2253     */
2254    if ((error = mly_alloc_command(sc, &mc))) {
2255	xpt_freeze_simq(sim, 1);
2256	csio->ccb_h.status |= CAM_REQUEUE_REQ;
2257	sc->mly_qfrzn_cnt++;
2258	return(error);
2259    }
2260
2261    /* build the command */
2262    mc->mc_data = csio;
2263    mc->mc_length = csio->dxfer_len;
2264    mc->mc_complete = mly_cam_complete;
2265    mc->mc_private = csio;
2266    mc->mc_flags |= MLY_CMD_CCB;
2267    /* XXX This code doesn't set the data direction in mc_flags. */
2268
2269    /* save the bus number in the ccb for later recovery XXX should be a better way */
2270     csio->ccb_h.sim_priv.entries[0].field = bus;
2271
2272    /* build the packet for the controller */
2273    ss = &mc->mc_packet->scsi_small;
2274    ss->opcode = MDACMD_SCSI;
2275    if (csio->ccb_h.flags & CAM_DIS_DISCONNECT)
2276	ss->command_control.disable_disconnect = 1;
2277    if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
2278	ss->command_control.data_direction = MLY_CCB_WRITE;
2279    ss->data_size = csio->dxfer_len;
2280    ss->addr.phys.lun = csio->ccb_h.target_lun;
2281    ss->addr.phys.target = csio->ccb_h.target_id;
2282    ss->addr.phys.channel = bus;
2283    if (csio->ccb_h.timeout < (60 * 1000)) {
2284	ss->timeout.value = csio->ccb_h.timeout / 1000;
2285	ss->timeout.scale = MLY_TIMEOUT_SECONDS;
2286    } else if (csio->ccb_h.timeout < (60 * 60 * 1000)) {
2287	ss->timeout.value = csio->ccb_h.timeout / (60 * 1000);
2288	ss->timeout.scale = MLY_TIMEOUT_MINUTES;
2289    } else {
2290	ss->timeout.value = csio->ccb_h.timeout / (60 * 60 * 1000);	/* overflow? */
2291	ss->timeout.scale = MLY_TIMEOUT_HOURS;
2292    }
2293    ss->maximum_sense_size = csio->sense_len;
2294    ss->cdb_length = csio->cdb_len;
2295    if (csio->ccb_h.flags & CAM_CDB_POINTER) {
2296	bcopy(csio->cdb_io.cdb_ptr, ss->cdb, csio->cdb_len);
2297    } else {
2298	bcopy(csio->cdb_io.cdb_bytes, ss->cdb, csio->cdb_len);
2299    }
2300
2301    /* give the command to the controller */
2302    if ((error = mly_start(mc))) {
2303	xpt_freeze_simq(sim, 1);
2304	csio->ccb_h.status |= CAM_REQUEUE_REQ;
2305	sc->mly_qfrzn_cnt++;
2306	return(error);
2307    }
2308
2309    return(0);
2310}
2311
2312/********************************************************************************
2313 * Check for possibly-completed commands.
2314 */
2315static void
2316mly_cam_poll(struct cam_sim *sim)
2317{
2318    struct mly_softc	*sc = cam_sim_softc(sim);
2319
2320    debug_called(2);
2321
2322    mly_done(sc);
2323}
2324
2325/********************************************************************************
2326 * Handle completion of a command - pass results back through the CCB
2327 */
2328static void
2329mly_cam_complete(struct mly_command *mc)
2330{
2331    struct mly_softc		*sc = mc->mc_sc;
2332    struct ccb_scsiio		*csio = (struct ccb_scsiio *)mc->mc_private;
2333    struct scsi_inquiry_data	*inq = (struct scsi_inquiry_data *)csio->data_ptr;
2334    struct mly_btl		*btl;
2335    u_int8_t			cmd;
2336    int				bus, target;
2337
2338    debug_called(2);
2339
2340    csio->scsi_status = mc->mc_status;
2341    switch(mc->mc_status) {
2342    case SCSI_STATUS_OK:
2343	/*
2344	 * In order to report logical device type and status, we overwrite
2345	 * the result of the INQUIRY command to logical devices.
2346	 */
2347	bus = csio->ccb_h.sim_priv.entries[0].field;
2348	target = csio->ccb_h.target_id;
2349	/* XXX validate bus/target? */
2350	if (sc->mly_btl[bus][target].mb_flags & MLY_BTL_LOGICAL) {
2351	    if (csio->ccb_h.flags & CAM_CDB_POINTER) {
2352		cmd = *csio->cdb_io.cdb_ptr;
2353	    } else {
2354		cmd = csio->cdb_io.cdb_bytes[0];
2355	    }
2356	    if (cmd == INQUIRY) {
2357		btl = &sc->mly_btl[bus][target];
2358		padstr(inq->vendor, mly_describe_code(mly_table_device_type, btl->mb_type), 8);
2359		padstr(inq->product, mly_describe_code(mly_table_device_state, btl->mb_state), 16);
2360		padstr(inq->revision, "", 4);
2361	    }
2362	}
2363
2364	debug(2, "SCSI_STATUS_OK");
2365	csio->ccb_h.status = CAM_REQ_CMP;
2366	break;
2367
2368    case SCSI_STATUS_CHECK_COND:
2369	debug(1, "SCSI_STATUS_CHECK_COND  sense %d  resid %d", mc->mc_sense, mc->mc_resid);
2370	csio->ccb_h.status = CAM_SCSI_STATUS_ERROR;
2371	bzero(&csio->sense_data, SSD_FULL_SIZE);
2372	bcopy(mc->mc_packet, &csio->sense_data, mc->mc_sense);
2373	csio->sense_len = mc->mc_sense;
2374	csio->ccb_h.status |= CAM_AUTOSNS_VALID;
2375	csio->resid = mc->mc_resid;	/* XXX this is a signed value... */
2376	break;
2377
2378    case SCSI_STATUS_BUSY:
2379	debug(1, "SCSI_STATUS_BUSY");
2380	csio->ccb_h.status = CAM_SCSI_BUSY;
2381	break;
2382
2383    default:
2384	debug(1, "unknown status 0x%x", csio->scsi_status);
2385	csio->ccb_h.status = CAM_REQ_CMP_ERR;
2386	break;
2387    }
2388
2389    if (sc->mly_qfrzn_cnt) {
2390	csio->ccb_h.status |= CAM_RELEASE_SIMQ;
2391	sc->mly_qfrzn_cnt--;
2392    }
2393
2394    xpt_done((union ccb *)csio);
2395    mly_release_command(mc);
2396}
2397
2398/********************************************************************************
2399 * Find a peripheral attahed at (bus),(target)
2400 */
2401static struct cam_periph *
2402mly_find_periph(struct mly_softc *sc, int bus, int target)
2403{
2404    struct cam_periph	*periph;
2405    struct cam_path	*path;
2406    int			status;
2407
2408    status = xpt_create_path(&path, NULL, cam_sim_path(sc->mly_cam_sim[bus]), target, 0);
2409    if (status == CAM_REQ_CMP) {
2410	periph = cam_periph_find(path, NULL);
2411	xpt_free_path(path);
2412    } else {
2413	periph = NULL;
2414    }
2415    return(periph);
2416}
2417
2418/********************************************************************************
2419 * Name the device at (bus)(target)
2420 */
2421static int
2422mly_name_device(struct mly_softc *sc, int bus, int target)
2423{
2424    struct cam_periph	*periph;
2425
2426    if ((periph = mly_find_periph(sc, bus, target)) != NULL) {
2427	sprintf(sc->mly_btl[bus][target].mb_name, "%s%d", periph->periph_name, periph->unit_number);
2428	return(0);
2429    }
2430    sc->mly_btl[bus][target].mb_name[0] = 0;
2431    return(ENOENT);
2432}
2433
2434/********************************************************************************
2435 ********************************************************************************
2436                                                                 Hardware Control
2437 ********************************************************************************
2438 ********************************************************************************/
2439
2440/********************************************************************************
2441 * Handshake with the firmware while the card is being initialised.
2442 */
2443static int
2444mly_fwhandshake(struct mly_softc *sc)
2445{
2446    u_int8_t	error, param0, param1;
2447    int		spinup = 0;
2448
2449    debug_called(1);
2450
2451    /* set HM_STSACK and let the firmware initialise */
2452    MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_STSACK);
2453    DELAY(1000);	/* too short? */
2454
2455    /* if HM_STSACK is still true, the controller is initialising */
2456    if (!MLY_IDBR_TRUE(sc, MLY_HM_STSACK))
2457	return(0);
2458    mly_printf(sc, "controller initialisation started\n");
2459
2460    /* spin waiting for initialisation to finish, or for a message to be delivered */
2461    while (MLY_IDBR_TRUE(sc, MLY_HM_STSACK)) {
2462	/* check for a message */
2463	if (MLY_ERROR_VALID(sc)) {
2464	    error = MLY_GET_REG(sc, sc->mly_error_status) & ~MLY_MSG_EMPTY;
2465	    param0 = MLY_GET_REG(sc, sc->mly_command_mailbox);
2466	    param1 = MLY_GET_REG(sc, sc->mly_command_mailbox + 1);
2467
2468	    switch(error) {
2469	    case MLY_MSG_SPINUP:
2470		if (!spinup) {
2471		    mly_printf(sc, "drive spinup in progress\n");
2472		    spinup = 1;			/* only print this once (should print drive being spun?) */
2473		}
2474		break;
2475	    case MLY_MSG_RACE_RECOVERY_FAIL:
2476		mly_printf(sc, "mirror race recovery failed, one or more drives offline\n");
2477		break;
2478	    case MLY_MSG_RACE_IN_PROGRESS:
2479		mly_printf(sc, "mirror race recovery in progress\n");
2480		break;
2481	    case MLY_MSG_RACE_ON_CRITICAL:
2482		mly_printf(sc, "mirror race recovery on a critical drive\n");
2483		break;
2484	    case MLY_MSG_PARITY_ERROR:
2485		mly_printf(sc, "FATAL MEMORY PARITY ERROR\n");
2486		return(ENXIO);
2487	    default:
2488		mly_printf(sc, "unknown initialisation code 0x%x\n", error);
2489	    }
2490	}
2491    }
2492    return(0);
2493}
2494
2495/********************************************************************************
2496 ********************************************************************************
2497                                                        Debugging and Diagnostics
2498 ********************************************************************************
2499 ********************************************************************************/
2500
2501/********************************************************************************
2502 * Print some information about the controller.
2503 */
2504static void
2505mly_describe_controller(struct mly_softc *sc)
2506{
2507    struct mly_ioctl_getcontrollerinfo	*mi = sc->mly_controllerinfo;
2508
2509    mly_printf(sc, "%16s, %d channel%s, firmware %d.%02d-%d-%02d (%02d%02d%02d%02d), %dMB RAM\n",
2510	       mi->controller_name, mi->physical_channels_present, (mi->physical_channels_present) > 1 ? "s" : "",
2511	       mi->fw_major, mi->fw_minor, mi->fw_turn, mi->fw_build,	/* XXX turn encoding? */
2512	       mi->fw_century, mi->fw_year, mi->fw_month, mi->fw_day,
2513	       mi->memory_size);
2514
2515    if (bootverbose) {
2516	mly_printf(sc, "%s %s (%x), %dMHz %d-bit %.16s\n",
2517		   mly_describe_code(mly_table_oemname, mi->oem_information),
2518		   mly_describe_code(mly_table_controllertype, mi->controller_type), mi->controller_type,
2519		   mi->interface_speed, mi->interface_width, mi->interface_name);
2520	mly_printf(sc, "%dMB %dMHz %d-bit %s%s%s, cache %dMB\n",
2521		   mi->memory_size, mi->memory_speed, mi->memory_width,
2522		   mly_describe_code(mly_table_memorytype, mi->memory_type),
2523		   mi->memory_parity ? "+parity": "",mi->memory_ecc ? "+ECC": "",
2524		   mi->cache_size);
2525	mly_printf(sc, "CPU: %s @ %dMHz\n",
2526		   mly_describe_code(mly_table_cputype, mi->cpu[0].type), mi->cpu[0].speed);
2527	if (mi->l2cache_size != 0)
2528	    mly_printf(sc, "%dKB L2 cache\n", mi->l2cache_size);
2529	if (mi->exmemory_size != 0)
2530	    mly_printf(sc, "%dMB %dMHz %d-bit private %s%s%s\n",
2531		       mi->exmemory_size, mi->exmemory_speed, mi->exmemory_width,
2532		       mly_describe_code(mly_table_memorytype, mi->exmemory_type),
2533		       mi->exmemory_parity ? "+parity": "",mi->exmemory_ecc ? "+ECC": "");
2534	mly_printf(sc, "battery backup %s\n", mi->bbu_present ? "present" : "not installed");
2535	mly_printf(sc, "maximum data transfer %d blocks, maximum sg entries/command %d\n",
2536		   mi->maximum_block_count, mi->maximum_sg_entries);
2537	mly_printf(sc, "logical devices present/critical/offline %d/%d/%d\n",
2538		   mi->logical_devices_present, mi->logical_devices_critical, mi->logical_devices_offline);
2539	mly_printf(sc, "physical devices present %d\n",
2540		   mi->physical_devices_present);
2541	mly_printf(sc, "physical disks present/offline %d/%d\n",
2542		   mi->physical_disks_present, mi->physical_disks_offline);
2543	mly_printf(sc, "%d physical channel%s, %d virtual channel%s of %d possible\n",
2544		   mi->physical_channels_present, mi->physical_channels_present == 1 ? "" : "s",
2545		   mi->virtual_channels_present, mi->virtual_channels_present == 1 ? "" : "s",
2546		   mi->virtual_channels_possible);
2547	mly_printf(sc, "%d parallel commands supported\n", mi->maximum_parallel_commands);
2548	mly_printf(sc, "%dMB flash ROM, %d of %d maximum cycles\n",
2549		   mi->flash_size, mi->flash_age, mi->flash_maximum_age);
2550    }
2551}
2552
2553#ifdef MLY_DEBUG
2554/********************************************************************************
2555 * Print some controller state
2556 */
2557static void
2558mly_printstate(struct mly_softc *sc)
2559{
2560    mly_printf(sc, "IDBR %02x  ODBR %02x  ERROR %02x  (%x %x %x)\n",
2561		  MLY_GET_REG(sc, sc->mly_idbr),
2562		  MLY_GET_REG(sc, sc->mly_odbr),
2563		  MLY_GET_REG(sc, sc->mly_error_status),
2564		  sc->mly_idbr,
2565		  sc->mly_odbr,
2566		  sc->mly_error_status);
2567    mly_printf(sc, "IMASK %02x  ISTATUS %02x\n",
2568		  MLY_GET_REG(sc, sc->mly_interrupt_mask),
2569		  MLY_GET_REG(sc, sc->mly_interrupt_status));
2570    mly_printf(sc, "COMMAND %02x %02x %02x %02x %02x %02x %02x %02x\n",
2571		  MLY_GET_REG(sc, sc->mly_command_mailbox),
2572		  MLY_GET_REG(sc, sc->mly_command_mailbox + 1),
2573		  MLY_GET_REG(sc, sc->mly_command_mailbox + 2),
2574		  MLY_GET_REG(sc, sc->mly_command_mailbox + 3),
2575		  MLY_GET_REG(sc, sc->mly_command_mailbox + 4),
2576		  MLY_GET_REG(sc, sc->mly_command_mailbox + 5),
2577		  MLY_GET_REG(sc, sc->mly_command_mailbox + 6),
2578		  MLY_GET_REG(sc, sc->mly_command_mailbox + 7));
2579    mly_printf(sc, "STATUS  %02x %02x %02x %02x %02x %02x %02x %02x\n",
2580		  MLY_GET_REG(sc, sc->mly_status_mailbox),
2581		  MLY_GET_REG(sc, sc->mly_status_mailbox + 1),
2582		  MLY_GET_REG(sc, sc->mly_status_mailbox + 2),
2583		  MLY_GET_REG(sc, sc->mly_status_mailbox + 3),
2584		  MLY_GET_REG(sc, sc->mly_status_mailbox + 4),
2585		  MLY_GET_REG(sc, sc->mly_status_mailbox + 5),
2586		  MLY_GET_REG(sc, sc->mly_status_mailbox + 6),
2587		  MLY_GET_REG(sc, sc->mly_status_mailbox + 7));
2588    mly_printf(sc, "        %04x        %08x\n",
2589		  MLY_GET_REG2(sc, sc->mly_status_mailbox),
2590		  MLY_GET_REG4(sc, sc->mly_status_mailbox + 4));
2591}
2592
2593struct mly_softc	*mly_softc0 = NULL;
2594void
2595mly_printstate0(void)
2596{
2597    if (mly_softc0 != NULL)
2598	mly_printstate(mly_softc0);
2599}
2600
2601/********************************************************************************
2602 * Print a command
2603 */
2604static void
2605mly_print_command(struct mly_command *mc)
2606{
2607    struct mly_softc	*sc = mc->mc_sc;
2608
2609    mly_printf(sc, "COMMAND @ %p\n", mc);
2610    mly_printf(sc, "  slot      %d\n", mc->mc_slot);
2611    mly_printf(sc, "  status    0x%x\n", mc->mc_status);
2612    mly_printf(sc, "  sense len %d\n", mc->mc_sense);
2613    mly_printf(sc, "  resid     %d\n", mc->mc_resid);
2614    mly_printf(sc, "  packet    %p/0x%llx\n", mc->mc_packet, mc->mc_packetphys);
2615    if (mc->mc_packet != NULL)
2616	mly_print_packet(mc);
2617    mly_printf(sc, "  data      %p/%d\n", mc->mc_data, mc->mc_length);
2618    mly_printf(sc, "  flags     %b\n", mc->mc_flags, "\20\1busy\2complete\3slotted\4mapped\5datain\6dataout\n");
2619    mly_printf(sc, "  complete  %p\n", mc->mc_complete);
2620    mly_printf(sc, "  private   %p\n", mc->mc_private);
2621}
2622
2623/********************************************************************************
2624 * Print a command packet
2625 */
2626static void
2627mly_print_packet(struct mly_command *mc)
2628{
2629    struct mly_softc			*sc = mc->mc_sc;
2630    struct mly_command_generic		*ge = (struct mly_command_generic *)mc->mc_packet;
2631    struct mly_command_scsi_small	*ss = (struct mly_command_scsi_small *)mc->mc_packet;
2632    struct mly_command_scsi_large	*sl = (struct mly_command_scsi_large *)mc->mc_packet;
2633    struct mly_command_ioctl		*io = (struct mly_command_ioctl *)mc->mc_packet;
2634    int					transfer;
2635
2636    mly_printf(sc, "   command_id           %d\n", ge->command_id);
2637    mly_printf(sc, "   opcode               %d\n", ge->opcode);
2638    mly_printf(sc, "   command_control      fua %d  dpo %d  est %d  dd %s  nas %d ddis %d\n",
2639		  ge->command_control.force_unit_access,
2640		  ge->command_control.disable_page_out,
2641		  ge->command_control.extended_sg_table,
2642		  (ge->command_control.data_direction == MLY_CCB_WRITE) ? "WRITE" : "READ",
2643		  ge->command_control.no_auto_sense,
2644		  ge->command_control.disable_disconnect);
2645    mly_printf(sc, "   data_size            %d\n", ge->data_size);
2646    mly_printf(sc, "   sense_buffer_address 0x%llx\n", ge->sense_buffer_address);
2647    mly_printf(sc, "   lun                  %d\n", ge->addr.phys.lun);
2648    mly_printf(sc, "   target               %d\n", ge->addr.phys.target);
2649    mly_printf(sc, "   channel              %d\n", ge->addr.phys.channel);
2650    mly_printf(sc, "   logical device       %d\n", ge->addr.log.logdev);
2651    mly_printf(sc, "   controller           %d\n", ge->addr.phys.controller);
2652    mly_printf(sc, "   timeout              %d %s\n",
2653		  ge->timeout.value,
2654		  (ge->timeout.scale == MLY_TIMEOUT_SECONDS) ? "seconds" :
2655		  ((ge->timeout.scale == MLY_TIMEOUT_MINUTES) ? "minutes" : "hours"));
2656    mly_printf(sc, "   maximum_sense_size   %d\n", ge->maximum_sense_size);
2657    switch(ge->opcode) {
2658    case MDACMD_SCSIPT:
2659    case MDACMD_SCSI:
2660	mly_printf(sc, "   cdb length           %d\n", ss->cdb_length);
2661	mly_printf(sc, "   cdb                  %*D\n", ss->cdb_length, ss->cdb, " ");
2662	transfer = 1;
2663	break;
2664    case MDACMD_SCSILC:
2665    case MDACMD_SCSILCPT:
2666	mly_printf(sc, "   cdb length           %d\n", sl->cdb_length);
2667	mly_printf(sc, "   cdb                  0x%llx\n", sl->cdb_physaddr);
2668	transfer = 1;
2669	break;
2670    case MDACMD_IOCTL:
2671	mly_printf(sc, "   sub_ioctl            0x%x\n", io->sub_ioctl);
2672	switch(io->sub_ioctl) {
2673	case MDACIOCTL_SETMEMORYMAILBOX:
2674	    mly_printf(sc, "   health_buffer_size   %d\n",
2675			  io->param.setmemorymailbox.health_buffer_size);
2676	    mly_printf(sc, "   health_buffer_phys   0x%llx\n",
2677			  io->param.setmemorymailbox.health_buffer_physaddr);
2678	    mly_printf(sc, "   command_mailbox      0x%llx\n",
2679			  io->param.setmemorymailbox.command_mailbox_physaddr);
2680	    mly_printf(sc, "   status_mailbox       0x%llx\n",
2681			  io->param.setmemorymailbox.status_mailbox_physaddr);
2682	    transfer = 0;
2683	    break;
2684
2685	case MDACIOCTL_SETREALTIMECLOCK:
2686	case MDACIOCTL_GETHEALTHSTATUS:
2687	case MDACIOCTL_GETCONTROLLERINFO:
2688	case MDACIOCTL_GETLOGDEVINFOVALID:
2689	case MDACIOCTL_GETPHYSDEVINFOVALID:
2690	case MDACIOCTL_GETPHYSDEVSTATISTICS:
2691	case MDACIOCTL_GETLOGDEVSTATISTICS:
2692	case MDACIOCTL_GETCONTROLLERSTATISTICS:
2693	case MDACIOCTL_GETBDT_FOR_SYSDRIVE:
2694	case MDACIOCTL_CREATENEWCONF:
2695	case MDACIOCTL_ADDNEWCONF:
2696	case MDACIOCTL_GETDEVCONFINFO:
2697	case MDACIOCTL_GETFREESPACELIST:
2698	case MDACIOCTL_MORE:
2699	case MDACIOCTL_SETPHYSDEVPARAMETER:
2700	case MDACIOCTL_GETPHYSDEVPARAMETER:
2701	case MDACIOCTL_GETLOGDEVPARAMETER:
2702	case MDACIOCTL_SETLOGDEVPARAMETER:
2703	    mly_printf(sc, "   param                %10D\n", io->param.data.param, " ");
2704	    transfer = 1;
2705	    break;
2706
2707	case MDACIOCTL_GETEVENT:
2708	    mly_printf(sc, "   event                %d\n",
2709		       io->param.getevent.sequence_number_low + ((u_int32_t)io->addr.log.logdev << 16));
2710	    transfer = 1;
2711	    break;
2712
2713	case MDACIOCTL_SETRAIDDEVSTATE:
2714	    mly_printf(sc, "   state                %d\n", io->param.setraiddevstate.state);
2715	    transfer = 0;
2716	    break;
2717
2718	case MDACIOCTL_XLATEPHYSDEVTORAIDDEV:
2719	    mly_printf(sc, "   raid_device          %d\n", io->param.xlatephysdevtoraiddev.raid_device);
2720	    mly_printf(sc, "   controller           %d\n", io->param.xlatephysdevtoraiddev.controller);
2721	    mly_printf(sc, "   channel              %d\n", io->param.xlatephysdevtoraiddev.channel);
2722	    mly_printf(sc, "   target               %d\n", io->param.xlatephysdevtoraiddev.target);
2723	    mly_printf(sc, "   lun                  %d\n", io->param.xlatephysdevtoraiddev.lun);
2724	    transfer = 0;
2725	    break;
2726
2727	case MDACIOCTL_GETGROUPCONFINFO:
2728	    mly_printf(sc, "   group                %d\n", io->param.getgroupconfinfo.group);
2729	    transfer = 1;
2730	    break;
2731
2732	case MDACIOCTL_GET_SUBSYSTEM_DATA:
2733	case MDACIOCTL_SET_SUBSYSTEM_DATA:
2734	case MDACIOCTL_STARTDISOCVERY:
2735	case MDACIOCTL_INITPHYSDEVSTART:
2736	case MDACIOCTL_INITPHYSDEVSTOP:
2737	case MDACIOCTL_INITRAIDDEVSTART:
2738	case MDACIOCTL_INITRAIDDEVSTOP:
2739	case MDACIOCTL_REBUILDRAIDDEVSTART:
2740	case MDACIOCTL_REBUILDRAIDDEVSTOP:
2741	case MDACIOCTL_MAKECONSISTENTDATASTART:
2742	case MDACIOCTL_MAKECONSISTENTDATASTOP:
2743	case MDACIOCTL_CONSISTENCYCHECKSTART:
2744	case MDACIOCTL_CONSISTENCYCHECKSTOP:
2745	case MDACIOCTL_RESETDEVICE:
2746	case MDACIOCTL_FLUSHDEVICEDATA:
2747	case MDACIOCTL_PAUSEDEVICE:
2748	case MDACIOCTL_UNPAUSEDEVICE:
2749	case MDACIOCTL_LOCATEDEVICE:
2750	case MDACIOCTL_SETMASTERSLAVEMODE:
2751	case MDACIOCTL_DELETERAIDDEV:
2752	case MDACIOCTL_REPLACEINTERNALDEV:
2753	case MDACIOCTL_CLEARCONF:
2754	case MDACIOCTL_GETCONTROLLERPARAMETER:
2755	case MDACIOCTL_SETCONTRLLERPARAMETER:
2756	case MDACIOCTL_CLEARCONFSUSPMODE:
2757	case MDACIOCTL_STOREIMAGE:
2758	case MDACIOCTL_READIMAGE:
2759	case MDACIOCTL_FLASHIMAGES:
2760	case MDACIOCTL_RENAMERAIDDEV:
2761	default:			/* no idea what to print */
2762	    transfer = 0;
2763	    break;
2764	}
2765	break;
2766
2767    case MDACMD_IOCTLCHECK:
2768    case MDACMD_MEMCOPY:
2769    default:
2770	transfer = 0;
2771	break;	/* print nothing */
2772    }
2773    if (transfer) {
2774	if (ge->command_control.extended_sg_table) {
2775	    mly_printf(sc, "   sg table             0x%llx/%d\n",
2776			  ge->transfer.indirect.table_physaddr[0], ge->transfer.indirect.entries[0]);
2777	} else {
2778	    mly_printf(sc, "   0000                 0x%llx/%lld\n",
2779			  ge->transfer.direct.sg[0].physaddr, ge->transfer.direct.sg[0].length);
2780	    mly_printf(sc, "   0001                 0x%llx/%lld\n",
2781			  ge->transfer.direct.sg[1].physaddr, ge->transfer.direct.sg[1].length);
2782	}
2783    }
2784}
2785
2786/********************************************************************************
2787 * Panic in a slightly informative fashion
2788 */
2789static void
2790mly_panic(struct mly_softc *sc, char *reason)
2791{
2792    mly_printstate(sc);
2793    panic(reason);
2794}
2795
2796/********************************************************************************
2797 * Print queue statistics, callable from DDB.
2798 */
2799void
2800mly_print_controller(int controller)
2801{
2802    struct mly_softc	*sc;
2803
2804    if ((sc = devclass_get_softc(devclass_find("mly"), controller)) == NULL) {
2805	printf("mly: controller %d invalid\n", controller);
2806    } else {
2807	device_printf(sc->mly_dev, "queue    curr max\n");
2808	device_printf(sc->mly_dev, "free     %04d/%04d\n",
2809		      sc->mly_qstat[MLYQ_FREE].q_length, sc->mly_qstat[MLYQ_FREE].q_max);
2810	device_printf(sc->mly_dev, "busy     %04d/%04d\n",
2811		      sc->mly_qstat[MLYQ_BUSY].q_length, sc->mly_qstat[MLYQ_BUSY].q_max);
2812	device_printf(sc->mly_dev, "complete %04d/%04d\n",
2813		      sc->mly_qstat[MLYQ_COMPLETE].q_length, sc->mly_qstat[MLYQ_COMPLETE].q_max);
2814    }
2815}
2816#endif
2817
2818
2819/********************************************************************************
2820 ********************************************************************************
2821                                                         Control device interface
2822 ********************************************************************************
2823 ********************************************************************************/
2824
2825/********************************************************************************
2826 * Accept an open operation on the control device.
2827 */
2828static int
2829mly_user_open(struct cdev *dev, int flags, int fmt, struct thread *td)
2830{
2831    struct mly_softc	*sc = dev->si_drv1;
2832
2833    MLY_LOCK(sc);
2834    sc->mly_state |= MLY_STATE_OPEN;
2835    MLY_UNLOCK(sc);
2836    return(0);
2837}
2838
2839/********************************************************************************
2840 * Accept the last close on the control device.
2841 */
2842static int
2843mly_user_close(struct cdev *dev, int flags, int fmt, struct thread *td)
2844{
2845    struct mly_softc	*sc = dev->si_drv1;
2846
2847    MLY_LOCK(sc);
2848    sc->mly_state &= ~MLY_STATE_OPEN;
2849    MLY_UNLOCK(sc);
2850    return (0);
2851}
2852
2853/********************************************************************************
2854 * Handle controller-specific control operations.
2855 */
2856static int
2857mly_user_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
2858				int32_t flag, struct thread *td)
2859{
2860    struct mly_softc		*sc = (struct mly_softc *)dev->si_drv1;
2861    struct mly_user_command	*uc = (struct mly_user_command *)addr;
2862    struct mly_user_health	*uh = (struct mly_user_health *)addr;
2863
2864    switch(cmd) {
2865    case MLYIO_COMMAND:
2866	return(mly_user_command(sc, uc));
2867    case MLYIO_HEALTH:
2868	return(mly_user_health(sc, uh));
2869    default:
2870	return(ENOIOCTL);
2871    }
2872}
2873
2874/********************************************************************************
2875 * Execute a command passed in from userspace.
2876 *
2877 * The control structure contains the actual command for the controller, as well
2878 * as the user-space data pointer and data size, and an optional sense buffer
2879 * size/pointer.  On completion, the data size is adjusted to the command
2880 * residual, and the sense buffer size to the size of the returned sense data.
2881 *
2882 */
2883static int
2884mly_user_command(struct mly_softc *sc, struct mly_user_command *uc)
2885{
2886    struct mly_command	*mc;
2887    int			error;
2888
2889    /* allocate a command */
2890    MLY_LOCK(sc);
2891    if (mly_alloc_command(sc, &mc)) {
2892	MLY_UNLOCK(sc);
2893	return (ENOMEM);	/* XXX Linux version will wait for a command */
2894    }
2895    MLY_UNLOCK(sc);
2896
2897    /* handle data size/direction */
2898    mc->mc_length = (uc->DataTransferLength >= 0) ? uc->DataTransferLength : -uc->DataTransferLength;
2899    if (mc->mc_length > 0) {
2900	if ((mc->mc_data = malloc(mc->mc_length, M_DEVBUF, M_NOWAIT)) == NULL) {
2901	    error = ENOMEM;
2902	    goto out;
2903	}
2904    }
2905    if (uc->DataTransferLength > 0) {
2906	mc->mc_flags |= MLY_CMD_DATAIN;
2907	bzero(mc->mc_data, mc->mc_length);
2908    }
2909    if (uc->DataTransferLength < 0) {
2910	mc->mc_flags |= MLY_CMD_DATAOUT;
2911	if ((error = copyin(uc->DataTransferBuffer, mc->mc_data, mc->mc_length)) != 0)
2912	    goto out;
2913    }
2914
2915    /* copy the controller command */
2916    bcopy(&uc->CommandMailbox, mc->mc_packet, sizeof(uc->CommandMailbox));
2917
2918    /* clear command completion handler so that we get woken up */
2919    mc->mc_complete = NULL;
2920
2921    /* execute the command */
2922    MLY_LOCK(sc);
2923    if ((error = mly_start(mc)) != 0) {
2924	MLY_UNLOCK(sc);
2925	goto out;
2926    }
2927    while (!(mc->mc_flags & MLY_CMD_COMPLETE))
2928	mtx_sleep(mc, &sc->mly_lock, PRIBIO, "mlyioctl", 0);
2929    MLY_UNLOCK(sc);
2930
2931    /* return the data to userspace */
2932    if (uc->DataTransferLength > 0)
2933	if ((error = copyout(mc->mc_data, uc->DataTransferBuffer, mc->mc_length)) != 0)
2934	    goto out;
2935
2936    /* return the sense buffer to userspace */
2937    if ((uc->RequestSenseLength > 0) && (mc->mc_sense > 0)) {
2938	if ((error = copyout(mc->mc_packet, uc->RequestSenseBuffer,
2939			     min(uc->RequestSenseLength, mc->mc_sense))) != 0)
2940	    goto out;
2941    }
2942
2943    /* return command results to userspace (caller will copy out) */
2944    uc->DataTransferLength = mc->mc_resid;
2945    uc->RequestSenseLength = min(uc->RequestSenseLength, mc->mc_sense);
2946    uc->CommandStatus = mc->mc_status;
2947    error = 0;
2948
2949 out:
2950    if (mc->mc_data != NULL)
2951	free(mc->mc_data, M_DEVBUF);
2952    MLY_LOCK(sc);
2953    mly_release_command(mc);
2954    MLY_UNLOCK(sc);
2955    return(error);
2956}
2957
2958/********************************************************************************
2959 * Return health status to userspace.  If the health change index in the user
2960 * structure does not match that currently exported by the controller, we
2961 * return the current status immediately.  Otherwise, we block until either
2962 * interrupted or new status is delivered.
2963 */
2964static int
2965mly_user_health(struct mly_softc *sc, struct mly_user_health *uh)
2966{
2967    struct mly_health_status		mh;
2968    int					error;
2969
2970    /* fetch the current health status from userspace */
2971    if ((error = copyin(uh->HealthStatusBuffer, &mh, sizeof(mh))) != 0)
2972	return(error);
2973
2974    /* spin waiting for a status update */
2975    MLY_LOCK(sc);
2976    error = EWOULDBLOCK;
2977    while ((error != 0) && (sc->mly_event_change == mh.change_counter))
2978	error = mtx_sleep(&sc->mly_event_change, &sc->mly_lock, PRIBIO | PCATCH,
2979	    "mlyhealth", 0);
2980    mh = sc->mly_mmbox->mmm_health.status;
2981    MLY_UNLOCK(sc);
2982
2983    /* copy the controller's health status buffer out */
2984    error = copyout(&mh, uh->HealthStatusBuffer, sizeof(mh));
2985    return(error);
2986}
2987
2988#ifdef MLY_DEBUG
2989static void
2990mly_timeout(void *arg)
2991{
2992	struct mly_softc *sc;
2993	struct mly_command *mc;
2994	int deadline;
2995
2996	sc = arg;
2997	MLY_ASSERT_LOCKED(sc);
2998	deadline = time_second - MLY_CMD_TIMEOUT;
2999	TAILQ_FOREACH(mc, &sc->mly_busy, mc_link) {
3000		if ((mc->mc_timestamp < deadline)) {
3001			device_printf(sc->mly_dev,
3002			    "COMMAND %p TIMEOUT AFTER %d SECONDS\n", mc,
3003			    (int)(time_second - mc->mc_timestamp));
3004		}
3005	}
3006
3007	callout_reset(&sc->mly_timeout, MLY_CMD_TIMEOUT * hz, mly_timeout, sc);
3008}
3009#endif
3010