]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/amr/amr.c
This commit was generated by cvs2svn to compensate for changes in r98524,
[FreeBSD/FreeBSD.git] / sys / dev / amr / amr.c
1 /*-
2  * Copyright (c) 1999,2000 Michael Smith
3  * Copyright (c) 2000 BSDi
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *      $FreeBSD$
28  */
29
30 /*
31  * Driver for the AMI MegaRaid family of controllers.
32  */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/malloc.h>
37 #include <sys/kernel.h>
38
39 #include <dev/amr/amr_compat.h>
40 #include <sys/bus.h>
41 #include <sys/conf.h>
42 #include <sys/devicestat.h>
43 #include <sys/disk.h>
44 #include <sys/stat.h>
45
46 #include <machine/bus_memio.h>
47 #include <machine/bus_pio.h>
48 #include <machine/bus.h>
49 #include <machine/resource.h>
50 #include <sys/rman.h>
51
52 #include <pci/pcireg.h>
53 #include <pci/pcivar.h>
54
55 #include <dev/amr/amrio.h>
56 #include <dev/amr/amrreg.h>
57 #include <dev/amr/amrvar.h>
58 #define AMR_DEFINE_TABLES
59 #include <dev/amr/amr_tables.h>
60
61 #define AMR_CDEV_MAJOR  132
62
63 static d_open_t         amr_open;
64 static d_close_t        amr_close;
65 static d_ioctl_t        amr_ioctl;
66
67 static struct cdevsw amr_cdevsw = {
68                 /* open */      amr_open,
69                 /* close */     amr_close,
70                 /* read */      noread,
71                 /* write */     nowrite,
72                 /* ioctl */     amr_ioctl,
73                 /* poll */      nopoll,
74                 /* mmap */      nommap,
75                 /* strategy */  nostrategy,
76                 /* name */      "amr",
77                 /* maj */       AMR_CDEV_MAJOR,
78                 /* dump */      nodump,
79                 /* psize */     nopsize,
80                 /* flags */     0,
81 };
82
83 /*
84  * Initialisation, bus interface.
85  */
86 static void     amr_startup(void *arg);
87
88 /*
89  * Command wrappers
90  */
91 static int      amr_query_controller(struct amr_softc *sc);
92 static void     *amr_enquiry(struct amr_softc *sc, size_t bufsize, 
93                              u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual);
94 static void     amr_completeio(struct amr_command *ac);
95
96 /*
97  * Command buffer allocation.
98  */
99 static void     amr_alloccmd_cluster(struct amr_softc *sc);
100 static void     amr_freecmd_cluster(struct amr_command_cluster *acc);
101
102 /*
103  * Command processing.
104  */
105 static int      amr_bio_command(struct amr_softc *sc, struct amr_command **acp);
106 static int      amr_wait_command(struct amr_command *ac);
107 static int      amr_poll_command(struct amr_command *ac);
108 static int      amr_getslot(struct amr_command *ac);
109 static void     amr_mapcmd(struct amr_command *ac);
110 static void     amr_unmapcmd(struct amr_command *ac);
111 static int      amr_start(struct amr_command *ac);
112 static void     amr_complete(void *context, int pending);
113
114 /*
115  * Status monitoring
116  */
117 static void     amr_periodic(void *data);
118
119 /*
120  * Interface-specific shims
121  */
122 static int      amr_quartz_submit_command(struct amr_softc *sc);
123 static int      amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
124
125 static int      amr_std_submit_command(struct amr_softc *sc);
126 static int      amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
127 static void     amr_std_attach_mailbox(struct amr_softc *sc);
128
129 #ifdef AMR_BOARD_INIT
130 static int      amr_quartz_init(struct amr_softc *sc);
131 static int      amr_std_init(struct amr_softc *sc);
132 #endif
133
134 /*
135  * Debugging
136  */
137 static void     amr_describe_controller(struct amr_softc *sc);
138 #ifdef AMR_DEBUG
139 static void     amr_printcommand(struct amr_command *ac);
140 #endif
141
142 /********************************************************************************
143  ********************************************************************************
144                                                                       Inline Glue
145  ********************************************************************************
146  ********************************************************************************/
147
148 /********************************************************************************
149  ********************************************************************************
150                                                                 Public Interfaces
151  ********************************************************************************
152  ********************************************************************************/
153
154 /********************************************************************************
155  * Initialise the controller and softc.
156  */
157 int
158 amr_attach(struct amr_softc *sc)
159 {
160
161     debug_called(1);
162
163     /*
164      * Initialise per-controller queues.
165      */
166     TAILQ_INIT(&sc->amr_completed);
167     TAILQ_INIT(&sc->amr_freecmds);
168     TAILQ_INIT(&sc->amr_cmd_clusters);
169     TAILQ_INIT(&sc->amr_ready);
170     bioq_init(&sc->amr_bioq);
171
172 #if __FreeBSD_version >= 500005
173     /*
174      * Initialise command-completion task.
175      */
176     TASK_INIT(&sc->amr_task_complete, 0, amr_complete, sc);
177 #endif
178
179     debug(2, "queue init done");
180
181     /*
182      * Configure for this controller type.
183      */
184     if (AMR_IS_QUARTZ(sc)) {
185         sc->amr_submit_command = amr_quartz_submit_command;
186         sc->amr_get_work       = amr_quartz_get_work;
187     } else {
188         sc->amr_submit_command = amr_std_submit_command;
189         sc->amr_get_work       = amr_std_get_work;
190         amr_std_attach_mailbox(sc);;
191     }
192
193 #ifdef AMR_BOARD_INIT
194     if ((AMR_IS_QUARTZ(sc) ? amr_quartz_init(sc) : amr_std_init(sc))))
195         return(ENXIO);
196 #endif
197
198     /*
199      * Quiz controller for features and limits.
200      */
201     if (amr_query_controller(sc))
202         return(ENXIO);
203
204     debug(2, "controller query complete");
205
206 #ifdef AMR_SCSI_PASSTHROUGH
207     /*
208      * Attach our 'real' SCSI channels to CAM.
209      */
210     if (amr_cam_attach(sc))
211         return(ENXIO);
212     debug(2, "CAM attach done");
213 #endif
214
215     /*
216      * Create the control device.
217      */
218     sc->amr_dev_t = make_dev(&amr_cdevsw, device_get_unit(sc->amr_dev), UID_ROOT, GID_OPERATOR,
219                              S_IRUSR | S_IWUSR, "amr%d", device_get_unit(sc->amr_dev));
220     sc->amr_dev_t->si_drv1 = sc;
221
222     /*
223      * Schedule ourselves to bring the controller up once interrupts are
224      * available.
225      */
226     bzero(&sc->amr_ich, sizeof(struct intr_config_hook));
227     sc->amr_ich.ich_func = amr_startup;
228     sc->amr_ich.ich_arg = sc;
229     if (config_intrhook_establish(&sc->amr_ich) != 0) {
230         device_printf(sc->amr_dev, "can't establish configuration hook\n");
231         return(ENOMEM);
232     }
233
234     /*
235      * Print a little information about the controller.
236      */
237     amr_describe_controller(sc);
238
239     debug(2, "attach complete");
240     return(0);
241 }
242
243 /********************************************************************************
244  * Locate disk resources and attach children to them.
245  */
246 static void
247 amr_startup(void *arg)
248 {
249     struct amr_softc    *sc = (struct amr_softc *)arg;
250     struct amr_logdrive *dr;
251     int                 i, error;
252     
253     debug_called(1);
254
255     /* pull ourselves off the intrhook chain */
256     config_intrhook_disestablish(&sc->amr_ich);
257
258     /* get up-to-date drive information */
259     if (amr_query_controller(sc)) {
260         device_printf(sc->amr_dev, "can't scan controller for drives\n");
261         return;
262     }
263
264     /* iterate over available drives */
265     for (i = 0, dr = &sc->amr_drive[0]; (i < AMR_MAXLD) && (dr->al_size != 0xffffffff); i++, dr++) {
266         /* are we already attached to this drive? */
267         if (dr->al_disk == 0) {
268             /* generate geometry information */
269             if (dr->al_size > 0x200000) {       /* extended translation? */
270                 dr->al_heads = 255;
271                 dr->al_sectors = 63;
272             } else {
273                 dr->al_heads = 64;
274                 dr->al_sectors = 32;
275             }
276             dr->al_cylinders = dr->al_size / (dr->al_heads * dr->al_sectors);
277             
278             dr->al_disk = device_add_child(sc->amr_dev, NULL, -1);
279             if (dr->al_disk == 0)
280                 device_printf(sc->amr_dev, "device_add_child failed\n");
281             device_set_ivars(dr->al_disk, dr);
282         }
283     }
284     
285     if ((error = bus_generic_attach(sc->amr_dev)) != 0)
286         device_printf(sc->amr_dev, "bus_generic_attach returned %d\n", error);
287     
288     /* mark controller back up */
289     sc->amr_state &= ~AMR_STATE_SHUTDOWN;
290
291     /* interrupts will be enabled before we do anything more */
292     sc->amr_state |= AMR_STATE_INTEN;
293
294     /*
295      * Start the timeout routine.
296      */
297 /*    sc->amr_timeout = timeout(amr_periodic, sc, hz);*/
298
299     return;
300 }
301
302 /*******************************************************************************
303  * Free resources associated with a controller instance
304  */
305 void
306 amr_free(struct amr_softc *sc)
307 {
308     struct amr_command_cluster  *acc;
309
310 #ifdef AMR_SCSI_PASSTHROUGH
311     /* detach from CAM */
312     amr_cam_detach(sc);
313 #endif
314
315     /* cancel status timeout */
316     untimeout(amr_periodic, sc, sc->amr_timeout);
317     
318     /* throw away any command buffers */
319     while ((acc = TAILQ_FIRST(&sc->amr_cmd_clusters)) != NULL) {
320         TAILQ_REMOVE(&sc->amr_cmd_clusters, acc, acc_link);
321         amr_freecmd_cluster(acc);
322     }
323 }
324
325 /*******************************************************************************
326  * Receive a bio structure from a child device and queue it on a particular
327  * disk resource, then poke the disk resource to start as much work as it can.
328  */
329 int
330 amr_submit_bio(struct amr_softc *sc, struct bio *bio)
331 {
332     debug_called(2);
333
334     amr_enqueue_bio(sc, bio);
335     amr_startio(sc);
336     return(0);
337 }
338
339 /********************************************************************************
340  * Accept an open operation on the control device.
341  */
342 int
343 amr_open(dev_t dev, int flags, int fmt, struct thread *td)
344 {
345     int                 unit = minor(dev);
346     struct amr_softc    *sc = devclass_get_softc(devclass_find("amr"), unit);
347
348     debug_called(1);
349
350     sc->amr_state |= AMR_STATE_OPEN;
351     return(0);
352 }
353
354 /********************************************************************************
355  * Accept the last close on the control device.
356  */
357 int
358 amr_close(dev_t dev, int flags, int fmt, struct thread *td)
359 {
360     int                 unit = minor(dev);
361     struct amr_softc    *sc = devclass_get_softc(devclass_find("amr"), unit);
362
363     debug_called(1);
364
365     sc->amr_state &= ~AMR_STATE_OPEN;
366     return (0);
367 }
368
369 /********************************************************************************
370  * Handle controller-specific control operations.
371  */
372 int
373 amr_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td)
374 {
375     struct amr_softc            *sc = (struct amr_softc *)dev->si_drv1;
376     int                         *arg = (int *)addr;
377     struct amr_user_ioctl       *au = (struct amr_user_ioctl *)addr;
378     struct amr_command          *ac;
379     struct amr_mailbox_ioctl    *mbi;
380     struct amr_passthrough      *ap;
381     void                        *dp;
382     int                         error;
383
384     debug_called(1);
385
386     error = 0;
387     dp = NULL;
388     ap = NULL;
389     ac = NULL;
390     switch(cmd) {
391
392     case AMR_IO_VERSION:
393         debug(1, "AMR_IO_VERSION");
394         *arg = AMR_IO_VERSION_NUMBER;
395         break;
396
397     case AMR_IO_COMMAND:
398         debug(1, "AMR_IO_COMMAND  0x%x", au->au_cmd[0]);
399         /* handle inbound data buffer */
400         if (au->au_length != 0) {
401             if ((dp = malloc(au->au_length, M_DEVBUF, M_WAITOK)) == NULL) {
402                 error = ENOMEM;
403                 break;
404             }
405             if ((error = copyin(au->au_buffer, dp, au->au_length)) != 0)
406                 break;
407             debug(2, "copyin %ld bytes from %p -> %p", au->au_length, au->au_buffer, dp);
408         }
409
410         if ((ac = amr_alloccmd(sc)) == NULL) {
411             error = ENOMEM;
412             break;
413         }
414
415         /* handle SCSI passthrough command */
416         if (au->au_cmd[0] == AMR_CMD_PASS) {
417             if ((ap = malloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
418                 error = ENOMEM;
419                 break;
420             }
421
422             /* copy cdb */
423             ap->ap_cdb_length = au->au_cmd[2];
424             bcopy(&au->au_cmd[3], &ap->ap_cdb[0], ap->ap_cdb_length);
425
426             /* build passthrough */
427             ap->ap_timeout              = au->au_cmd[ap->ap_cdb_length + 3] & 0x07;
428             ap->ap_ars                  = (au->au_cmd[ap->ap_cdb_length + 3] & 0x08) ? 1 : 0;
429             ap->ap_islogical            = (au->au_cmd[ap->ap_cdb_length + 3] & 0x80) ? 1 : 0;
430             ap->ap_logical_drive_no     = au->au_cmd[ap->ap_cdb_length + 4];
431             ap->ap_channel              = au->au_cmd[ap->ap_cdb_length + 5];
432             ap->ap_scsi_id              = au->au_cmd[ap->ap_cdb_length + 6];
433             ap->ap_request_sense_length = 14;
434             /* XXX what about the request-sense area? does the caller want it? */
435
436             /* build command */
437             ac->ac_data = ap;
438             ac->ac_length = sizeof(*ap);
439             ac->ac_flags |= AMR_CMD_DATAOUT;
440             ac->ac_ccb_data = dp;
441             ac->ac_ccb_length = au->au_length;
442             if (au->au_direction & AMR_IO_READ)
443                 ac->ac_flags |= AMR_CMD_CCB_DATAIN;
444             if (au->au_direction & AMR_IO_WRITE)
445                 ac->ac_flags |= AMR_CMD_CCB_DATAOUT;
446
447             ac->ac_mailbox.mb_command = AMR_CMD_PASS;
448
449         } else {
450             /* direct command to controller */
451             mbi = (struct amr_mailbox_ioctl *)&ac->ac_mailbox;
452
453             /* copy pertinent mailbox items */
454             mbi->mb_command = au->au_cmd[0];
455             mbi->mb_channel = au->au_cmd[1];
456             mbi->mb_param = au->au_cmd[2];
457             mbi->mb_pad[0] = au->au_cmd[3];
458             mbi->mb_drive = au->au_cmd[4];
459
460             /* build the command */
461             ac->ac_data = dp;
462             ac->ac_length = au->au_length;
463             if (au->au_direction & AMR_IO_READ)
464                 ac->ac_flags |= AMR_CMD_DATAIN;
465             if (au->au_direction & AMR_IO_WRITE)
466                 ac->ac_flags |= AMR_CMD_DATAOUT;
467         }
468
469         /* run the command */
470         if ((error = amr_wait_command(ac)) != 0)
471             break;
472
473         /* copy out data and set status */
474         if (au->au_length != 0)
475             error = copyout(dp, au->au_buffer, au->au_length);
476         debug(2, "copyout %ld bytes from %p -> %p", au->au_length, dp, au->au_buffer);
477         if (dp != NULL)
478             debug(2, "%16D", dp, " ");
479         au->au_status = ac->ac_status;
480         break;
481         
482     default:
483         debug(1, "unknown ioctl 0x%lx", cmd);
484         error = ENOIOCTL;
485         break;
486     }
487
488     if (dp != NULL)
489         free(dp, M_DEVBUF);
490     if (ap != NULL)
491         free(ap, M_DEVBUF);
492     if (ac != NULL)
493         amr_releasecmd(ac);
494     return(error);
495 }
496
497 /********************************************************************************
498  ********************************************************************************
499                                                                 Status Monitoring
500  ********************************************************************************
501  ********************************************************************************/
502
503 /********************************************************************************
504  * Perform a periodic check of the controller status
505  */
506 static void
507 amr_periodic(void *data)
508 {
509     struct amr_softc    *sc = (struct amr_softc *)data;
510
511     debug_called(2);
512
513     /* XXX perform periodic status checks here */
514
515     /* compensate for missed interrupts */
516     amr_done(sc);
517
518     /* reschedule */
519     sc->amr_timeout = timeout(amr_periodic, sc, hz);
520 }
521
522 /********************************************************************************
523  ********************************************************************************
524                                                                  Command Wrappers
525  ********************************************************************************
526  ********************************************************************************/
527
528 /********************************************************************************
529  * Interrogate the controller for the operational parameters we require.
530  */
531 static int
532 amr_query_controller(struct amr_softc *sc)
533 {
534     struct amr_enquiry3 *aex;
535     struct amr_prodinfo *ap;
536     struct amr_enquiry  *ae;
537     int                 ldrv;
538
539     /* 
540      * If we haven't found the real limit yet, let us have a couple of commands in
541      * order to be able to probe.
542      */
543     if (sc->amr_maxio == 0)
544         sc->amr_maxio = 2;
545
546     /* 
547      * Try to issue an ENQUIRY3 command 
548      */
549     if ((aex = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_ENQ3, 
550                            AMR_CONFIG_ENQ3_SOLICITED_FULL)) != NULL) {
551
552         /*
553          * Fetch current state of logical drives.
554          */
555         for (ldrv = 0; ldrv < aex->ae_numldrives; ldrv++) {
556             sc->amr_drive[ldrv].al_size       = aex->ae_drivesize[ldrv];
557             sc->amr_drive[ldrv].al_state      = aex->ae_drivestate[ldrv];
558             sc->amr_drive[ldrv].al_properties = aex->ae_driveprop[ldrv];
559             debug(2, "  drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size,
560                   sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties);
561         }
562         free(aex, M_DEVBUF);
563
564         /*
565          * Get product info for channel count.
566          */
567         if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0)) == NULL) {
568             device_printf(sc->amr_dev, "can't obtain product data from controller\n");
569             return(1);
570         }
571         sc->amr_maxdrives = 40;
572         sc->amr_maxchan = ap->ap_nschan;
573         sc->amr_maxio = ap->ap_maxio;
574         sc->amr_type |= AMR_TYPE_40LD;
575         free(ap, M_DEVBUF);
576
577     } else {
578
579         /* failed, try the 8LD ENQUIRY commands */
580         if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0)) == NULL) {
581             if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0)) == NULL) {
582                 device_printf(sc->amr_dev, "can't obtain configuration data from controller\n");
583                 return(1);
584             }
585             ae->ae_signature = 0;
586         }
587
588         /*
589          * Fetch current state of logical drives.
590          */
591         for (ldrv = 0; ldrv < ae->ae_ldrv.al_numdrives; ldrv++) {
592             sc->amr_drive[ldrv].al_size       = ae->ae_ldrv.al_size[ldrv];
593             sc->amr_drive[ldrv].al_state      = ae->ae_ldrv.al_state[ldrv];
594             sc->amr_drive[ldrv].al_properties = ae->ae_ldrv.al_properties[ldrv];
595             debug(2, "  drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size,
596                   sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties);
597         }
598
599         sc->amr_maxdrives = 8;
600         sc->amr_maxchan = ae->ae_adapter.aa_channels;
601         sc->amr_maxio = ae->ae_adapter.aa_maxio;
602         free(ae, M_DEVBUF);
603     }
604
605     /*
606      * Mark remaining drives as unused.
607      */
608     for (; ldrv < AMR_MAXLD; ldrv++)
609         sc->amr_drive[ldrv].al_size = 0xffffffff;
610
611     /* 
612      * Cap the maximum number of outstanding I/Os.  AMI's Linux driver doesn't trust
613      * the controller's reported value, and lockups have been seen when we do.
614      */
615     sc->amr_maxio = imin(sc->amr_maxio, AMR_LIMITCMD);
616
617     return(0);
618 }
619
620 /********************************************************************************
621  * Run a generic enquiry-style command.
622  */
623 static void *
624 amr_enquiry(struct amr_softc *sc, size_t bufsize, u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual)
625 {
626     struct amr_command  *ac;
627     void                *result;
628     u_int8_t            *mbox;
629     int                 error;
630
631     debug_called(1);
632
633     error = 1;
634     result = NULL;
635     
636     /* get ourselves a command buffer */
637     if ((ac = amr_alloccmd(sc)) == NULL)
638         goto out;
639     /* allocate the response structure */
640     if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
641         goto out;
642     /* set command flags */
643     ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
644     
645     /* point the command at our data */
646     ac->ac_data = result;
647     ac->ac_length = bufsize;
648     
649     /* build the command proper */
650     mbox = (u_int8_t *)&ac->ac_mailbox;         /* XXX want a real structure for this? */
651     mbox[0] = cmd;
652     mbox[2] = cmdsub;
653     mbox[3] = cmdqual;
654
655     /* can't assume that interrupts are going to work here, so play it safe */
656     if (amr_poll_command(ac))
657         goto out;
658     error = ac->ac_status;
659     
660  out:
661     if (ac != NULL)
662         amr_releasecmd(ac);
663     if ((error != 0) && (result != NULL)) {
664         free(result, M_DEVBUF);
665         result = NULL;
666     }
667     return(result);
668 }
669
670 /********************************************************************************
671  * Flush the controller's internal cache, return status.
672  */
673 int
674 amr_flush(struct amr_softc *sc)
675 {
676     struct amr_command  *ac;
677     int                 error;
678
679     /* get ourselves a command buffer */
680     error = 1;
681     if ((ac = amr_alloccmd(sc)) == NULL)
682         goto out;
683     /* set command flags */
684     ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
685     
686     /* build the command proper */
687     ac->ac_mailbox.mb_command = AMR_CMD_FLUSH;
688
689     /* we have to poll, as the system may be going down or otherwise damaged */
690     if (amr_poll_command(ac))
691         goto out;
692     error = ac->ac_status;
693     
694  out:
695     if (ac != NULL)
696         amr_releasecmd(ac);
697     return(error);
698 }
699
700 /********************************************************************************
701  * Try to find I/O work for the controller from one or more of the work queues.
702  *
703  * We make the assumption that if the controller is not ready to take a command
704  * at some given time, it will generate an interrupt at some later time when
705  * it is.
706  */
707 void
708 amr_startio(struct amr_softc *sc)
709 {
710     struct amr_command  *ac;
711
712     /* spin until something prevents us from doing any work */
713     for (;;) {
714
715         /* try to get a ready command */
716         ac = amr_dequeue_ready(sc);
717
718         /* if that failed, build a command from a bio */
719         if (ac == NULL)
720             (void)amr_bio_command(sc, &ac);
721
722 #ifdef AMR_SCSI_PASSTHROUGH
723         /* if that failed, build a command from a ccb */
724         if (ac == NULL)
725             (void)amr_cam_command(sc, &ac);
726 #endif
727         
728         /* if we don't have anything to do, give up */
729         if (ac == NULL)
730             break;
731
732         /* try to give the command to the controller; if this fails save it for later and give up */
733         if (amr_start(ac)) {
734             debug(2, "controller busy, command deferred");
735             amr_requeue_ready(ac);      /* XXX schedule retry very soon? */
736             break;
737         }
738     }
739 }
740
741 /********************************************************************************
742  * Handle completion of an I/O command.
743  */
744 static void
745 amr_completeio(struct amr_command *ac)
746 {
747     struct amr_softc    *sc = ac->ac_sc;
748     
749     if (ac->ac_status != AMR_STATUS_SUCCESS) {  /* could be more verbose here? */
750         ac->ac_bio->bio_error = EIO;
751         ac->ac_bio->bio_flags |= BIO_ERROR;
752
753         device_printf(sc->amr_dev, "I/O error - 0x%x\n", ac->ac_status);
754 /*      amr_printcommand(ac);*/
755     }
756     amrd_intr(ac->ac_bio);
757     amr_releasecmd(ac);
758 }
759
760 /********************************************************************************
761  ********************************************************************************
762                                                                Command Processing
763  ********************************************************************************
764  ********************************************************************************/
765
766 /********************************************************************************
767  * Convert a bio off the top of the bio queue into a command.
768  */
769 static int
770 amr_bio_command(struct amr_softc *sc, struct amr_command **acp)
771 {
772     struct amr_command  *ac;
773     struct amrd_softc   *amrd;
774     struct bio          *bio;
775     int                 error;
776     int                 blkcount;
777     int                 driveno;
778     int                 cmd;
779
780     ac = NULL;
781     error = 0;
782
783     /* get a bio to work on */
784     if ((bio = amr_dequeue_bio(sc)) == NULL)
785         goto out;
786
787     /* get a command */
788     if ((ac = amr_alloccmd(sc)) == NULL) {
789         error = ENOMEM;
790         goto out;
791     }   
792         
793     /* connect the bio to the command */
794     ac->ac_complete = amr_completeio;
795     ac->ac_bio = bio;
796     ac->ac_data = bio->bio_data;
797     ac->ac_length = bio->bio_bcount;
798     if (BIO_IS_READ(bio)) {
799         ac->ac_flags |= AMR_CMD_DATAIN;
800         cmd = AMR_CMD_LREAD;
801     } else {
802         ac->ac_flags |= AMR_CMD_DATAOUT;
803         cmd = AMR_CMD_LWRITE;
804     }
805     amrd = (struct amrd_softc *)bio->bio_dev->si_drv1;
806     driveno = amrd->amrd_drive - sc->amr_drive;
807     blkcount = (bio->bio_bcount + AMR_BLKSIZE - 1) / AMR_BLKSIZE;
808
809     ac->ac_mailbox.mb_command = cmd;
810     ac->ac_mailbox.mb_blkcount = blkcount;
811     ac->ac_mailbox.mb_lba = bio->bio_pblkno;
812     ac->ac_mailbox.mb_drive = driveno;
813     /* we fill in the s/g related data when the command is mapped */
814
815     if ((bio->bio_pblkno + blkcount) > sc->amr_drive[driveno].al_size)
816         device_printf(sc->amr_dev, "I/O beyond end of unit (%lld,%d > %lu)\n", 
817                       (long long)bio->bio_pblkno, blkcount,
818                       (u_long)sc->amr_drive[driveno].al_size);
819
820 out:
821     if (error != 0) {
822         if (ac != NULL)
823             amr_releasecmd(ac);
824         if (bio != NULL)                        /* this breaks ordering... */
825             amr_enqueue_bio(sc, bio);
826     }
827     *acp = ac;
828     return(error);
829 }
830
831 /********************************************************************************
832  * Take a command, submit it to the controller and sleep until it completes
833  * or fails.  Interrupts must be enabled, returns nonzero on error.
834  */
835 static int
836 amr_wait_command(struct amr_command *ac)
837 {
838     int                 error, count;
839     
840     debug_called(1);
841
842     ac->ac_complete = NULL;
843     ac->ac_flags |= AMR_CMD_SLEEP;
844     if ((error = amr_start(ac)) != 0)
845         return(error);
846     
847     count = 0;
848     /* XXX better timeout? */
849     while ((ac->ac_flags & AMR_CMD_BUSY) && (count < 30)) {
850         tsleep(ac, PRIBIO | PCATCH, "amrwcmd", hz);
851     }
852     return(0);
853 }
854
855 /********************************************************************************
856  * Take a command, submit it to the controller and busy-wait for it to return.
857  * Returns nonzero on error.  Can be safely called with interrupts enabled.
858  */
859 static int
860 amr_poll_command(struct amr_command *ac)
861 {
862     struct amr_softc    *sc = ac->ac_sc;
863     int                 error, count;
864
865     debug_called(2);
866
867     ac->ac_complete = NULL;
868     if ((error = amr_start(ac)) != 0)
869         return(error);
870
871     count = 0;
872     do {
873         /* 
874          * Poll for completion, although the interrupt handler may beat us to it. 
875          * Note that the timeout here is somewhat arbitrary.
876          */
877         amr_done(sc);
878         DELAY(1000);
879     } while ((ac->ac_flags & AMR_CMD_BUSY) && (count++ < 1000));
880     if (!(ac->ac_flags & AMR_CMD_BUSY)) {
881         error = 0;
882     } else {
883         /* XXX the slot is now marked permanently busy */
884         error = EIO;
885         device_printf(sc->amr_dev, "polled command timeout\n");
886     }
887     return(error);
888 }
889
890 /********************************************************************************
891  * Get a free command slot for a command if it doesn't already have one.
892  *
893  * May be safely called multiple times for a given command.
894  */
895 static int
896 amr_getslot(struct amr_command *ac)
897 {
898     struct amr_softc    *sc = ac->ac_sc;
899     int                 s, slot, limit, error;
900
901     debug_called(3);
902
903     /* if the command already has a slot, don't try to give it another one */
904     if (ac->ac_slot != 0)
905         return(0);
906
907     /* enforce slot usage limit */
908     limit = (ac->ac_flags & AMR_CMD_PRIORITY) ? sc->amr_maxio : sc->amr_maxio - 4;
909     if (sc->amr_busyslots > limit)
910         return(EBUSY);
911     
912     /*
913      * Allocate a slot.  XXX linear scan is slow
914      */
915     error = EBUSY;
916     s = splbio();
917     for (slot = 0; slot < sc->amr_maxio; slot++) {
918         if (sc->amr_busycmd[slot] == NULL) {
919             sc->amr_busycmd[slot] = ac;
920             sc->amr_busyslots++;
921             ac->ac_slot = slot;
922             error = 0;
923             break;
924         }
925     }
926     splx(s);
927
928     return(error);
929 }
930
931 /********************************************************************************
932  * Map/unmap (ac)'s data in the controller's addressable space as required.
933  *
934  * These functions may be safely called multiple times on a given command.
935  */
936 static void
937 amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
938 {
939     struct amr_command  *ac = (struct amr_command *)arg;
940     struct amr_softc    *sc = ac->ac_sc;
941     struct amr_sgentry  *sg;
942     int                 i;
943     u_int8_t            *sgc;
944
945     debug_called(3);
946
947     /* get base address of s/g table */
948     sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
949
950     /* save data physical address */
951     ac->ac_dataphys = segs[0].ds_addr;
952
953     /* for AMR_CMD_CONFIG the s/g count goes elsewhere */
954     if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG) {
955         sgc = &(((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param);
956     } else {
957         sgc = &ac->ac_mailbox.mb_nsgelem;
958     }
959
960     /* decide whether we need to populate the s/g table */
961     if (nsegments < 2) {
962         *sgc = 0;
963         ac->ac_mailbox.mb_physaddr = ac->ac_dataphys;
964     } else {
965         *sgc = nsegments;
966         ac->ac_mailbox.mb_physaddr = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry));
967         for (i = 0; i < nsegments; i++, sg++) {
968             sg->sg_addr = segs[i].ds_addr;
969             sg->sg_count = segs[i].ds_len;
970         }
971     }
972 }
973
974 static void
975 amr_setup_ccbmap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
976 {
977     struct amr_command          *ac = (struct amr_command *)arg;
978     struct amr_softc            *sc = ac->ac_sc;
979     struct amr_sgentry          *sg;
980     struct amr_passthrough      *ap = (struct amr_passthrough *)ac->ac_data;
981     int                         i;
982
983     /* get base address of s/g table */
984     sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
985
986     /* save s/g table information in passthrough */
987     ap->ap_no_sg_elements = nsegments;
988     ap->ap_data_transfer_address = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry));
989
990     /* save pointer to passthrough in command   XXX is this already done above? */
991     ac->ac_mailbox.mb_physaddr = ac->ac_dataphys;
992
993     debug(3, "slot %d  %d segments at 0x%x, passthrough at 0x%x", ac->ac_slot,
994            ap->ap_no_sg_elements, ap->ap_data_transfer_address, ac->ac_dataphys);
995     
996     /* populate s/g table (overwrites previous call which mapped the passthrough) */
997     for (i = 0; i < nsegments; i++, sg++) {
998         sg->sg_addr = segs[i].ds_addr;
999         sg->sg_count = segs[i].ds_len;
1000         debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count);
1001     }
1002 }
1003
1004 static void
1005 amr_mapcmd(struct amr_command *ac)
1006 {
1007     struct amr_softc    *sc = ac->ac_sc;
1008
1009     debug_called(3);
1010
1011     /* if the command involves data at all, and hasn't been mapped */
1012     if (!(ac->ac_flags & AMR_CMD_MAPPED)) {
1013
1014         if (ac->ac_data != NULL) {
1015             /* map the data buffers into bus space and build the s/g list */
1016             bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_dmamap, ac->ac_data, ac->ac_length, 
1017                             amr_setup_dmamap, ac, 0);
1018             if (ac->ac_flags & AMR_CMD_DATAIN)
1019                 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREREAD);
1020             if (ac->ac_flags & AMR_CMD_DATAOUT)
1021                 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREWRITE);
1022         }
1023
1024         if (ac->ac_ccb_data != NULL) {
1025             bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, ac->ac_ccb_data, ac->ac_ccb_length, 
1026                             amr_setup_ccbmap, ac, 0);
1027             if (ac->ac_flags & AMR_CMD_CCB_DATAIN)
1028                 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_PREREAD);
1029             if (ac->ac_flags & AMR_CMD_CCB_DATAOUT)
1030                 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_PREWRITE);
1031         }
1032         ac->ac_flags |= AMR_CMD_MAPPED;
1033     }
1034 }
1035
1036 static void
1037 amr_unmapcmd(struct amr_command *ac)
1038 {
1039     struct amr_softc    *sc = ac->ac_sc;
1040
1041     debug_called(3);
1042
1043     /* if the command involved data at all and was mapped */
1044     if (ac->ac_flags & AMR_CMD_MAPPED) {
1045
1046         if (ac->ac_data != NULL) {
1047             if (ac->ac_flags & AMR_CMD_DATAIN)
1048                 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTREAD);
1049             if (ac->ac_flags & AMR_CMD_DATAOUT)
1050                 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTWRITE);
1051             bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap);
1052         }
1053
1054         if (ac->ac_ccb_data != NULL) {
1055             if (ac->ac_flags & AMR_CMD_CCB_DATAIN)
1056                 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_POSTREAD);
1057             if (ac->ac_flags & AMR_CMD_CCB_DATAOUT)
1058                 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_POSTWRITE);
1059             bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_ccb_dmamap);
1060         }
1061         ac->ac_flags &= ~AMR_CMD_MAPPED;
1062     }
1063 }
1064
1065 /********************************************************************************
1066  * Take a command and give it to the controller, returns 0 if successful, or
1067  * EBUSY if the command should be retried later.
1068  */
1069 static int
1070 amr_start(struct amr_command *ac)
1071 {
1072     struct amr_softc    *sc = ac->ac_sc;
1073     int                 done, s, i;
1074     
1075     debug_called(3);
1076
1077     /* mark command as busy so that polling consumer can tell */
1078     ac->ac_flags |= AMR_CMD_BUSY;
1079
1080     /* get a command slot (freed in amr_done) */
1081     if (amr_getslot(ac))
1082         return(EBUSY);
1083
1084     /* now we have a slot, we can map the command (unmapped in amr_complete) */
1085     amr_mapcmd(ac);
1086
1087     /* mark the new mailbox we are going to copy in as busy */
1088     ac->ac_mailbox.mb_busy = 1;
1089
1090     /* clear the poll/ack fields in the mailbox */
1091     sc->amr_mailbox->mb_poll = 0;
1092     sc->amr_mailbox->mb_ack = 0;
1093
1094     /* 
1095      * Save the slot number so that we can locate this command when complete.
1096      * Note that ident = 0 seems to be special, so we don't use it.
1097      */
1098     ac->ac_mailbox.mb_ident = ac->ac_slot + 1;
1099
1100     /* 
1101      * Spin waiting for the mailbox, give up after ~1 second.  We expect the
1102      * controller to be able to handle our I/O.
1103      *
1104      * XXX perhaps we should wait for less time, and count on the deferred command
1105      * handling to deal with retries?
1106      */
1107     debug(4, "wait for mailbox");
1108     for (i = 10000, done = 0; (i > 0) && !done; i--) {
1109         s = splbio();
1110         
1111         /* is the mailbox free? */
1112         if (sc->amr_mailbox->mb_busy == 0) {
1113             debug(4, "got mailbox");
1114             sc->amr_mailbox64->mb64_segment = 0;
1115             bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, AMR_MBOX_CMDSIZE);
1116             done = 1;
1117
1118             /* not free, spin waiting */
1119         } else {
1120             debug(4, "busy flag %x\n", sc->amr_mailbox->mb_busy);
1121             /* this is somewhat ugly */
1122             DELAY(100);
1123         }
1124         splx(s);        /* drop spl to allow completion interrupts */
1125     }
1126
1127     /*
1128      * Now give the command to the controller
1129      */
1130     if (done) {
1131         if (sc->amr_submit_command(sc)) {
1132             /* the controller wasn't ready to take the command, forget that we tried to post it */
1133             sc->amr_mailbox->mb_busy = 0;
1134             return(EBUSY);
1135         }
1136         debug(3, "posted command");
1137         return(0);
1138     }
1139     
1140     /*
1141      * The controller wouldn't take the command.  Return the command as busy
1142      * so that it is retried later.
1143      */
1144     return(EBUSY);
1145 }
1146
1147 /********************************************************************************
1148  * Extract one or more completed commands from the controller (sc)
1149  *
1150  * Returns nonzero if any commands on the work queue were marked as completed.
1151  */
1152 int
1153 amr_done(struct amr_softc *sc)
1154 {
1155     struct amr_command  *ac;
1156     struct amr_mailbox  mbox;
1157     int                 i, idx, result;
1158     
1159     debug_called(3);
1160
1161     /* See if there's anything for us to do */
1162     result = 0;
1163
1164     /* loop collecting completed commands */
1165     for (;;) {
1166         /* poll for a completed command's identifier and status */
1167         if (sc->amr_get_work(sc, &mbox)) {
1168             result = 1;
1169             
1170             /* iterate over completed commands in this result */
1171             for (i = 0; i < mbox.mb_nstatus; i++) {
1172                 /* get pointer to busy command */
1173                 idx = mbox.mb_completed[i] - 1;
1174                 ac = sc->amr_busycmd[idx];
1175
1176                 /* really a busy command? */
1177                 if (ac != NULL) {
1178
1179                     /* pull the command from the busy index */
1180                     sc->amr_busycmd[idx] = NULL;
1181                     sc->amr_busyslots--;
1182                 
1183                     /* save status for later use */
1184                     ac->ac_status = mbox.mb_status;
1185                     amr_enqueue_completed(ac);
1186                     debug(3, "completed command with status %x", mbox.mb_status);
1187                 } else {
1188                     device_printf(sc->amr_dev, "bad slot %d completed\n", idx);
1189                 }
1190             }
1191         } else {
1192             break;      /* no work */
1193         }
1194     }
1195     
1196     /* if we've completed any commands, try posting some more */
1197     if (result)
1198         amr_startio(sc);
1199     
1200     /* handle completion and timeouts */
1201 #if __FreeBSD_version >= 500005
1202     if (sc->amr_state & AMR_STATE_INTEN) 
1203         taskqueue_enqueue(taskqueue_swi, &sc->amr_task_complete);
1204     else
1205 #endif
1206         amr_complete(sc, 0);
1207     
1208     return(result);
1209 }
1210
1211 /********************************************************************************
1212  * Do completion processing on done commands on (sc)
1213  */
1214 static void
1215 amr_complete(void *context, int pending)
1216 {
1217     struct amr_softc    *sc = (struct amr_softc *)context;
1218     struct amr_command  *ac;
1219
1220     debug_called(3);
1221
1222     /* pull completed commands off the queue */
1223     for (;;) {
1224         ac = amr_dequeue_completed(sc);
1225         if (ac == NULL)
1226             break;
1227
1228         /* unmap the command's data buffer */
1229         amr_unmapcmd(ac);
1230
1231         /* unbusy the command */
1232         ac->ac_flags &= ~AMR_CMD_BUSY;
1233             
1234         /* 
1235          * Is there a completion handler? 
1236          */
1237         if (ac->ac_complete != NULL) {
1238             ac->ac_complete(ac);
1239             
1240             /* 
1241              * Is someone sleeping on this one?
1242              */
1243         } else if (ac->ac_flags & AMR_CMD_SLEEP) {
1244             wakeup(ac);
1245         }
1246     }
1247 }
1248
1249 /********************************************************************************
1250  ********************************************************************************
1251                                                         Command Buffer Management
1252  ********************************************************************************
1253  ********************************************************************************/
1254
1255 /********************************************************************************
1256  * Get a new command buffer.
1257  *
1258  * This may return NULL in low-memory cases.
1259  *
1260  * If possible, we recycle a command buffer that's been used before.
1261  */
1262 struct amr_command *
1263 amr_alloccmd(struct amr_softc *sc)
1264 {
1265     struct amr_command  *ac;
1266
1267     debug_called(3);
1268
1269     ac = amr_dequeue_free(sc);
1270     if (ac == NULL) {
1271         amr_alloccmd_cluster(sc);
1272         ac = amr_dequeue_free(sc);
1273     }
1274     if (ac == NULL)
1275         return(NULL);
1276
1277     /* clear out significant fields */
1278     ac->ac_slot = 0;
1279     ac->ac_status = 0;
1280     bzero(&ac->ac_mailbox, sizeof(struct amr_mailbox));
1281     ac->ac_flags = 0;
1282     ac->ac_bio = NULL;
1283     ac->ac_data = NULL;
1284     ac->ac_ccb_data = NULL;
1285     ac->ac_complete = NULL;
1286     return(ac);
1287 }
1288
1289 /********************************************************************************
1290  * Release a command buffer for recycling.
1291  */
1292 void
1293 amr_releasecmd(struct amr_command *ac)
1294 {
1295     debug_called(3);
1296
1297     amr_enqueue_free(ac);
1298 }
1299
1300 /********************************************************************************
1301  * Allocate a new command cluster and initialise it.
1302  */
1303 void
1304 amr_alloccmd_cluster(struct amr_softc *sc)
1305 {
1306     struct amr_command_cluster  *acc;
1307     struct amr_command          *ac;
1308     int                         s, i;
1309
1310     acc = malloc(AMR_CMD_CLUSTERSIZE, M_DEVBUF, M_NOWAIT);
1311     if (acc != NULL) {
1312         s = splbio();
1313         TAILQ_INSERT_TAIL(&sc->amr_cmd_clusters, acc, acc_link);
1314         splx(s);
1315         for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++) {
1316             ac = &acc->acc_command[i];
1317             bzero(ac, sizeof(*ac));
1318             ac->ac_sc = sc;
1319             if (!bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap) &&
1320                 !bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_ccb_dmamap))
1321                 amr_releasecmd(ac);
1322         }
1323     }
1324 }
1325
1326 /********************************************************************************
1327  * Free a command cluster
1328  */
1329 void
1330 amr_freecmd_cluster(struct amr_command_cluster *acc)
1331 {
1332     struct amr_softc    *sc = acc->acc_command[0].ac_sc;
1333     int                 i;
1334
1335     for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++)
1336         bus_dmamap_destroy(sc->amr_buffer_dmat, acc->acc_command[i].ac_dmamap);
1337     free(acc, M_DEVBUF);
1338 }
1339
1340 /********************************************************************************
1341  ********************************************************************************
1342                                                          Interface-specific Shims
1343  ********************************************************************************
1344  ********************************************************************************/
1345
1346 /********************************************************************************
1347  * Tell the controller that the mailbox contains a valid command
1348  */
1349 static int
1350 amr_quartz_submit_command(struct amr_softc *sc)
1351 {
1352     debug_called(3);
1353
1354     if (AMR_QGET_IDB(sc) & AMR_QIDB_SUBMIT)
1355         return(EBUSY);
1356     AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT);
1357     return(0);
1358 }
1359
1360 static int
1361 amr_std_submit_command(struct amr_softc *sc)
1362 {
1363     debug_called(3);
1364
1365     if (AMR_SGET_MBSTAT(sc) & AMR_SMBOX_BUSYFLAG)
1366         return(EBUSY);
1367     AMR_SPOST_COMMAND(sc);
1368     return(0);
1369 }
1370
1371 /********************************************************************************
1372  * Claim any work that the controller has completed; acknowledge completion,
1373  * save details of the completion in (mbsave)
1374  */
1375 static int
1376 amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
1377 {
1378     int         s, worked;
1379     u_int32_t   outd;
1380
1381     debug_called(3);
1382
1383     worked = 0;
1384     s = splbio();
1385
1386     /* work waiting for us? */
1387     if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) {
1388
1389         /* save mailbox, which contains a list of completed commands */
1390         bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave));
1391
1392         /* acknowledge interrupt */
1393         AMR_QPUT_ODB(sc, AMR_QODB_READY);
1394
1395         /* acknowledge that we have the commands */
1396         AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK);
1397
1398 #ifndef AMR_QUARTZ_GOFASTER
1399         /*
1400          * This waits for the controller to notice that we've taken the
1401          * command from it.  It's very inefficient, and we shouldn't do it,
1402          * but if we remove this code, we stop completing commands under
1403          * load.
1404          *
1405          * Peter J says we shouldn't do this.  The documentation says we
1406          * should.  Who is right?
1407          */
1408         while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK)
1409             ;                           /* XXX aiee! what if it dies? */
1410 #endif
1411
1412         worked = 1;                     /* got some work */
1413     }
1414
1415     splx(s);
1416     return(worked);
1417 }
1418
1419 static int
1420 amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
1421 {
1422     int         s, worked;
1423     u_int8_t    istat;
1424
1425     debug_called(3);
1426
1427     worked = 0;
1428     s = splbio();
1429
1430     /* check for valid interrupt status */
1431     istat = AMR_SGET_ISTAT(sc);
1432     if ((istat & AMR_SINTR_VALID) != 0) {
1433         AMR_SPUT_ISTAT(sc, istat);      /* ack interrupt status */
1434
1435         /* save mailbox, which contains a list of completed commands */
1436         bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave));
1437
1438         AMR_SACK_INTERRUPT(sc);         /* acknowledge we have the mailbox */
1439         worked = 1;
1440     }
1441
1442     splx(s);
1443     return(worked);
1444 }
1445
1446 /********************************************************************************
1447  * Notify the controller of the mailbox location.
1448  */
1449 static void
1450 amr_std_attach_mailbox(struct amr_softc *sc)
1451 {
1452
1453     /* program the mailbox physical address */
1454     AMR_SBYTE_SET(sc, AMR_SMBOX_0, sc->amr_mailboxphys         & 0xff);
1455     AMR_SBYTE_SET(sc, AMR_SMBOX_1, (sc->amr_mailboxphys >>  8) & 0xff);
1456     AMR_SBYTE_SET(sc, AMR_SMBOX_2, (sc->amr_mailboxphys >> 16) & 0xff);
1457     AMR_SBYTE_SET(sc, AMR_SMBOX_3, (sc->amr_mailboxphys >> 24) & 0xff);
1458     AMR_SBYTE_SET(sc, AMR_SMBOX_ENABLE, AMR_SMBOX_ADDR);
1459
1460     /* clear any outstanding interrupt and enable interrupts proper */
1461     AMR_SACK_INTERRUPT(sc);
1462     AMR_SENABLE_INTR(sc);
1463 }
1464
1465 #ifdef AMR_BOARD_INIT
1466 /********************************************************************************
1467  * Initialise the controller
1468  */
1469 static int
1470 amr_quartz_init(struct amr_softc *sc)
1471 {
1472     int         status, ostatus;
1473
1474     device_printf(sc->amr_dev, "initial init status %x\n", AMR_QGET_INITSTATUS(sc));
1475
1476     AMR_QRESET(sc);
1477
1478     ostatus = 0xff;
1479     while ((status = AMR_QGET_INITSTATUS(sc)) != AMR_QINIT_DONE) {
1480         if (status != ostatus) {
1481             device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_qinit, status));
1482             ostatus = status;
1483         }
1484         switch (status) {
1485         case AMR_QINIT_NOMEM:
1486             return(ENOMEM);
1487
1488         case AMR_QINIT_SCAN:
1489             /* XXX we could print channel/target here */
1490             break;
1491         }
1492     }
1493     return(0);
1494 }
1495
1496 static int
1497 amr_std_init(struct amr_softc *sc)
1498 {
1499     int         status, ostatus;
1500
1501     device_printf(sc->amr_dev, "initial init status %x\n", AMR_SGET_INITSTATUS(sc));
1502
1503     AMR_SRESET(sc);
1504  
1505     ostatus = 0xff;
1506     while ((status = AMR_SGET_INITSTATUS(sc)) != AMR_SINIT_DONE) {
1507         if (status != ostatus) {
1508             device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_sinit, status));
1509             ostatus = status;
1510         }
1511         switch (status) {
1512         case AMR_SINIT_NOMEM:
1513             return(ENOMEM);
1514
1515         case AMR_SINIT_INPROG:
1516             /* XXX we could print channel/target here? */
1517             break;
1518         }
1519     }
1520     return(0);
1521 }
1522 #endif
1523
1524 /********************************************************************************
1525  ********************************************************************************
1526                                                                         Debugging
1527  ********************************************************************************
1528  ********************************************************************************/
1529
1530 /********************************************************************************
1531  * Identify the controller and print some information about it.
1532  */
1533 static void
1534 amr_describe_controller(struct amr_softc *sc)
1535 {
1536     struct amr_prodinfo *ap;
1537     struct amr_enquiry  *ae;
1538     char                *prod;
1539
1540     /*
1541      * Try to get 40LD product info, which tells us what the card is labelled as.
1542      */
1543     if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0)) != NULL) {
1544         device_printf(sc->amr_dev, "<%.80s> Firmware %.16s, BIOS %.16s, %dMB RAM\n",
1545                       ap->ap_product, ap->ap_firmware, ap->ap_bios,
1546                       ap->ap_memsize);
1547
1548         free(ap, M_DEVBUF);
1549         return;
1550     }
1551
1552     /*
1553      * Try 8LD extended ENQUIRY to get controller signature, and use lookup table.
1554      */
1555     if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0)) != NULL) {
1556         prod = amr_describe_code(amr_table_adaptertype, ae->ae_signature);
1557
1558     } else if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0)) != NULL) {
1559
1560         /*
1561          * Try to work it out based on the PCI signatures.
1562          */
1563         switch (pci_get_device(sc->amr_dev)) {
1564         case 0x9010:
1565             prod = "Series 428";
1566             break;
1567         case 0x9060:
1568             prod = "Series 434";
1569             break;
1570         default:
1571             prod = "unknown controller";
1572             break;
1573         }
1574     } else {
1575         prod = "unsupported controller";
1576     }
1577
1578     /*
1579      * HP NetRaid controllers have a special encoding of the firmware and
1580      * BIOS versions. The AMI version seems to have it as strings whereas
1581      * the HP version does it with a leading uppercase character and two
1582      * binary numbers.
1583      */
1584      
1585     if(ae->ae_adapter.aa_firmware[2] >= 'A' &&
1586        ae->ae_adapter.aa_firmware[2] <= 'Z' &&
1587        ae->ae_adapter.aa_firmware[1] <  ' ' &&
1588        ae->ae_adapter.aa_firmware[0] <  ' ' &&
1589        ae->ae_adapter.aa_bios[2] >= 'A'     &&
1590        ae->ae_adapter.aa_bios[2] <= 'Z'     &&
1591        ae->ae_adapter.aa_bios[1] <  ' '     &&
1592        ae->ae_adapter.aa_bios[0] <  ' ') {
1593
1594         /* this looks like we have an HP NetRaid version of the MegaRaid */
1595
1596         if(ae->ae_signature == AMR_SIG_438) {
1597                 /* the AMI 438 is an NetRaid 3si in HP-land */
1598                 prod = "HP NetRaid 3si";
1599         }
1600         
1601         device_printf(sc->amr_dev, "<%s> Firmware %c.%02d.%02d, BIOS %c.%02d.%02d, %dMB RAM\n",
1602                       prod, ae->ae_adapter.aa_firmware[2],
1603                       ae->ae_adapter.aa_firmware[1],
1604                       ae->ae_adapter.aa_firmware[0],
1605                       ae->ae_adapter.aa_bios[2],
1606                       ae->ae_adapter.aa_bios[1],
1607                       ae->ae_adapter.aa_bios[0],
1608                       ae->ae_adapter.aa_memorysize);            
1609     } else {
1610         device_printf(sc->amr_dev, "<%s> Firmware %.4s, BIOS %.4s, %dMB RAM\n", 
1611                       prod, ae->ae_adapter.aa_firmware, ae->ae_adapter.aa_bios,
1612                       ae->ae_adapter.aa_memorysize);
1613     }           
1614     free(ae, M_DEVBUF);
1615 }
1616
1617 #ifdef AMR_DEBUG
1618 /********************************************************************************
1619  * Print the command (ac) in human-readable format
1620  */
1621 static void
1622 amr_printcommand(struct amr_command *ac)
1623 {
1624     struct amr_softc    *sc = ac->ac_sc;
1625     struct amr_sgentry  *sg;
1626     int                 i;
1627     
1628     device_printf(sc->amr_dev, "cmd %x  ident %d  drive %d\n",
1629                   ac->ac_mailbox.mb_command, ac->ac_mailbox.mb_ident, ac->ac_mailbox.mb_drive);
1630     device_printf(sc->amr_dev, "blkcount %d  lba %d\n", 
1631                   ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba);
1632     device_printf(sc->amr_dev, "virtaddr %p  length %lu\n", ac->ac_data, (unsigned long)ac->ac_length);
1633     device_printf(sc->amr_dev, "sg physaddr %08x  nsg %d\n",
1634                   ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem);
1635     device_printf(sc->amr_dev, "ccb %p  bio %p\n", ac->ac_ccb_data, ac->ac_bio);
1636
1637     /* get base address of s/g table */
1638     sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
1639     for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++)
1640         device_printf(sc->amr_dev, "  %x/%d\n", sg->sg_addr, sg->sg_count);
1641 }
1642 #endif