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