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