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