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