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