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