Device layer rollup commit.
[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.8 2004/05/19 22:52:47 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     /* allocate the response structure */
1202     if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1203         goto out;
1204     /* get a command slot */
1205     if (mlx_getslot(mc))
1206         goto out;
1207
1208     /* map the command so the controller can see it */
1209     mc->mc_data = result;
1210     mc->mc_length = /*sizeof(struct mlx_eventlog_entry)*/1024;
1211     mlx_mapcmd(mc);
1212
1213     /* build the command to get one entry */
1214     mlx_make_type3(mc, MLX_CMD_LOGOP, MLX_LOGOP_GET, 1, sc->mlx_lastevent, 0, 0, mc->mc_dataphys, 0);
1215     mc->mc_complete = mlx_periodic_eventlog_respond;
1216     mc->mc_private = mc;
1217
1218     /* start the command */
1219     if ((error = mlx_start(mc)) != 0)
1220         goto out;
1221     
1222     error = 0;                  /* success */
1223  out:
1224     if (error != 0) {
1225         if (mc != NULL)
1226             mlx_releasecmd(mc);
1227         if (result != NULL)
1228             free(result, M_DEVBUF);
1229     }
1230 }
1231
1232 /********************************************************************************
1233  * Handle the result of polling for a log message, generate diagnostic output.
1234  * If this wasn't the last message waiting for us, we'll go collect another.
1235  */
1236 static char *mlx_sense_messages[] = {
1237     "because write recovery failed",
1238     "because of SCSI bus reset failure",
1239     "because of double check condition",
1240     "because it was removed",
1241     "because of gross error on SCSI chip",
1242     "because of bad tag returned from drive",
1243     "because of timeout on SCSI command",
1244     "because of reset SCSI command issued from system",
1245     "because busy or parity error count exceeded limit",
1246     "because of 'kill drive' command from system",
1247     "because of selection timeout",
1248     "due to SCSI phase sequence error",
1249     "due to unknown status"
1250 };
1251
1252 static void
1253 mlx_periodic_eventlog_respond(struct mlx_command *mc)
1254 {
1255     struct mlx_softc            *sc = mc->mc_sc;
1256     struct mlx_eventlog_entry   *el = (struct mlx_eventlog_entry *)mc->mc_data;
1257     char                        *reason;
1258
1259     debug_called(1);
1260
1261     sc->mlx_lastevent++;                /* next message... */
1262     if (mc->mc_status == 0) {
1263
1264         /* handle event log message */
1265         switch(el->el_type) {
1266             /*
1267              * This is the only sort of message we understand at the moment.
1268              * The tests here are probably incomplete.
1269              */
1270         case MLX_LOGMSG_SENSE:  /* sense data */
1271             /* Mylex vendor-specific message indicating a drive was killed? */
1272             if ((el->el_sensekey == 9) &&
1273                 (el->el_asc == 0x80)) {
1274                 if (el->el_asq < (sizeof(mlx_sense_messages) / sizeof(mlx_sense_messages[0]))) {
1275                     reason = mlx_sense_messages[el->el_asq];
1276                 } else {
1277                     reason = "for unknown reason";
1278                 }
1279                 device_printf(sc->mlx_dev, "physical drive %d:%d killed %s\n",
1280                               el->el_channel, el->el_target, reason);
1281             }
1282             /* SCSI drive was reset? */
1283             if ((el->el_sensekey == 6) && (el->el_asc == 0x29)) {
1284                 device_printf(sc->mlx_dev, "physical drive %d:%d reset\n", 
1285                               el->el_channel, el->el_target);
1286             }
1287             /* SCSI drive error? */
1288             if (!((el->el_sensekey == 0) ||
1289                   ((el->el_sensekey == 2) &&
1290                    (el->el_asc == 0x04) &&
1291                    ((el->el_asq == 0x01) ||
1292                     (el->el_asq == 0x02))))) {
1293                 device_printf(sc->mlx_dev, "physical drive %d:%d error log: sense = %d asc = %x asq = %x\n",
1294                               el->el_channel, el->el_target, el->el_sensekey, el->el_asc, el->el_asq);
1295                 device_printf(sc->mlx_dev, "  info %4D csi %4D\n", el->el_information, ":", el->el_csi, ":");
1296             }
1297             break;
1298             
1299         default:
1300             device_printf(sc->mlx_dev, "unknown log message type 0x%x\n", el->el_type);
1301             break;
1302         }
1303     } else {
1304         device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
1305         /* give up on all the outstanding messages, as we may have come unsynched */
1306         sc->mlx_lastevent = sc->mlx_currevent;
1307     }
1308         
1309     /* dispose of command and data */
1310     free(mc->mc_data, M_DEVBUF);
1311     mlx_releasecmd(mc);
1312
1313     /* is there another message to obtain? */
1314     if (sc->mlx_lastevent != sc->mlx_currevent) {
1315         mlx_periodic_eventlog_poll(sc);
1316     } else {
1317         /* clear log-busy status */
1318         atomic_clear_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY);
1319     }
1320 }
1321
1322 /********************************************************************************
1323  * Handle check/rebuild operations in progress.
1324  */
1325 static void
1326 mlx_periodic_rebuild(struct mlx_command *mc)
1327 {
1328     struct mlx_softc            *sc = mc->mc_sc;
1329     struct mlx_rebuild_status   *mr = (struct mlx_rebuild_status *)mc->mc_data;
1330
1331     switch(mc->mc_status) {
1332     case 0:                             /* operation running, update stats */
1333         sc->mlx_rebuildstat = *mr;
1334
1335         /* spontaneous rebuild/check? */
1336         if (sc->mlx_background == 0) {
1337             sc->mlx_background = MLX_BACKGROUND_SPONTANEOUS;
1338             device_printf(sc->mlx_dev, "background check/rebuild operation started\n");
1339         }
1340         break;
1341
1342     case 0x0105:                        /* nothing running, finalise stats and report */
1343         switch(sc->mlx_background) {
1344         case MLX_BACKGROUND_CHECK:
1345             device_printf(sc->mlx_dev, "consistency check completed\n");        /* XXX print drive? */
1346             break;
1347         case MLX_BACKGROUND_REBUILD:
1348             device_printf(sc->mlx_dev, "drive rebuild completed\n");    /* XXX print channel/target? */
1349             break;
1350         case MLX_BACKGROUND_SPONTANEOUS:
1351         default:
1352             /* if we have previously been non-idle, report the transition */
1353             if (sc->mlx_rebuildstat.rs_code != MLX_REBUILDSTAT_IDLE) {
1354                 device_printf(sc->mlx_dev, "background check/rebuild operation completed\n");
1355             }
1356         }
1357         sc->mlx_background = 0;
1358         sc->mlx_rebuildstat.rs_code = MLX_REBUILDSTAT_IDLE;
1359         break;
1360     }
1361     free(mc->mc_data, M_DEVBUF);
1362     mlx_releasecmd(mc);
1363 }
1364
1365 /********************************************************************************
1366  ********************************************************************************
1367                                                                     Channel Pause
1368  ********************************************************************************
1369  ********************************************************************************/
1370
1371 /********************************************************************************
1372  * It's time to perform a channel pause action for (sc), either start or stop
1373  * the pause.
1374  */
1375 static void
1376 mlx_pause_action(struct mlx_softc *sc)
1377 {
1378     struct mlx_command  *mc;
1379     int                 failsafe, i, command;
1380
1381     /* What are we doing here? */
1382     if (sc->mlx_pause.mp_when == 0) {
1383         command = MLX_CMD_STARTCHANNEL;
1384         failsafe = 0;
1385
1386     } else {
1387         command = MLX_CMD_STOPCHANNEL;
1388
1389         /* 
1390          * Channels will always start again after the failsafe period, 
1391          * which is specified in multiples of 30 seconds.
1392          * This constrains us to a maximum pause of 450 seconds.
1393          */
1394         failsafe = ((sc->mlx_pause.mp_howlong - time_second) + 5) / 30;
1395         if (failsafe > 0xf) {
1396             failsafe = 0xf;
1397             sc->mlx_pause.mp_howlong = time_second + (0xf * 30) - 5;
1398         }
1399     }
1400
1401     /* build commands for every channel requested */
1402     for (i = 0; i < sc->mlx_enq2->me_actual_channels; i++) {
1403         if ((1 << i) & sc->mlx_pause.mp_which) {
1404
1405             /* get ourselves a command buffer */
1406             if ((mc = mlx_alloccmd(sc)) == NULL)
1407                 goto fail;
1408             /* get a command slot */
1409             mc->mc_flags |= MLX_CMD_PRIORITY;
1410             if (mlx_getslot(mc))
1411                 goto fail;
1412
1413             /* build the command */
1414             mlx_make_type2(mc, command, (failsafe << 4) | i, 0, 0, 0, 0, 0, 0, 0);
1415             mc->mc_complete = mlx_pause_done;
1416             mc->mc_private = sc;                /* XXX not needed */
1417             if (mlx_start(mc))
1418                 goto fail;
1419             /* command submitted OK */
1420             return;
1421     
1422         fail:
1423             device_printf(sc->mlx_dev, "%s failed for channel %d\n", 
1424                           command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", i);
1425             if (mc != NULL)
1426                 mlx_releasecmd(mc);
1427         }
1428     }
1429 }
1430
1431 static void
1432 mlx_pause_done(struct mlx_command *mc)
1433 {
1434     struct mlx_softc    *sc = mc->mc_sc;
1435     int                 command = mc->mc_mailbox[0];
1436     int                 channel = mc->mc_mailbox[2] & 0xf;
1437     
1438     if (mc->mc_status != 0) {
1439         device_printf(sc->mlx_dev, "%s command failed - %s\n", 
1440                       command == MLX_CMD_STOPCHANNEL ? "pause" : "resume", mlx_diagnose_command(mc));
1441     } else if (command == MLX_CMD_STOPCHANNEL) {
1442         device_printf(sc->mlx_dev, "channel %d pausing for %ld seconds\n", 
1443                       channel, (long)(sc->mlx_pause.mp_howlong - time_second));
1444     } else {
1445         device_printf(sc->mlx_dev, "channel %d resuming\n", channel);
1446     }
1447     mlx_releasecmd(mc);
1448 }
1449
1450 /********************************************************************************
1451  ********************************************************************************
1452                                                                Command Submission
1453  ********************************************************************************
1454  ********************************************************************************/
1455
1456 /********************************************************************************
1457  * Perform an Enquiry command using a type-3 command buffer and a return a single
1458  * linear result buffer.  If the completion function is specified, it will
1459  * be called with the completed command (and the result response will not be
1460  * valid until that point).  Otherwise, the command will either be busy-waited
1461  * for (interrupts not enabled), or slept for.
1462  */
1463 static void *
1464 mlx_enquire(struct mlx_softc *sc, int command, size_t bufsize, void (* complete)(struct mlx_command *mc))
1465 {
1466     struct mlx_command  *mc;
1467     void                *result;
1468     int                 error;
1469
1470     debug_called(1);
1471
1472     /* get ourselves a command buffer */
1473     error = 1;
1474     result = NULL;
1475     if ((mc = mlx_alloccmd(sc)) == NULL)
1476         goto out;
1477     /* allocate the response structure */
1478     if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
1479         goto out;
1480     /* get a command slot */
1481     mc->mc_flags |= MLX_CMD_PRIORITY | MLX_CMD_DATAOUT;
1482     if (mlx_getslot(mc))
1483         goto out;
1484
1485     /* map the command so the controller can see it */
1486     mc->mc_data = result;
1487     mc->mc_length = bufsize;
1488     mlx_mapcmd(mc);
1489
1490     /* build an enquiry command */
1491     mlx_make_type2(mc, command, 0, 0, 0, 0, 0, 0, mc->mc_dataphys, 0);
1492
1493     /* do we want a completion callback? */
1494     if (complete != NULL) {
1495         mc->mc_complete = complete;
1496         mc->mc_private = mc;
1497         if ((error = mlx_start(mc)) != 0)
1498             goto out;
1499     } else {
1500         /* run the command in either polled or wait mode */
1501         if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1502             goto out;
1503     
1504         /* command completed OK? */
1505         if (mc->mc_status != 0) {
1506             device_printf(sc->mlx_dev, "ENQUIRY failed - %s\n", mlx_diagnose_command(mc));
1507             goto out;
1508         }
1509     }
1510     error = 0;                  /* success */
1511  out:
1512     /* we got a command, but nobody else will free it */
1513     if ((complete == NULL) && (mc != NULL))
1514         mlx_releasecmd(mc);
1515     /* we got an error, and we allocated a result */
1516     if ((error != 0) && (result != NULL)) {
1517         free(result, M_DEVBUF);
1518         result = NULL;
1519     }
1520     return(result);
1521 }
1522
1523
1524 /********************************************************************************
1525  * Perform a Flush command on the nominated controller.
1526  *
1527  * May be called with interrupts enabled or disabled; will not return until
1528  * the flush operation completes or fails.
1529  */
1530 static int
1531 mlx_flush(struct mlx_softc *sc)
1532 {
1533     struct mlx_command  *mc;
1534     int                 error;
1535
1536     debug_called(1);
1537
1538     /* get ourselves a command buffer */
1539     error = 1;
1540     if ((mc = mlx_alloccmd(sc)) == NULL)
1541         goto out;
1542     /* get a command slot */
1543     if (mlx_getslot(mc))
1544         goto out;
1545
1546     /* build a flush command */
1547     mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1548
1549     /* can't assume that interrupts are going to work here, so play it safe */
1550     if (mlx_poll_command(mc))
1551         goto out;
1552     
1553     /* command completed OK? */
1554     if (mc->mc_status != 0) {
1555         device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1556         goto out;
1557     }
1558     
1559     error = 0;                  /* success */
1560  out:
1561     if (mc != NULL)
1562         mlx_releasecmd(mc);
1563     return(error);
1564 }
1565
1566 /********************************************************************************
1567  * Start a background consistency check on (drive).
1568  *
1569  * May be called with interrupts enabled or disabled; will return as soon as the
1570  * operation has started or been refused.
1571  */
1572 static int
1573 mlx_check(struct mlx_softc *sc, int drive)
1574 {
1575     struct mlx_command  *mc;
1576     int                 error;
1577
1578     debug_called(1);
1579
1580     /* get ourselves a command buffer */
1581     error = 0x10000;
1582     if ((mc = mlx_alloccmd(sc)) == NULL)
1583         goto out;
1584     /* get a command slot */
1585     if (mlx_getslot(mc))
1586         goto out;
1587
1588     /* build a checkasync command, set the "fix it" flag */
1589     mlx_make_type2(mc, MLX_CMD_CHECKASYNC, 0, 0, 0, 0, 0, drive | 0x80, 0, 0);
1590
1591     /* start the command and wait for it to be returned */
1592     if (mlx_wait_command(mc))
1593         goto out;
1594     
1595     /* command completed OK? */
1596     if (mc->mc_status != 0) {   
1597         device_printf(sc->mlx_dev, "CHECK ASYNC failed - %s\n", mlx_diagnose_command(mc));
1598     } else {
1599         device_printf(sc->mlx_sysdrive[drive].ms_disk, "consistency check started");
1600     }
1601     error = mc->mc_status;
1602
1603  out:
1604     if (mc != NULL)
1605         mlx_releasecmd(mc);
1606     return(error);
1607 }
1608
1609 /********************************************************************************
1610  * Start a background rebuild of the physical drive at (channel),(target).
1611  *
1612  * May be called with interrupts enabled or disabled; will return as soon as the
1613  * operation has started or been refused.
1614  */
1615 static int
1616 mlx_rebuild(struct mlx_softc *sc, int channel, int target)
1617 {
1618     struct mlx_command  *mc;
1619     int                 error;
1620
1621     debug_called(1);
1622
1623     /* get ourselves a command buffer */
1624     error = 0x10000;
1625     if ((mc = mlx_alloccmd(sc)) == NULL)
1626         goto out;
1627     /* get a command slot */
1628     if (mlx_getslot(mc))
1629         goto out;
1630
1631     /* build a checkasync command, set the "fix it" flag */
1632     mlx_make_type2(mc, MLX_CMD_REBUILDASYNC, channel, target, 0, 0, 0, 0, 0, 0);
1633
1634     /* start the command and wait for it to be returned */
1635     if (mlx_wait_command(mc))
1636         goto out;
1637     
1638     /* command completed OK? */
1639     if (mc->mc_status != 0) {   
1640         device_printf(sc->mlx_dev, "REBUILD ASYNC failed - %s\n", mlx_diagnose_command(mc));
1641     } else {
1642         device_printf(sc->mlx_dev, "drive rebuild started for %d:%d\n", channel, target);
1643     }
1644     error = mc->mc_status;
1645
1646  out:
1647     if (mc != NULL)
1648         mlx_releasecmd(mc);
1649     return(error);
1650 }
1651
1652 /********************************************************************************
1653  * Run the command (mc) and return when it completes.
1654  *
1655  * Interrupts need to be enabled; returns nonzero on error.
1656  */
1657 static int
1658 mlx_wait_command(struct mlx_command *mc)
1659 {
1660     struct mlx_softc    *sc = mc->mc_sc;
1661     int                 error, count;
1662
1663     debug_called(1);
1664
1665     mc->mc_complete = NULL;
1666     mc->mc_private = mc;                /* wake us when you're done */
1667     if ((error = mlx_start(mc)) != 0)
1668         return(error);
1669
1670     count = 0;
1671     /* XXX better timeout? */
1672     while ((mc->mc_status == MLX_STATUS_BUSY) && (count < 30)) {
1673         tsleep(mc->mc_private, PCATCH, "mlxwcmd", hz);
1674     }
1675
1676     if (mc->mc_status != 0) {
1677         device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1678         return(EIO);
1679     }
1680     return(0);
1681 }
1682
1683
1684 /********************************************************************************
1685  * Start the command (mc) and busy-wait for it to complete.
1686  *
1687  * Should only be used when interrupts can't be relied upon. Returns 0 on 
1688  * success, nonzero on error.
1689  * Successfully completed commands are dequeued.
1690  */
1691 static int
1692 mlx_poll_command(struct mlx_command *mc)
1693 {
1694     struct mlx_softc    *sc = mc->mc_sc;
1695     int                 error, count, s;
1696
1697     debug_called(1);
1698
1699     mc->mc_complete = NULL;
1700     mc->mc_private = NULL;      /* we will poll for it */
1701     if ((error = mlx_start(mc)) != 0)
1702         return(error);
1703     
1704     count = 0;
1705     do {
1706         /* poll for completion */
1707         mlx_done(mc->mc_sc);
1708         
1709     } while ((mc->mc_status == MLX_STATUS_BUSY) && (count++ < 15000000));
1710     if (mc->mc_status != MLX_STATUS_BUSY) {
1711         s = splbio();
1712         TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1713         splx(s);
1714         return(0);
1715     }
1716     device_printf(sc->mlx_dev, "command failed - %s\n", mlx_diagnose_command(mc));
1717     return(EIO);
1718 }
1719
1720 /********************************************************************************
1721  * Pull as much work off the softc's work queue as possible and give it to the
1722  * controller.  Leave a couple of slots free for emergencies.
1723  *
1724  * Must be called at splbio or in an equivalent fashion that prevents 
1725  * reentry or activity on the bioq.
1726  */
1727 static void
1728 mlx_startio(struct mlx_softc *sc)
1729 {
1730     struct mlx_command  *mc;
1731     struct mlxd_softc   *mlxd;
1732     mlx_bio             *bp;
1733     int                 blkcount;
1734     int                 driveno;
1735     int                 cmd;
1736     int                 s;
1737
1738     /* avoid reentrancy */
1739     if (mlx_lock_tas(sc, MLX_LOCK_STARTING))
1740         return;
1741
1742     /* spin until something prevents us from doing any work */
1743     s = splbio();
1744     for (;;) {
1745
1746         /* see if there's work to be done */
1747         if ((bp = MLX_BIO_QFIRST(sc->mlx_bioq)) == NULL)
1748             break;
1749         /* get a command */
1750         if ((mc = mlx_alloccmd(sc)) == NULL)
1751             break;
1752         /* get a slot for the command */
1753         if (mlx_getslot(mc) != 0) {
1754             mlx_releasecmd(mc);
1755             break;
1756         }
1757         /* get the buf containing our work */
1758         MLX_BIO_QREMOVE(sc->mlx_bioq, bp);
1759         sc->mlx_waitbufs--;
1760         splx(s);
1761         
1762         /* connect the buf to the command */
1763         mc->mc_complete = mlx_completeio;
1764         mc->mc_private = bp;
1765         mc->mc_data = MLX_BIO_DATA(bp);
1766         mc->mc_length = MLX_BIO_LENGTH(bp);
1767         if (MLX_BIO_IS_READ(bp)) {
1768             mc->mc_flags |= MLX_CMD_DATAIN;
1769             cmd = MLX_CMD_READSG;
1770         } else {
1771             mc->mc_flags |= MLX_CMD_DATAOUT;
1772             cmd = MLX_CMD_WRITESG;
1773         }
1774         
1775         /* map the command so the controller can work with it */
1776         mlx_mapcmd(mc);
1777         
1778         /* build a suitable I/O command (assumes 512-byte rounded transfers) */
1779         mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp);
1780         driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1781         blkcount = (MLX_BIO_LENGTH(bp) + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1782
1783         if ((MLX_BIO_LBA(bp) + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1784             device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n", 
1785                           MLX_BIO_LBA(bp), blkcount, sc->mlx_sysdrive[driveno].ms_size);
1786
1787         /*
1788          * Build the I/O command.  Note that the SG list type bits are set to zero,
1789          * denoting the format of SG list that we are using.
1790          */
1791         if (sc->mlx_iftype == MLX_IFTYPE_2) {
1792             mlx_make_type1(mc, (cmd == MLX_CMD_WRITESG) ? MLX_CMD_WRITESG_OLD : MLX_CMD_READSG_OLD,
1793                            blkcount & 0xff,                             /* xfer length low byte */
1794                            MLX_BIO_LBA(bp),                             /* physical block number */
1795                            driveno,                                     /* target drive number */
1796                            mc->mc_sgphys,                               /* location of SG list */
1797                            mc->mc_nsgent & 0x3f);                       /* size of SG list (top 3 bits clear) */
1798         } else {
1799             mlx_make_type5(mc, cmd, 
1800                            blkcount & 0xff,                             /* xfer length low byte */
1801                            (driveno << 3) | ((blkcount >> 8) & 0x07),   /* target and length high 3 bits */
1802                            MLX_BIO_LBA(bp),                             /* physical block number */
1803                            mc->mc_sgphys,                               /* location of SG list */
1804                            mc->mc_nsgent & 0x3f);                       /* size of SG list (top 3 bits clear) */
1805         }
1806         
1807         /* try to give command to controller */
1808         if (mlx_start(mc) != 0) {
1809             /* fail the command */
1810             mc->mc_status = MLX_STATUS_WEDGED;
1811             mlx_completeio(mc);
1812         }
1813         s = splbio();
1814     }
1815     splx(s);
1816     mlx_lock_clr(sc, MLX_LOCK_STARTING);
1817 }
1818
1819 /********************************************************************************
1820  * Handle completion of an I/O command.
1821  */
1822 static void
1823 mlx_completeio(struct mlx_command *mc)
1824 {
1825     struct mlx_softc    *sc = mc->mc_sc;
1826     mlx_bio             *bp = (mlx_bio *)mc->mc_private;
1827     struct mlxd_softc   *mlxd = (struct mlxd_softc *)MLX_BIO_SOFTC(bp);
1828     
1829     if (mc->mc_status != MLX_STATUS_OK) {       /* could be more verbose here? */
1830         MLX_BIO_SET_ERROR(bp, EIO);
1831
1832         switch(mc->mc_status) {
1833         case MLX_STATUS_RDWROFFLINE:            /* system drive has gone offline */
1834             device_printf(mlxd->mlxd_dev, "drive offline\n");
1835             /* should signal this with a return code */
1836             mlxd->mlxd_drive->ms_state = MLX_SYSD_OFFLINE;
1837             break;
1838
1839         default:                                /* other I/O error */
1840             device_printf(sc->mlx_dev, "I/O error - %s\n", mlx_diagnose_command(mc));
1841 #if 0
1842             device_printf(sc->mlx_dev, "  b_bcount %ld  blkcount %ld  b_pblkno %d\n", 
1843                           MLX_BIO_LENGTH(bp), MLX_BIO_LENGTH(bp) / MLX_BLKSIZE, MLX_BIO_LBA(bp));
1844             device_printf(sc->mlx_dev, "  %13D\n", mc->mc_mailbox, " ");
1845 #endif
1846             break;
1847         }
1848     }
1849     mlx_releasecmd(mc);
1850     mlxd_intr(bp);
1851 }
1852
1853 /********************************************************************************
1854  * Take a command from user-space and try to run it.
1855  *
1856  * XXX Note that this can't perform very much in the way of error checking, and
1857  *     as such, applications _must_ be considered trustworthy.
1858  * XXX Commands using S/G for data are not supported.
1859  */
1860 static int
1861 mlx_user_command(struct mlx_softc *sc, struct mlx_usercommand *mu)
1862 {
1863     struct mlx_command  *mc;
1864     struct mlx_dcdb     *dcdb;
1865     void                *kbuf;
1866     int                 error;
1867     
1868     debug_called(0);
1869     
1870     kbuf = NULL;
1871     mc = NULL;
1872     dcdb = NULL;
1873     error = ENOMEM;
1874
1875     /* get ourselves a command and copy in from user space */
1876     if ((mc = mlx_alloccmd(sc)) == NULL)
1877         goto out;
1878     bcopy(mu->mu_command, mc->mc_mailbox, sizeof(mc->mc_mailbox));
1879     debug(0, "got command buffer");
1880
1881     /* if we need a buffer for data transfer, allocate one and copy in its initial contents */
1882     if (mu->mu_datasize > 0) {
1883         if (mu->mu_datasize > MAXPHYS)
1884             return (EINVAL);
1885         if (((kbuf = malloc(mu->mu_datasize, M_DEVBUF, M_WAITOK)) == NULL) ||
1886             (error = copyin(mu->mu_buf, kbuf, mu->mu_datasize)))
1887             goto out;
1888         debug(0, "got kernel buffer");
1889     }
1890
1891     /* get a command slot */
1892     if (mlx_getslot(mc))
1893         goto out;
1894     debug(0, "got a slot");
1895     
1896     /* map the command so the controller can see it */
1897     mc->mc_data = kbuf;
1898     mc->mc_length = mu->mu_datasize;
1899     mlx_mapcmd(mc);
1900     debug(0, "mapped");
1901
1902     /* 
1903      * If this is a passthrough SCSI command, the DCDB is packed at the 
1904      * beginning of the data area.  Fix up the DCDB to point to the correct physical
1905      * address and override any bufptr supplied by the caller since we know
1906      * what it's meant to be.
1907      */
1908     if (mc->mc_mailbox[0] == MLX_CMD_DIRECT_CDB) {
1909         dcdb = (struct mlx_dcdb *)kbuf;
1910         dcdb->dcdb_physaddr = mc->mc_dataphys + sizeof(*dcdb);
1911         mu->mu_bufptr = 8;
1912     }
1913     
1914     /* 
1915      * If there's a data buffer, fix up the command's buffer pointer.
1916      */
1917     if (mu->mu_datasize > 0) {
1918
1919         /* range check the pointer to physical buffer address */
1920         if ((mu->mu_bufptr < 0) || (mu->mu_bufptr > (sizeof(mu->mu_command) - sizeof(u_int32_t)))) {
1921             error = EINVAL;
1922             goto out;
1923         }
1924         mc->mc_mailbox[mu->mu_bufptr    ] =  mc->mc_dataphys        & 0xff;
1925         mc->mc_mailbox[mu->mu_bufptr + 1] = (mc->mc_dataphys >> 8)  & 0xff;
1926         mc->mc_mailbox[mu->mu_bufptr + 2] = (mc->mc_dataphys >> 16) & 0xff;
1927         mc->mc_mailbox[mu->mu_bufptr + 3] = (mc->mc_dataphys >> 24) & 0xff;
1928     }
1929     debug(0, "command fixup");
1930
1931     /* submit the command and wait */
1932     if ((error = mlx_wait_command(mc)) != 0)
1933         goto out;
1934
1935     /* copy out status and data */
1936     mu->mu_status = mc->mc_status;
1937     if ((mu->mu_datasize > 0) && ((error = copyout(kbuf, mu->mu_buf, mu->mu_datasize))))
1938         goto out;
1939     error = 0;
1940     
1941  out:
1942     mlx_releasecmd(mc);
1943     if (kbuf != NULL)
1944         free(kbuf, M_DEVBUF);
1945     return(error);
1946 }
1947
1948 /********************************************************************************
1949  ********************************************************************************
1950                                                         Command I/O to Controller
1951  ********************************************************************************
1952  ********************************************************************************/
1953
1954 /********************************************************************************
1955  * Find a free command slot for (mc).
1956  *
1957  * Don't hand out a slot to a normal-priority command unless there are at least
1958  * 4 slots free for priority commands.
1959  */
1960 static int
1961 mlx_getslot(struct mlx_command *mc)
1962 {
1963     struct mlx_softc    *sc = mc->mc_sc;
1964     int                 s, slot, limit;
1965
1966     debug_called(1);
1967
1968     /* 
1969      * Enforce slot-usage limit, if we have the required information.
1970      */
1971     if (sc->mlx_enq2 != NULL) {
1972         limit = sc->mlx_enq2->me_max_commands;
1973     } else {
1974         limit = 2;
1975     }
1976     if (sc->mlx_busycmds >= ((mc->mc_flags & MLX_CMD_PRIORITY) ? limit : limit - 4))
1977         return(EBUSY);
1978
1979     /* 
1980      * Allocate an outstanding command slot 
1981      *
1982      * XXX linear search is slow
1983      */
1984     s = splbio();
1985     for (slot = 0; slot < limit; slot++) {
1986         debug(2, "try slot %d", slot);
1987         if (sc->mlx_busycmd[slot] == NULL)
1988             break;
1989     }
1990     if (slot < limit) {
1991         sc->mlx_busycmd[slot] = mc;
1992         sc->mlx_busycmds++;
1993     }
1994     splx(s);
1995
1996     /* out of slots? */
1997     if (slot >= limit)
1998         return(EBUSY);
1999
2000     debug(2, "got slot %d", slot);
2001     mc->mc_slot = slot;
2002     return(0);
2003 }
2004
2005 /********************************************************************************
2006  * Map/unmap (mc)'s data in the controller's addressable space.
2007  */
2008 static void
2009 mlx_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
2010 {
2011     struct mlx_command  *mc = (struct mlx_command *)arg;
2012     struct mlx_softc    *sc = mc->mc_sc;
2013     struct mlx_sgentry  *sg;
2014     int                 i;
2015
2016     debug_called(1);
2017
2018     /* XXX should be unnecessary */
2019     if (sc->mlx_enq2 && (nsegments > sc->mlx_enq2->me_max_sg))
2020         panic("MLX: too many s/g segments (%d, max %d)", nsegments, sc->mlx_enq2->me_max_sg);
2021
2022     /* get base address of s/g table */
2023     sg = sc->mlx_sgtable + (mc->mc_slot * MLX_NSEG);
2024
2025     /* save s/g table information in command */
2026     mc->mc_nsgent = nsegments;
2027     mc->mc_sgphys = sc->mlx_sgbusaddr + (mc->mc_slot * MLX_NSEG * sizeof(struct mlx_sgentry));
2028     mc->mc_dataphys = segs[0].ds_addr;
2029
2030     /* populate s/g table */
2031     for (i = 0; i < nsegments; i++, sg++) {
2032         sg->sg_addr = segs[i].ds_addr;
2033         sg->sg_count = segs[i].ds_len;
2034     }
2035 }
2036
2037 static void
2038 mlx_mapcmd(struct mlx_command *mc)
2039 {
2040     struct mlx_softc    *sc = mc->mc_sc;
2041
2042     debug_called(1);
2043
2044     /* if the command involves data at all */
2045     if (mc->mc_data != NULL) {
2046         
2047         /* map the data buffer into bus space and build the s/g list */
2048         bus_dmamap_load(sc->mlx_buffer_dmat, mc->mc_dmamap, mc->mc_data, mc->mc_length, 
2049                         mlx_setup_dmamap, mc, 0);
2050         if (mc->mc_flags & MLX_CMD_DATAIN)
2051             bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREREAD);
2052         if (mc->mc_flags & MLX_CMD_DATAOUT)
2053             bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_PREWRITE);
2054     }
2055 }
2056
2057 static void
2058 mlx_unmapcmd(struct mlx_command *mc)
2059 {
2060     struct mlx_softc    *sc = mc->mc_sc;
2061
2062     debug_called(1);
2063
2064     /* if the command involved data at all */
2065     if (mc->mc_data != NULL) {
2066         
2067         if (mc->mc_flags & MLX_CMD_DATAIN)
2068             bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTREAD);
2069         if (mc->mc_flags & MLX_CMD_DATAOUT)
2070             bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
2071
2072         bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap); 
2073     }
2074 }
2075
2076 /********************************************************************************
2077  * Try to deliver (mc) to the controller.
2078  *
2079  * Can be called at any interrupt level, with or without interrupts enabled.
2080  */
2081 static int
2082 mlx_start(struct mlx_command *mc)
2083 {
2084     struct mlx_softc    *sc = mc->mc_sc;
2085     int                 i, s, done;
2086
2087     debug_called(1);
2088
2089     /* save the slot number as ident so we can handle this command when complete */
2090     mc->mc_mailbox[0x1] = mc->mc_slot;
2091
2092     /* mark the command as currently being processed */
2093     mc->mc_status = MLX_STATUS_BUSY;
2094
2095     /* set a default 60-second timeout  XXX tunable?  XXX not currently used */
2096     mc->mc_timeout = time_second + 60;
2097     
2098     /* spin waiting for the mailbox */
2099     for (i = 100000, done = 0; (i > 0) && !done; i--) {
2100         s = splbio();
2101         if (sc->mlx_tryqueue(sc, mc)) {
2102             done = 1;
2103             /* move command to work queue */
2104             TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
2105         }
2106         splx(s);        /* drop spl to allow completion interrupts */
2107     }
2108
2109     /* command is enqueued */
2110     if (done)
2111         return(0);
2112
2113     /* 
2114      * We couldn't get the controller to take the command.  Revoke the slot
2115      * that the command was given and return it with a bad status.
2116      */
2117     sc->mlx_busycmd[mc->mc_slot] = NULL;
2118     device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
2119     mc->mc_status = MLX_STATUS_WEDGED;
2120     mlx_complete(sc);
2121     return(EIO);
2122 }
2123
2124 /********************************************************************************
2125  * Poll the controller (sc) for completed commands.
2126  * Update command status and free slots for reuse.  If any slots were freed,
2127  * new commands may be posted.
2128  *
2129  * Returns nonzero if one or more commands were completed.
2130  */
2131 static int
2132 mlx_done(struct mlx_softc *sc)
2133 {
2134     struct mlx_command  *mc;
2135     int                 s, result;
2136     u_int8_t            slot;
2137     u_int16_t           status;
2138     
2139     debug_called(2);
2140
2141     result = 0;
2142
2143     /* loop collecting completed commands */
2144     s = splbio();
2145     for (;;) {
2146         /* poll for a completed command's identifier and status */
2147         if (sc->mlx_findcomplete(sc, &slot, &status)) {
2148             result = 1;
2149             mc = sc->mlx_busycmd[slot];                 /* find command */
2150             if (mc != NULL) {                           /* paranoia */
2151                 if (mc->mc_status == MLX_STATUS_BUSY) {
2152                     mc->mc_status = status;             /* save status */
2153
2154                     /* free slot for reuse */
2155                     sc->mlx_busycmd[slot] = NULL;
2156                     sc->mlx_busycmds--;
2157                 } else {
2158                     device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
2159                 }
2160             } else {
2161                 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
2162             }
2163         } else {
2164             break;
2165         }
2166     }
2167     splx(s);
2168
2169     /* if we've completed any commands, try posting some more */
2170     if (result)
2171         mlx_startio(sc);
2172
2173     /* handle completion and timeouts */
2174     mlx_complete(sc);
2175
2176     return(result);
2177 }
2178
2179 /********************************************************************************
2180  * Perform post-completion processing for commands on (sc).
2181  */
2182 static void
2183 mlx_complete(struct mlx_softc *sc) 
2184 {
2185     struct mlx_command  *mc, *nc;
2186     int                 s, count;
2187     
2188     debug_called(2);
2189
2190     /* avoid reentrancy  XXX might want to signal and request a restart */
2191     if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
2192         return;
2193
2194     s = splbio();
2195     count = 0;
2196
2197     /* scan the list of busy/done commands */
2198     mc = TAILQ_FIRST(&sc->mlx_work);
2199     while (mc != NULL) {
2200         nc = TAILQ_NEXT(mc, mc_link);
2201
2202         /* Command has been completed in some fashion */
2203         if (mc->mc_status != MLX_STATUS_BUSY) {
2204         
2205             /* unmap the command's data buffer */
2206             mlx_unmapcmd(mc);
2207             /*
2208              * Does the command have a completion handler?
2209              */
2210             if (mc->mc_complete != NULL) {
2211                 /* remove from list and give to handler */
2212                 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2213                 mc->mc_complete(mc);
2214
2215                 /* 
2216                  * Is there a sleeper waiting on this command?
2217                  */
2218             } else if (mc->mc_private != NULL) {        /* sleeping caller wants to know about it */
2219
2220                 /* remove from list and wake up sleeper */
2221                 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2222                 wakeup_one(mc->mc_private);
2223
2224                 /*
2225                  * Leave the command for a caller that's polling for it.
2226                  */
2227             } else {
2228             }
2229         }
2230         mc = nc;
2231     }
2232     splx(s);
2233
2234     mlx_lock_clr(sc, MLX_LOCK_COMPLETING);
2235 }
2236
2237 /********************************************************************************
2238  ********************************************************************************
2239                                                         Command Buffer Management
2240  ********************************************************************************
2241  ********************************************************************************/
2242
2243 /********************************************************************************
2244  * Get a new command buffer.
2245  *
2246  * This may return NULL in low-memory cases.
2247  *
2248  * Note that using malloc() is expensive (the command buffer is << 1 page) but
2249  * necessary if we are to be a loadable module before the zone allocator is fixed.
2250  *
2251  * If possible, we recycle a command buffer that's been used before.
2252  *
2253  * XXX Note that command buffers are not cleaned out - it is the caller's 
2254  *     responsibility to ensure that all required fields are filled in before
2255  *     using a buffer.
2256  */
2257 static struct mlx_command *
2258 mlx_alloccmd(struct mlx_softc *sc)
2259 {
2260     struct mlx_command  *mc;
2261     int                 error;
2262     int                 s;
2263
2264     debug_called(1);
2265
2266     s = splbio();
2267     if ((mc = TAILQ_FIRST(&sc->mlx_freecmds)) != NULL)
2268         TAILQ_REMOVE(&sc->mlx_freecmds, mc, mc_link);
2269     splx(s);
2270
2271     /* allocate a new command buffer? */
2272     if (mc == NULL) {
2273         mc = (struct mlx_command *)malloc(sizeof(*mc), M_DEVBUF, M_NOWAIT | M_ZERO);
2274         if (mc != NULL) {
2275             mc->mc_sc = sc;
2276             error = bus_dmamap_create(sc->mlx_buffer_dmat, 0, &mc->mc_dmamap);
2277             if (error) {
2278                 free(mc, M_DEVBUF);
2279                 return(NULL);
2280             }
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 }