amr.c revision 111528
1281SN/A/*-
2281SN/A * Copyright (c) 1999,2000 Michael Smith
3281SN/A * Copyright (c) 2000 BSDi
4281SN/A * All rights reserved.
5281SN/A *
6281SN/A * Redistribution and use in source and binary forms, with or without
7281SN/A * modification, are permitted provided that the following conditions
8281SN/A * are met:
9281SN/A * 1. Redistributions of source code must retain the above copyright
10281SN/A *    notice, this list of conditions and the following disclaimer.
11281SN/A * 2. Redistributions in binary form must reproduce the above copyright
12281SN/A *    notice, this list of conditions and the following disclaimer in the
13281SN/A *    documentation and/or other materials provided with the distribution.
14281SN/A *
15281SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16281SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17281SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18281SN/A * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19281SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20281SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21281SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22281SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23281SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24281SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25281SN/A * SUCH DAMAGE.
26281SN/A *
27281SN/A * Copyright (c) 2002 Eric Moore
28281SN/A * Copyright (c) 2002 LSI Logic Corporation
29281SN/A * All rights reserved.
30281SN/A *
31281SN/A * Redistribution and use in source and binary forms, with or without
32281SN/A * modification, are permitted provided that the following conditions
33281SN/A * are met:
34281SN/A * 1. Redistributions of source code must retain the above copyright
35281SN/A *    notice, this list of conditions and the following disclaimer.
36281SN/A * 2. Redistributions in binary form must reproduce the above copyright
37281SN/A *    notice, this list of conditions and the following disclaimer in the
38281SN/A *    documentation and/or other materials provided with the distribution.
39281SN/A * 3. The party using or redistributing the source code and binary forms
40281SN/A *    agrees to the disclaimer below and the terms and conditions set forth
41281SN/A *    herein.
42281SN/A *
43281SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
44281SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45281SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46281SN/A * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
47281SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48281SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49281SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50281SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51281SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52281SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53281SN/A * SUCH DAMAGE.
54281SN/A *
55281SN/A *
56281SN/A *	$FreeBSD: head/sys/dev/amr/amr.c 111528 2003-02-26 03:15:42Z scottl $
57281SN/A */
58281SN/A
59281SN/A/*
60281SN/A * Driver for the AMI MegaRaid family of controllers.
61281SN/A */
62281SN/A
63281SN/A#include <sys/param.h>
64281SN/A#include <sys/systm.h>
65281SN/A#include <sys/malloc.h>
66281SN/A#include <sys/kernel.h>
67281SN/A
68281SN/A#include <dev/amr/amr_compat.h>
69281SN/A#include <sys/bus.h>
70281SN/A#include <sys/conf.h>
71281SN/A#include <sys/devicestat.h>
72281SN/A#include <sys/disk.h>
73281SN/A#include <sys/stat.h>
74281SN/A
75281SN/A#include <machine/bus_memio.h>
76281SN/A#include <machine/bus_pio.h>
77281SN/A#include <machine/bus.h>
78281SN/A#include <machine/resource.h>
79281SN/A#include <sys/rman.h>
80281SN/A
81281SN/A#include <pci/pcireg.h>
82281SN/A#include <pci/pcivar.h>
83281SN/A
84281SN/A#include <dev/amr/amrio.h>
85281SN/A#include <dev/amr/amrreg.h>
86281SN/A#include <dev/amr/amrvar.h>
87281SN/A#define AMR_DEFINE_TABLES
88281SN/A#include <dev/amr/amr_tables.h>
89281SN/A
90281SN/A#define AMR_CDEV_MAJOR	132
91281SN/A
92281SN/Astatic d_open_t         amr_open;
93281SN/Astatic d_close_t        amr_close;
94281SN/Astatic d_ioctl_t        amr_ioctl;
95281SN/A
96281SN/Astatic struct cdevsw amr_cdevsw = {
97281SN/A		/* open */	amr_open,
98281SN/A		/* close */	amr_close,
99281SN/A		/* read */	noread,
100281SN/A		/* write */	nowrite,
101281SN/A		/* ioctl */	amr_ioctl,
102281SN/A		/* poll */	nopoll,
103281SN/A		/* mmap */	nommap,
104281SN/A		/* strategy */	nostrategy,
105281SN/A		/* name */ 	"amr",
106281SN/A		/* maj */	AMR_CDEV_MAJOR,
107281SN/A		/* dump */	nodump,
108281SN/A		/* psize */ 	nopsize,
109281SN/A		/* flags */	0,
110281SN/A};
111281SN/A
112281SN/A/*
113281SN/A * Initialisation, bus interface.
114281SN/A */
115281SN/Astatic void	amr_startup(void *arg);
116281SN/A
117281SN/A/*
118281SN/A * Command wrappers
119281SN/A */
120281SN/Astatic int	amr_query_controller(struct amr_softc *sc);
121281SN/Astatic void	*amr_enquiry(struct amr_softc *sc, size_t bufsize,
122281SN/A			     u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual);
123281SN/Astatic void	amr_completeio(struct amr_command *ac);
124281SN/Astatic int	amr_support_ext_cdb(struct amr_softc *sc);
125281SN/A
126281SN/A/*
127281SN/A * Command buffer allocation.
128281SN/A */
129281SN/Astatic void	amr_alloccmd_cluster(struct amr_softc *sc);
130281SN/Astatic void	amr_freecmd_cluster(struct amr_command_cluster *acc);
131281SN/A
132281SN/A/*
133281SN/A * Command processing.
134281SN/A */
135281SN/Astatic int	amr_bio_command(struct amr_softc *sc, struct amr_command **acp);
136281SN/Astatic int	amr_wait_command(struct amr_command *ac);
137281SN/Astatic int	amr_getslot(struct amr_command *ac);
138281SN/Astatic void	amr_mapcmd(struct amr_command *ac);
139281SN/Astatic void	amr_unmapcmd(struct amr_command *ac);
140281SN/Astatic int	amr_start(struct amr_command *ac);
141281SN/Astatic void	amr_complete(void *context, int pending);
142281SN/A
143281SN/A/*
144281SN/A * Status monitoring
145281SN/A */
146281SN/Astatic void	amr_periodic(void *data);
147281SN/A
148281SN/A/*
149281SN/A * Interface-specific shims
150281SN/A */
151281SN/Astatic int	amr_quartz_submit_command(struct amr_softc *sc);
152281SN/Astatic int	amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
153281SN/Astatic int	amr_quartz_poll_command(struct amr_command *ac);
154281SN/A
155281SN/Astatic int	amr_std_submit_command(struct amr_softc *sc);
156281SN/Astatic int	amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave);
157281SN/Astatic int	amr_std_poll_command(struct amr_command *ac);
158281SN/Astatic void	amr_std_attach_mailbox(struct amr_softc *sc);
159281SN/A
160281SN/A#ifdef AMR_BOARD_INIT
161281SN/Astatic int	amr_quartz_init(struct amr_softc *sc);
162281SN/Astatic int	amr_std_init(struct amr_softc *sc);
163281SN/A#endif
164281SN/A
165281SN/A/*
166281SN/A * Debugging
167281SN/A */
168281SN/Astatic void	amr_describe_controller(struct amr_softc *sc);
169281SN/A#ifdef AMR_DEBUG
170281SN/A#if 0
171281SN/Astatic void	amr_printcommand(struct amr_command *ac);
172281SN/A#endif
173281SN/A#endif
174281SN/A
175281SN/A/********************************************************************************
176281SN/A ********************************************************************************
177281SN/A                                                                      Inline Glue
178281SN/A ********************************************************************************
179281SN/A ********************************************************************************/
180281SN/A
181281SN/A/********************************************************************************
182281SN/A ********************************************************************************
183281SN/A                                                                Public Interfaces
184281SN/A ********************************************************************************
185281SN/A ********************************************************************************/
186281SN/A
187281SN/A/********************************************************************************
188281SN/A * Initialise the controller and softc.
189281SN/A */
190281SN/Aint
191281SN/Aamr_attach(struct amr_softc *sc)
192281SN/A{
193281SN/A
194281SN/A    debug_called(1);
195281SN/A
196281SN/A    /*
197281SN/A     * Initialise per-controller queues.
198281SN/A     */
199281SN/A    TAILQ_INIT(&sc->amr_completed);
200281SN/A    TAILQ_INIT(&sc->amr_freecmds);
201281SN/A    TAILQ_INIT(&sc->amr_cmd_clusters);
202281SN/A    TAILQ_INIT(&sc->amr_ready);
203281SN/A    bioq_init(&sc->amr_bioq);
204281SN/A
205281SN/A#if __FreeBSD_version >= 500005
206281SN/A    /*
207281SN/A     * Initialise command-completion task.
208281SN/A     */
209281SN/A    TASK_INIT(&sc->amr_task_complete, 0, amr_complete, sc);
210281SN/A#endif
211281SN/A
212281SN/A    debug(2, "queue init done");
213281SN/A
214281SN/A    /*
215281SN/A     * Configure for this controller type.
216281SN/A     */
217281SN/A    if (AMR_IS_QUARTZ(sc)) {
218281SN/A	sc->amr_submit_command = amr_quartz_submit_command;
219281SN/A	sc->amr_get_work       = amr_quartz_get_work;
220281SN/A	sc->amr_poll_command   = amr_quartz_poll_command;
221281SN/A    } else {
222281SN/A	sc->amr_submit_command = amr_std_submit_command;
223281SN/A	sc->amr_get_work       = amr_std_get_work;
224281SN/A	sc->amr_poll_command   = amr_std_poll_command;
225281SN/A	amr_std_attach_mailbox(sc);;
226281SN/A    }
227281SN/A
228281SN/A#ifdef AMR_BOARD_INIT
229281SN/A    if ((AMR_IS_QUARTZ(sc) ? amr_quartz_init(sc) : amr_std_init(sc))))
230281SN/A	return(ENXIO);
231281SN/A#endif
232281SN/A
233281SN/A    /*
234281SN/A     * Quiz controller for features and limits.
235281SN/A     */
236281SN/A    if (amr_query_controller(sc))
237281SN/A	return(ENXIO);
238281SN/A
239281SN/A    debug(2, "controller query complete");
240281SN/A
241281SN/A    /*
242     * Attach our 'real' SCSI channels to CAM.
243     */
244    if (amr_cam_attach(sc))
245	return(ENXIO);
246    debug(2, "CAM attach done");
247
248    /*
249     * Create the control device.
250     */
251    sc->amr_dev_t = make_dev(&amr_cdevsw, device_get_unit(sc->amr_dev), UID_ROOT, GID_OPERATOR,
252			     S_IRUSR | S_IWUSR, "amr%d", device_get_unit(sc->amr_dev));
253    sc->amr_dev_t->si_drv1 = sc;
254
255    /*
256     * Schedule ourselves to bring the controller up once interrupts are
257     * available.
258     */
259    bzero(&sc->amr_ich, sizeof(struct intr_config_hook));
260    sc->amr_ich.ich_func = amr_startup;
261    sc->amr_ich.ich_arg = sc;
262    if (config_intrhook_establish(&sc->amr_ich) != 0) {
263	device_printf(sc->amr_dev, "can't establish configuration hook\n");
264	return(ENOMEM);
265    }
266
267    /*
268     * Print a little information about the controller.
269     */
270    amr_describe_controller(sc);
271
272    debug(2, "attach complete");
273    return(0);
274}
275
276/********************************************************************************
277 * Locate disk resources and attach children to them.
278 */
279static void
280amr_startup(void *arg)
281{
282    struct amr_softc	*sc = (struct amr_softc *)arg;
283    struct amr_logdrive	*dr;
284    int			i, error;
285
286    debug_called(1);
287
288    /* pull ourselves off the intrhook chain */
289    config_intrhook_disestablish(&sc->amr_ich);
290
291    /* get up-to-date drive information */
292    if (amr_query_controller(sc)) {
293	device_printf(sc->amr_dev, "can't scan controller for drives\n");
294	return;
295    }
296
297    /* iterate over available drives */
298    for (i = 0, dr = &sc->amr_drive[0]; (i < AMR_MAXLD) && (dr->al_size != 0xffffffff); i++, dr++) {
299	/* are we already attached to this drive? */
300	if (dr->al_disk == 0) {
301	    /* generate geometry information */
302	    if (dr->al_size > 0x200000) {	/* extended translation? */
303		dr->al_heads = 255;
304		dr->al_sectors = 63;
305	    } else {
306		dr->al_heads = 64;
307		dr->al_sectors = 32;
308	    }
309	    dr->al_cylinders = dr->al_size / (dr->al_heads * dr->al_sectors);
310
311	    dr->al_disk = device_add_child(sc->amr_dev, NULL, -1);
312	    if (dr->al_disk == 0)
313		device_printf(sc->amr_dev, "device_add_child failed\n");
314	    device_set_ivars(dr->al_disk, dr);
315	}
316    }
317
318    if ((error = bus_generic_attach(sc->amr_dev)) != 0)
319	device_printf(sc->amr_dev, "bus_generic_attach returned %d\n", error);
320
321    /* mark controller back up */
322    sc->amr_state &= ~AMR_STATE_SHUTDOWN;
323
324    /* interrupts will be enabled before we do anything more */
325    sc->amr_state |= AMR_STATE_INTEN;
326
327    /*
328     * Start the timeout routine.
329     */
330/*    sc->amr_timeout = timeout(amr_periodic, sc, hz);*/
331
332    return;
333}
334
335/*******************************************************************************
336 * Free resources associated with a controller instance
337 */
338void
339amr_free(struct amr_softc *sc)
340{
341    struct amr_command_cluster	*acc;
342
343    /* detach from CAM */
344    amr_cam_detach(sc);
345
346    /* cancel status timeout */
347    untimeout(amr_periodic, sc, sc->amr_timeout);
348
349    /* throw away any command buffers */
350    while ((acc = TAILQ_FIRST(&sc->amr_cmd_clusters)) != NULL) {
351	TAILQ_REMOVE(&sc->amr_cmd_clusters, acc, acc_link);
352	amr_freecmd_cluster(acc);
353    }
354
355    /* destroy control device */
356    if( sc->amr_dev_t != (dev_t)NULL)
357	    destroy_dev(sc->amr_dev_t);
358}
359
360/*******************************************************************************
361 * Receive a bio structure from a child device and queue it on a particular
362 * disk resource, then poke the disk resource to start as much work as it can.
363 */
364int
365amr_submit_bio(struct amr_softc *sc, struct bio *bio)
366{
367    debug_called(2);
368
369    amr_enqueue_bio(sc, bio);
370    amr_startio(sc);
371    return(0);
372}
373
374/********************************************************************************
375 * Accept an open operation on the control device.
376 */
377static int
378amr_open(dev_t dev, int flags, int fmt, d_thread_t *td)
379{
380    int			unit = minor(dev);
381    struct amr_softc	*sc = devclass_get_softc(devclass_find("amr"), unit);
382
383    debug_called(1);
384
385    sc->amr_state |= AMR_STATE_OPEN;
386    return(0);
387}
388
389/********************************************************************************
390 * Accept the last close on the control device.
391 */
392static int
393amr_close(dev_t dev, int flags, int fmt, d_thread_t *td)
394{
395    int			unit = minor(dev);
396    struct amr_softc	*sc = devclass_get_softc(devclass_find("amr"), unit);
397
398    debug_called(1);
399
400    sc->amr_state &= ~AMR_STATE_OPEN;
401    return (0);
402}
403
404/********************************************************************************
405 * Handle controller-specific control operations.
406 */
407static int
408amr_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, d_thread_t *td)
409{
410    struct amr_softc		*sc = (struct amr_softc *)dev->si_drv1;
411    int				*arg = (int *)addr;
412    struct amr_user_ioctl	*au = (struct amr_user_ioctl *)addr;
413    struct amr_command		*ac;
414    struct amr_mailbox_ioctl	*mbi;
415    struct amr_passthrough	*ap;
416    void			*dp;
417    int				error;
418
419    debug_called(1);
420
421    error = 0;
422    dp = NULL;
423    ap = NULL;
424    ac = NULL;
425    switch(cmd) {
426
427    case AMR_IO_VERSION:
428	debug(1, "AMR_IO_VERSION");
429	*arg = AMR_IO_VERSION_NUMBER;
430	break;
431
432    case AMR_IO_COMMAND:
433	debug(1, "AMR_IO_COMMAND  0x%x", au->au_cmd[0]);
434	/* handle inbound data buffer */
435	if (au->au_length != 0) {
436	    if ((dp = malloc(au->au_length, M_DEVBUF, M_WAITOK)) == NULL) {
437		error = ENOMEM;
438		break;
439	    }
440	    if ((error = copyin(au->au_buffer, dp, au->au_length)) != 0)
441		break;
442	    debug(2, "copyin %ld bytes from %p -> %p", au->au_length, au->au_buffer, dp);
443	}
444
445	if ((ac = amr_alloccmd(sc)) == NULL) {
446	    error = ENOMEM;
447	    break;
448	}
449
450	/* handle SCSI passthrough command */
451	if (au->au_cmd[0] == AMR_CMD_PASS) {
452	    if ((ap = malloc(sizeof(*ap), M_DEVBUF, M_WAITOK | M_ZERO)) == NULL) {
453		error = ENOMEM;
454		break;
455	    }
456
457	    /* copy cdb */
458	    ap->ap_cdb_length = au->au_cmd[2];
459	    bcopy(&au->au_cmd[3], &ap->ap_cdb[0], ap->ap_cdb_length);
460
461	    /* build passthrough */
462	    ap->ap_timeout		= au->au_cmd[ap->ap_cdb_length + 3] & 0x07;
463	    ap->ap_ars			= (au->au_cmd[ap->ap_cdb_length + 3] & 0x08) ? 1 : 0;
464	    ap->ap_islogical		= (au->au_cmd[ap->ap_cdb_length + 3] & 0x80) ? 1 : 0;
465	    ap->ap_logical_drive_no	= au->au_cmd[ap->ap_cdb_length + 4];
466	    ap->ap_channel		= au->au_cmd[ap->ap_cdb_length + 5];
467	    ap->ap_scsi_id 		= au->au_cmd[ap->ap_cdb_length + 6];
468	    ap->ap_request_sense_length	= 14;
469	    ap->ap_data_transfer_length = au->au_length;
470	    /* XXX what about the request-sense area? does the caller want it? */
471
472	    /* build command */
473	    ac->ac_data = ap;
474	    ac->ac_length = sizeof(*ap);
475	    ac->ac_flags |= AMR_CMD_DATAOUT;
476	    ac->ac_ccb_data = dp;
477	    ac->ac_ccb_length = au->au_length;
478	    if (au->au_direction & AMR_IO_READ)
479		ac->ac_flags |= AMR_CMD_CCB_DATAIN;
480	    if (au->au_direction & AMR_IO_WRITE)
481		ac->ac_flags |= AMR_CMD_CCB_DATAOUT;
482
483	    ac->ac_mailbox.mb_command = AMR_CMD_PASS;
484
485	} else {
486	    /* direct command to controller */
487	    mbi = (struct amr_mailbox_ioctl *)&ac->ac_mailbox;
488
489	    /* copy pertinent mailbox items */
490	    mbi->mb_command = au->au_cmd[0];
491	    mbi->mb_channel = au->au_cmd[1];
492	    mbi->mb_param = au->au_cmd[2];
493	    mbi->mb_pad[0] = au->au_cmd[3];
494	    mbi->mb_drive = au->au_cmd[4];
495
496	    /* build the command */
497	    ac->ac_data = dp;
498	    ac->ac_length = au->au_length;
499	    if (au->au_direction & AMR_IO_READ)
500		ac->ac_flags |= AMR_CMD_DATAIN;
501	    if (au->au_direction & AMR_IO_WRITE)
502		ac->ac_flags |= AMR_CMD_DATAOUT;
503	}
504
505	/* run the command */
506	if ((error = amr_wait_command(ac)) != 0)
507	    break;
508
509	/* copy out data and set status */
510	if (au->au_length != 0)
511	    error = copyout(dp, au->au_buffer, au->au_length);
512	debug(2, "copyout %ld bytes from %p -> %p", au->au_length, dp, au->au_buffer);
513	if (dp != NULL)
514	    debug(2, "%16d", (int)dp);
515	au->au_status = ac->ac_status;
516	break;
517
518    default:
519	debug(1, "unknown ioctl 0x%lx", cmd);
520	error = ENOIOCTL;
521	break;
522    }
523
524    if (dp != NULL)
525	free(dp, M_DEVBUF);
526    if (ap != NULL)
527	free(ap, M_DEVBUF);
528    if (ac != NULL)
529	amr_releasecmd(ac);
530    return(error);
531}
532
533/********************************************************************************
534 ********************************************************************************
535                                                                Status Monitoring
536 ********************************************************************************
537 ********************************************************************************/
538
539/********************************************************************************
540 * Perform a periodic check of the controller status
541 */
542static void
543amr_periodic(void *data)
544{
545    struct amr_softc	*sc = (struct amr_softc *)data;
546
547    debug_called(2);
548
549    /* XXX perform periodic status checks here */
550
551    /* compensate for missed interrupts */
552    amr_done(sc);
553
554    /* reschedule */
555    sc->amr_timeout = timeout(amr_periodic, sc, hz);
556}
557
558/********************************************************************************
559 ********************************************************************************
560                                                                 Command Wrappers
561 ********************************************************************************
562 ********************************************************************************/
563
564/********************************************************************************
565 * Interrogate the controller for the operational parameters we require.
566 */
567static int
568amr_query_controller(struct amr_softc *sc)
569{
570    struct amr_enquiry3	*aex;
571    struct amr_prodinfo	*ap;
572    struct amr_enquiry	*ae;
573    int			ldrv;
574
575    /*
576     * If we haven't found the real limit yet, let us have a couple of commands in
577     * order to be able to probe.
578     */
579    if (sc->amr_maxio == 0)
580	sc->amr_maxio = 2;
581
582    /*
583     * Greater than 10 byte cdb support
584     */
585    sc->support_ext_cdb = amr_support_ext_cdb(sc);
586
587    if(sc->support_ext_cdb) {
588	debug(2,"supports extended CDBs.");
589    }
590
591    /*
592     * Try to issue an ENQUIRY3 command
593     */
594    if ((aex = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_ENQ3,
595			   AMR_CONFIG_ENQ3_SOLICITED_FULL)) != NULL) {
596
597	/*
598	 * Fetch current state of logical drives.
599	 */
600	for (ldrv = 0; ldrv < aex->ae_numldrives; ldrv++) {
601	    sc->amr_drive[ldrv].al_size       = aex->ae_drivesize[ldrv];
602	    sc->amr_drive[ldrv].al_state      = aex->ae_drivestate[ldrv];
603	    sc->amr_drive[ldrv].al_properties = aex->ae_driveprop[ldrv];
604	    debug(2, "  drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size,
605		  sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties);
606	}
607	free(aex, M_DEVBUF);
608
609	/*
610	 * Get product info for channel count.
611	 */
612	if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0)) == NULL) {
613	    device_printf(sc->amr_dev, "can't obtain product data from controller\n");
614	    return(1);
615	}
616	sc->amr_maxdrives = 40;
617	sc->amr_maxchan = ap->ap_nschan;
618	sc->amr_maxio = ap->ap_maxio;
619	sc->amr_type |= AMR_TYPE_40LD;
620	free(ap, M_DEVBUF);
621
622    } else {
623
624	/* failed, try the 8LD ENQUIRY commands */
625	if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0)) == NULL) {
626	    if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0)) == NULL) {
627		device_printf(sc->amr_dev, "can't obtain configuration data from controller\n");
628		return(1);
629	    }
630	    ae->ae_signature = 0;
631	}
632
633	/*
634	 * Fetch current state of logical drives.
635	 */
636	for (ldrv = 0; ldrv < ae->ae_ldrv.al_numdrives; ldrv++) {
637	    sc->amr_drive[ldrv].al_size       = ae->ae_ldrv.al_size[ldrv];
638	    sc->amr_drive[ldrv].al_state      = ae->ae_ldrv.al_state[ldrv];
639	    sc->amr_drive[ldrv].al_properties = ae->ae_ldrv.al_properties[ldrv];
640	    debug(2, "  drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size,
641		  sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties);
642	}
643
644	sc->amr_maxdrives = 8;
645	sc->amr_maxchan = ae->ae_adapter.aa_channels;
646	sc->amr_maxio = ae->ae_adapter.aa_maxio;
647	free(ae, M_DEVBUF);
648    }
649
650    /*
651     * Mark remaining drives as unused.
652     */
653    for (; ldrv < AMR_MAXLD; ldrv++)
654	sc->amr_drive[ldrv].al_size = 0xffffffff;
655
656    /*
657     * Cap the maximum number of outstanding I/Os.  AMI's Linux driver doesn't trust
658     * the controller's reported value, and lockups have been seen when we do.
659     */
660    sc->amr_maxio = imin(sc->amr_maxio, AMR_LIMITCMD);
661
662    return(0);
663}
664
665/********************************************************************************
666 * Run a generic enquiry-style command.
667 */
668static void *
669amr_enquiry(struct amr_softc *sc, size_t bufsize, u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual)
670{
671    struct amr_command	*ac;
672    void		*result;
673    u_int8_t		*mbox;
674    int			error;
675
676    debug_called(1);
677
678    error = 1;
679    result = NULL;
680
681    /* get ourselves a command buffer */
682    if ((ac = amr_alloccmd(sc)) == NULL)
683	goto out;
684    /* allocate the response structure */
685    if ((result = malloc(bufsize, M_DEVBUF, M_NOWAIT)) == NULL)
686	goto out;
687    /* set command flags */
688    ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
689
690    /* point the command at our data */
691    ac->ac_data = result;
692    ac->ac_length = bufsize;
693
694    /* build the command proper */
695    mbox = (u_int8_t *)&ac->ac_mailbox;		/* XXX want a real structure for this? */
696    mbox[0] = cmd;
697    mbox[2] = cmdsub;
698    mbox[3] = cmdqual;
699
700    /* can't assume that interrupts are going to work here, so play it safe */
701    if (sc->amr_poll_command(ac))
702	goto out;
703    error = ac->ac_status;
704
705 out:
706    if (ac != NULL)
707	amr_releasecmd(ac);
708    if ((error != 0) && (result != NULL)) {
709	free(result, M_DEVBUF);
710	result = NULL;
711    }
712    return(result);
713}
714
715/********************************************************************************
716 * Flush the controller's internal cache, return status.
717 */
718int
719amr_flush(struct amr_softc *sc)
720{
721    struct amr_command	*ac;
722    int			error;
723
724    /* get ourselves a command buffer */
725    error = 1;
726    if ((ac = amr_alloccmd(sc)) == NULL)
727	goto out;
728    /* set command flags */
729    ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
730
731    /* build the command proper */
732    ac->ac_mailbox.mb_command = AMR_CMD_FLUSH;
733
734    /* we have to poll, as the system may be going down or otherwise damaged */
735    if (sc->amr_poll_command(ac))
736	goto out;
737    error = ac->ac_status;
738
739 out:
740    if (ac != NULL)
741	amr_releasecmd(ac);
742    return(error);
743}
744
745/********************************************************************************
746 * Detect extented cdb >> greater than 10 byte cdb support
747 * returns '1' means this support exist
748 * returns '0' means this support doesn't exist
749 */
750static int
751amr_support_ext_cdb(struct amr_softc *sc)
752{
753    struct amr_command	*ac;
754    u_int8_t		*mbox;
755    int			error;
756
757    /* get ourselves a command buffer */
758    error = 0;
759    if ((ac = amr_alloccmd(sc)) == NULL)
760	goto out;
761    /* set command flags */
762    ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT;
763
764    /* build the command proper */
765    mbox = (u_int8_t *)&ac->ac_mailbox;		/* XXX want a real structure for this? */
766    mbox[0] = 0xA4;
767    mbox[2] = 0x16;
768
769
770    /* we have to poll, as the system may be going down or otherwise damaged */
771    if (sc->amr_poll_command(ac))
772	goto out;
773    if( ac->ac_status == AMR_STATUS_SUCCESS ) {
774	    error = 1;
775    }
776
777out:
778    if (ac != NULL)
779	amr_releasecmd(ac);
780    return(error);
781}
782
783/********************************************************************************
784 * Try to find I/O work for the controller from one or more of the work queues.
785 *
786 * We make the assumption that if the controller is not ready to take a command
787 * at some given time, it will generate an interrupt at some later time when
788 * it is.
789 */
790void
791amr_startio(struct amr_softc *sc)
792{
793    struct amr_command	*ac;
794
795    /* spin until something prevents us from doing any work */
796    for (;;) {
797
798	/* try to get a ready command */
799	ac = amr_dequeue_ready(sc);
800
801	/* if that failed, build a command from a bio */
802	if (ac == NULL)
803	    (void)amr_bio_command(sc, &ac);
804
805	/* if that failed, build a command from a ccb */
806	if (ac == NULL)
807	    (void)amr_cam_command(sc, &ac);
808
809	/* if we don't have anything to do, give up */
810	if (ac == NULL)
811	    break;
812
813	/* try to give the command to the controller; if this fails save it for later and give up */
814	if (amr_start(ac)) {
815	    debug(2, "controller busy, command deferred");
816	    amr_requeue_ready(ac);	/* XXX schedule retry very soon? */
817	    break;
818	}
819    }
820}
821
822/********************************************************************************
823 * Handle completion of an I/O command.
824 */
825static void
826amr_completeio(struct amr_command *ac)
827{
828    struct amr_softc	*sc = ac->ac_sc;
829
830    if (ac->ac_status != AMR_STATUS_SUCCESS) {	/* could be more verbose here? */
831	ac->ac_bio->bio_error = EIO;
832	ac->ac_bio->bio_flags |= BIO_ERROR;
833
834	device_printf(sc->amr_dev, "I/O error - 0x%x\n", ac->ac_status);
835/*	amr_printcommand(ac);*/
836    }
837    amrd_intr(ac->ac_bio);
838    amr_releasecmd(ac);
839}
840
841/********************************************************************************
842 ********************************************************************************
843                                                               Command Processing
844 ********************************************************************************
845 ********************************************************************************/
846
847/********************************************************************************
848 * Convert a bio off the top of the bio queue into a command.
849 */
850static int
851amr_bio_command(struct amr_softc *sc, struct amr_command **acp)
852{
853    struct amr_command	*ac;
854    struct amrd_softc	*amrd;
855    struct bio		*bio;
856    int			error;
857    int			blkcount;
858    int			driveno;
859    int			cmd;
860
861    ac = NULL;
862    error = 0;
863
864    /* get a bio to work on */
865    if ((bio = amr_dequeue_bio(sc)) == NULL)
866	goto out;
867
868    /* get a command */
869    if ((ac = amr_alloccmd(sc)) == NULL) {
870	error = ENOMEM;
871	goto out;
872    }
873
874    /* connect the bio to the command */
875    ac->ac_complete = amr_completeio;
876    ac->ac_bio = bio;
877    ac->ac_data = bio->bio_data;
878    ac->ac_length = bio->bio_bcount;
879    if (BIO_IS_READ(bio)) {
880	ac->ac_flags |= AMR_CMD_DATAIN;
881	cmd = AMR_CMD_LREAD;
882    } else {
883	ac->ac_flags |= AMR_CMD_DATAOUT;
884	cmd = AMR_CMD_LWRITE;
885    }
886    amrd = (struct amrd_softc *)bio->bio_disk->d_drv1;
887    driveno = amrd->amrd_drive - sc->amr_drive;
888    blkcount = (bio->bio_bcount + AMR_BLKSIZE - 1) / AMR_BLKSIZE;
889
890    ac->ac_mailbox.mb_command = cmd;
891    ac->ac_mailbox.mb_blkcount = blkcount;
892    ac->ac_mailbox.mb_lba = bio->bio_pblkno;
893    ac->ac_mailbox.mb_drive = driveno;
894    /* we fill in the s/g related data when the command is mapped */
895
896    if ((bio->bio_pblkno + blkcount) > sc->amr_drive[driveno].al_size)
897	device_printf(sc->amr_dev, "I/O beyond end of unit (%lld,%d > %lu)\n",
898		      (long long)bio->bio_pblkno, blkcount,
899		      (u_long)sc->amr_drive[driveno].al_size);
900
901out:
902    if (error != 0) {
903	if (ac != NULL)
904	    amr_releasecmd(ac);
905	if (bio != NULL)			/* this breaks ordering... */
906	    amr_enqueue_bio(sc, bio);
907    }
908    *acp = ac;
909    return(error);
910}
911
912/********************************************************************************
913 * Take a command, submit it to the controller and sleep until it completes
914 * or fails.  Interrupts must be enabled, returns nonzero on error.
915 */
916static int
917amr_wait_command(struct amr_command *ac)
918{
919    int			error, count;
920
921    debug_called(1);
922
923    ac->ac_complete = NULL;
924    ac->ac_flags |= AMR_CMD_SLEEP;
925    if ((error = amr_start(ac)) != 0)
926	return(error);
927
928    count = 0;
929    /* XXX better timeout? */
930    while ((ac->ac_flags & AMR_CMD_BUSY) && (count < 30)) {
931	tsleep(ac, PRIBIO | PCATCH, "amrwcmd", hz);
932    }
933    return(0);
934}
935
936/********************************************************************************
937 * Take a command, submit it to the controller and busy-wait for it to return.
938 * Returns nonzero on error.  Can be safely called with interrupts enabled.
939 */
940static int
941amr_std_poll_command(struct amr_command *ac)
942{
943    struct amr_softc	*sc = ac->ac_sc;
944    int			error, count;
945
946    debug_called(2);
947
948    ac->ac_complete = NULL;
949    if ((error = amr_start(ac)) != 0)
950	return(error);
951
952    count = 0;
953    do {
954	/*
955	 * Poll for completion, although the interrupt handler may beat us to it.
956	 * Note that the timeout here is somewhat arbitrary.
957	 */
958	amr_done(sc);
959	DELAY(1000);
960    } while ((ac->ac_flags & AMR_CMD_BUSY) && (count++ < 1000));
961    if (!(ac->ac_flags & AMR_CMD_BUSY)) {
962	error = 0;
963    } else {
964	/* XXX the slot is now marked permanently busy */
965	error = EIO;
966	device_printf(sc->amr_dev, "polled command timeout\n");
967    }
968    return(error);
969}
970
971/********************************************************************************
972 * Take a command, submit it to the controller and busy-wait for it to return.
973 * Returns nonzero on error.  Can be safely called with interrupts enabled.
974 */
975static int
976amr_quartz_poll_command(struct amr_command *ac)
977{
978    struct amr_softc	*sc = ac->ac_sc;
979    int			s;
980    int			error,count;
981
982    debug_called(2);
983
984    /* now we have a slot, we can map the command (unmapped in amr_complete) */
985    amr_mapcmd(ac);
986
987    s = splbio();
988
989    count=0;
990    while (sc->amr_busyslots){
991	tsleep(sc, PRIBIO | PCATCH, "amrpoll", hz);
992	if(count++>10) {
993	    break;
994	}
995    }
996
997    if(sc->amr_busyslots) {
998	device_printf(sc->amr_dev, "adapter is busy\n");
999	splx(s);
1000	amr_unmapcmd(ac);
1001    	ac->ac_status=0;
1002	return(1);
1003    }
1004
1005    bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, AMR_MBOX_CMDSIZE);
1006
1007    /* clear the poll/ack fields in the mailbox */
1008    sc->amr_mailbox->mb_ident = 0xFE;
1009    sc->amr_mailbox->mb_nstatus = 0xFF;
1010    sc->amr_mailbox->mb_status = 0xFF;
1011    sc->amr_mailbox->mb_poll = 0;
1012    sc->amr_mailbox->mb_ack = 0;
1013    sc->amr_mailbox->mb_busy = 1;
1014
1015    AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT);
1016
1017    while(sc->amr_mailbox->mb_nstatus == 0xFF);
1018    while(sc->amr_mailbox->mb_status == 0xFF);
1019    ac->ac_status=sc->amr_mailbox->mb_status;
1020    error = (ac->ac_status !=AMR_STATUS_SUCCESS) ? 1:0;
1021    while(sc->amr_mailbox->mb_poll != 0x77);
1022    sc->amr_mailbox->mb_poll = 0;
1023    sc->amr_mailbox->mb_ack = 0x77;
1024
1025    /* acknowledge that we have the commands */
1026    AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK);
1027    while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK);
1028
1029    splx(s);
1030
1031    /* unmap the command's data buffer */
1032    amr_unmapcmd(ac);
1033
1034    return(error);
1035}
1036
1037/********************************************************************************
1038 * Get a free command slot for a command if it doesn't already have one.
1039 *
1040 * May be safely called multiple times for a given command.
1041 */
1042static int
1043amr_getslot(struct amr_command *ac)
1044{
1045    struct amr_softc	*sc = ac->ac_sc;
1046    int			s, slot, limit, error;
1047
1048    debug_called(3);
1049
1050    /* if the command already has a slot, don't try to give it another one */
1051    if (ac->ac_slot != 0)
1052	return(0);
1053
1054    /* enforce slot usage limit */
1055    limit = (ac->ac_flags & AMR_CMD_PRIORITY) ? sc->amr_maxio : sc->amr_maxio - 4;
1056    if (sc->amr_busyslots > limit)
1057	return(EBUSY);
1058
1059    /*
1060     * Allocate a slot.  XXX linear scan is slow
1061     */
1062    error = EBUSY;
1063    s = splbio();
1064    for (slot = 0; slot < sc->amr_maxio; slot++) {
1065	if (sc->amr_busycmd[slot] == NULL) {
1066	    sc->amr_busycmd[slot] = ac;
1067	    sc->amr_busyslots++;
1068	    ac->ac_slot = slot;
1069	    error = 0;
1070	    break;
1071	}
1072    }
1073    splx(s);
1074
1075    return(error);
1076}
1077
1078/********************************************************************************
1079 * Map/unmap (ac)'s data in the controller's addressable space as required.
1080 *
1081 * These functions may be safely called multiple times on a given command.
1082 */
1083static void
1084amr_setup_dmamap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1085{
1086    struct amr_command	*ac = (struct amr_command *)arg;
1087    struct amr_softc	*sc = ac->ac_sc;
1088    struct amr_sgentry	*sg;
1089    int			i;
1090    u_int8_t		*sgc;
1091
1092    debug_called(3);
1093
1094    /* get base address of s/g table */
1095    sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
1096
1097    /* save data physical address */
1098    ac->ac_dataphys = segs[0].ds_addr;
1099
1100    /* for AMR_CMD_CONFIG the s/g count goes elsewhere */
1101    if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG) {
1102	sgc = &(((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param);
1103    } else {
1104	sgc = &ac->ac_mailbox.mb_nsgelem;
1105    }
1106
1107    /* decide whether we need to populate the s/g table */
1108    if (nsegments < 2) {
1109	*sgc = 0;
1110	ac->ac_mailbox.mb_nsgelem = 0;
1111	ac->ac_mailbox.mb_physaddr = ac->ac_dataphys;
1112    } else {
1113        ac->ac_mailbox.mb_nsgelem = nsegments;
1114	*sgc = nsegments;
1115	ac->ac_mailbox.mb_physaddr = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry));
1116	for (i = 0; i < nsegments; i++, sg++) {
1117	    sg->sg_addr = segs[i].ds_addr;
1118	    sg->sg_count = segs[i].ds_len;
1119	}
1120    }
1121}
1122
1123static void
1124amr_setup_ccbmap(void *arg, bus_dma_segment_t *segs, int nsegments, int error)
1125{
1126    struct amr_command          *ac = (struct amr_command *)arg;
1127    struct amr_softc            *sc = ac->ac_sc;
1128    struct amr_sgentry          *sg;
1129    struct amr_passthrough      *ap = (struct amr_passthrough *)ac->ac_data;
1130    struct amr_ext_passthrough	*aep = (struct amr_ext_passthrough *)ac->ac_data;
1131    int                         i;
1132
1133    /* get base address of s/g table */
1134    sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
1135
1136    /* decide whether we need to populate the s/g table */
1137    if( ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS ) {
1138	if (nsegments < 2) {
1139	    aep->ap_no_sg_elements = 0;
1140	    aep->ap_data_transfer_address =  segs[0].ds_addr;
1141	} else {
1142	    /* save s/g table information in passthrough */
1143	    aep->ap_no_sg_elements = nsegments;
1144	    aep->ap_data_transfer_address = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry));
1145	    /* populate s/g table (overwrites previous call which mapped the passthrough) */
1146	    for (i = 0; i < nsegments; i++, sg++) {
1147		sg->sg_addr = segs[i].ds_addr;
1148		sg->sg_count = segs[i].ds_len;
1149		debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count);
1150	    }
1151	}
1152	debug(3, "slot %d  %d segments at 0x%x, passthrough at 0x%x", ac->ac_slot,
1153	    aep->ap_no_sg_elements, aep->ap_data_transfer_address, ac->ac_dataphys);
1154    } else {
1155	if (nsegments < 2) {
1156	    ap->ap_no_sg_elements = 0;
1157	    ap->ap_data_transfer_address =  segs[0].ds_addr;
1158	} else {
1159	    /* save s/g table information in passthrough */
1160	    ap->ap_no_sg_elements = nsegments;
1161	    ap->ap_data_transfer_address = sc->amr_sgbusaddr + (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry));
1162	    /* populate s/g table (overwrites previous call which mapped the passthrough) */
1163	    for (i = 0; i < nsegments; i++, sg++) {
1164		sg->sg_addr = segs[i].ds_addr;
1165		sg->sg_count = segs[i].ds_len;
1166		debug(3, " %d: 0x%x/%d", i, sg->sg_addr, sg->sg_count);
1167	    }
1168	}
1169	debug(3, "slot %d  %d segments at 0x%x, passthrough at 0x%x", ac->ac_slot,
1170	    ap->ap_no_sg_elements, ap->ap_data_transfer_address, ac->ac_dataphys);
1171    }
1172}
1173
1174static void
1175amr_mapcmd(struct amr_command *ac)
1176{
1177    struct amr_softc	*sc = ac->ac_sc;
1178
1179    debug_called(3);
1180
1181    /* if the command involves data at all, and hasn't been mapped */
1182    if (!(ac->ac_flags & AMR_CMD_MAPPED)) {
1183
1184	if (ac->ac_data != NULL) {
1185	    /* map the data buffers into bus space and build the s/g list */
1186	    bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_dmamap, ac->ac_data, ac->ac_length,
1187			    amr_setup_dmamap, ac, 0);
1188	    if (ac->ac_flags & AMR_CMD_DATAIN)
1189		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREREAD);
1190	    if (ac->ac_flags & AMR_CMD_DATAOUT)
1191		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_PREWRITE);
1192	}
1193
1194	if (ac->ac_ccb_data != NULL) {
1195	    bus_dmamap_load(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, ac->ac_ccb_data, ac->ac_ccb_length,
1196			    amr_setup_ccbmap, ac, 0);
1197	    if (ac->ac_flags & AMR_CMD_CCB_DATAIN)
1198		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_PREREAD);
1199	    if (ac->ac_flags & AMR_CMD_CCB_DATAOUT)
1200		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_PREWRITE);
1201	}
1202	ac->ac_flags |= AMR_CMD_MAPPED;
1203    }
1204}
1205
1206static void
1207amr_unmapcmd(struct amr_command *ac)
1208{
1209    struct amr_softc	*sc = ac->ac_sc;
1210
1211    debug_called(3);
1212
1213    /* if the command involved data at all and was mapped */
1214    if (ac->ac_flags & AMR_CMD_MAPPED) {
1215
1216	if (ac->ac_data != NULL) {
1217	    if (ac->ac_flags & AMR_CMD_DATAIN)
1218		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTREAD);
1219	    if (ac->ac_flags & AMR_CMD_DATAOUT)
1220		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTWRITE);
1221	    bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap);
1222	}
1223
1224	if (ac->ac_ccb_data != NULL) {
1225	    if (ac->ac_flags & AMR_CMD_CCB_DATAIN)
1226		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_POSTREAD);
1227	    if (ac->ac_flags & AMR_CMD_CCB_DATAOUT)
1228		bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_ccb_dmamap, BUS_DMASYNC_POSTWRITE);
1229	    bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_ccb_dmamap);
1230	}
1231	ac->ac_flags &= ~AMR_CMD_MAPPED;
1232    }
1233}
1234
1235/********************************************************************************
1236 * Take a command and give it to the controller, returns 0 if successful, or
1237 * EBUSY if the command should be retried later.
1238 */
1239static int
1240amr_start(struct amr_command *ac)
1241{
1242    struct amr_softc	*sc = ac->ac_sc;
1243    int			done, s, i;
1244
1245    debug_called(3);
1246
1247    /* mark command as busy so that polling consumer can tell */
1248    ac->ac_flags |= AMR_CMD_BUSY;
1249
1250    /* get a command slot (freed in amr_done) */
1251    if (amr_getslot(ac))
1252	return(EBUSY);
1253
1254    /* now we have a slot, we can map the command (unmapped in amr_complete) */
1255    amr_mapcmd(ac);
1256
1257    /* mark the new mailbox we are going to copy in as busy */
1258    ac->ac_mailbox.mb_busy = 1;
1259
1260    /* clear the poll/ack fields in the mailbox */
1261    sc->amr_mailbox->mb_poll = 0;
1262    sc->amr_mailbox->mb_ack = 0;
1263
1264    /*
1265     * Save the slot number so that we can locate this command when complete.
1266     * Note that ident = 0 seems to be special, so we don't use it.
1267     */
1268    ac->ac_mailbox.mb_ident = ac->ac_slot + 1;
1269
1270    /*
1271     * Spin waiting for the mailbox, give up after ~1 second.  We expect the
1272     * controller to be able to handle our I/O.
1273     *
1274     * XXX perhaps we should wait for less time, and count on the deferred command
1275     * handling to deal with retries?
1276     */
1277    debug(4, "wait for mailbox");
1278    for (i = 10000, done = 0; (i > 0) && !done; i--) {
1279	s = splbio();
1280
1281	/* is the mailbox free? */
1282	if (sc->amr_mailbox->mb_busy == 0) {
1283	    debug(4, "got mailbox");
1284	    sc->amr_mailbox64->mb64_segment = 0;
1285	    bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, AMR_MBOX_CMDSIZE);
1286	    done = 1;
1287
1288	    /* not free, spin waiting */
1289	} else {
1290	    debug(4, "busy flag %x\n", sc->amr_mailbox->mb_busy);
1291	    /* this is somewhat ugly */
1292	    DELAY(100);
1293	}
1294	splx(s);	/* drop spl to allow completion interrupts */
1295    }
1296
1297    /*
1298     * Now give the command to the controller
1299     */
1300    if (done) {
1301	if (sc->amr_submit_command(sc)) {
1302	    /* the controller wasn't ready to take the command, forget that we tried to post it */
1303	    sc->amr_mailbox->mb_busy = 0;
1304	    return(EBUSY);
1305	}
1306	debug(3, "posted command");
1307	return(0);
1308    }
1309
1310    /*
1311     * The controller wouldn't take the command.  Return the command as busy
1312     * so that it is retried later.
1313     */
1314    return(EBUSY);
1315}
1316
1317/********************************************************************************
1318 * Extract one or more completed commands from the controller (sc)
1319 *
1320 * Returns nonzero if any commands on the work queue were marked as completed.
1321 */
1322int
1323amr_done(struct amr_softc *sc)
1324{
1325    struct amr_command	*ac;
1326    struct amr_mailbox	mbox;
1327    int			i, idx, result;
1328
1329    debug_called(3);
1330
1331    /* See if there's anything for us to do */
1332    result = 0;
1333
1334    /* loop collecting completed commands */
1335    for (;;) {
1336	/* poll for a completed command's identifier and status */
1337	if (sc->amr_get_work(sc, &mbox)) {
1338	    result = 1;
1339
1340	    /* iterate over completed commands in this result */
1341	    for (i = 0; i < mbox.mb_nstatus; i++) {
1342		/* get pointer to busy command */
1343		idx = mbox.mb_completed[i] - 1;
1344		ac = sc->amr_busycmd[idx];
1345
1346		/* really a busy command? */
1347		if (ac != NULL) {
1348
1349		    /* pull the command from the busy index */
1350		    sc->amr_busycmd[idx] = NULL;
1351		    sc->amr_busyslots--;
1352
1353		    /* save status for later use */
1354		    ac->ac_status = mbox.mb_status;
1355		    amr_enqueue_completed(ac);
1356		    debug(3, "completed command with status %x", mbox.mb_status);
1357		} else {
1358		    device_printf(sc->amr_dev, "bad slot %d completed\n", idx);
1359		}
1360	    }
1361	} else {
1362	    break;	/* no work */
1363	}
1364    }
1365
1366    /* if we've completed any commands, try posting some more */
1367    if (result)
1368	amr_startio(sc);
1369
1370    /* handle completion and timeouts */
1371#if __FreeBSD_version >= 500005
1372    if (sc->amr_state & AMR_STATE_INTEN)
1373	taskqueue_enqueue(taskqueue_swi_giant, &sc->amr_task_complete);
1374    else
1375#endif
1376	amr_complete(sc, 0);
1377
1378    return(result);
1379}
1380
1381/********************************************************************************
1382 * Do completion processing on done commands on (sc)
1383 */
1384static void
1385amr_complete(void *context, int pending)
1386{
1387    struct amr_softc	*sc = (struct amr_softc *)context;
1388    struct amr_command	*ac;
1389
1390    debug_called(3);
1391
1392    /* pull completed commands off the queue */
1393    for (;;) {
1394	ac = amr_dequeue_completed(sc);
1395	if (ac == NULL)
1396	    break;
1397
1398	/* unmap the command's data buffer */
1399	amr_unmapcmd(ac);
1400
1401	/* unbusy the command */
1402	ac->ac_flags &= ~AMR_CMD_BUSY;
1403
1404	/*
1405	 * Is there a completion handler?
1406	 */
1407	if (ac->ac_complete != NULL) {
1408	    ac->ac_complete(ac);
1409
1410	    /*
1411	     * Is someone sleeping on this one?
1412	     */
1413	} else if (ac->ac_flags & AMR_CMD_SLEEP) {
1414	    wakeup(ac);
1415	}
1416
1417	if(!sc->amr_busyslots) {
1418	    wakeup(sc);
1419	}
1420    }
1421}
1422
1423/********************************************************************************
1424 ********************************************************************************
1425                                                        Command Buffer Management
1426 ********************************************************************************
1427 ********************************************************************************/
1428
1429/********************************************************************************
1430 * Get a new command buffer.
1431 *
1432 * This may return NULL in low-memory cases.
1433 *
1434 * If possible, we recycle a command buffer that's been used before.
1435 */
1436struct amr_command *
1437amr_alloccmd(struct amr_softc *sc)
1438{
1439    struct amr_command	*ac;
1440
1441    debug_called(3);
1442
1443    ac = amr_dequeue_free(sc);
1444    if (ac == NULL) {
1445	amr_alloccmd_cluster(sc);
1446	ac = amr_dequeue_free(sc);
1447    }
1448    if (ac == NULL)
1449	return(NULL);
1450
1451    /* clear out significant fields */
1452    ac->ac_slot = 0;
1453    ac->ac_status = 0;
1454    bzero(&ac->ac_mailbox, sizeof(struct amr_mailbox));
1455    ac->ac_flags = 0;
1456    ac->ac_bio = NULL;
1457    ac->ac_data = NULL;
1458    ac->ac_ccb_data = NULL;
1459    ac->ac_complete = NULL;
1460    return(ac);
1461}
1462
1463/********************************************************************************
1464 * Release a command buffer for recycling.
1465 */
1466void
1467amr_releasecmd(struct amr_command *ac)
1468{
1469    debug_called(3);
1470
1471    amr_enqueue_free(ac);
1472}
1473
1474/********************************************************************************
1475 * Allocate a new command cluster and initialise it.
1476 */
1477static void
1478amr_alloccmd_cluster(struct amr_softc *sc)
1479{
1480    struct amr_command_cluster	*acc;
1481    struct amr_command		*ac;
1482    int				s, i;
1483
1484    acc = malloc(AMR_CMD_CLUSTERSIZE, M_DEVBUF, M_NOWAIT);
1485    if (acc != NULL) {
1486	s = splbio();
1487	TAILQ_INSERT_TAIL(&sc->amr_cmd_clusters, acc, acc_link);
1488	splx(s);
1489	for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++) {
1490	    ac = &acc->acc_command[i];
1491	    bzero(ac, sizeof(*ac));
1492	    ac->ac_sc = sc;
1493	    if (!bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap) &&
1494		!bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_ccb_dmamap))
1495		amr_releasecmd(ac);
1496	}
1497    }
1498}
1499
1500/********************************************************************************
1501 * Free a command cluster
1502 */
1503static void
1504amr_freecmd_cluster(struct amr_command_cluster *acc)
1505{
1506    struct amr_softc	*sc = acc->acc_command[0].ac_sc;
1507    int			i;
1508
1509    for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++)
1510	bus_dmamap_destroy(sc->amr_buffer_dmat, acc->acc_command[i].ac_dmamap);
1511    free(acc, M_DEVBUF);
1512}
1513
1514/********************************************************************************
1515 ********************************************************************************
1516                                                         Interface-specific Shims
1517 ********************************************************************************
1518 ********************************************************************************/
1519
1520/********************************************************************************
1521 * Tell the controller that the mailbox contains a valid command
1522 */
1523static int
1524amr_quartz_submit_command(struct amr_softc *sc)
1525{
1526    debug_called(3);
1527
1528    if (AMR_QGET_IDB(sc) & AMR_QIDB_SUBMIT)
1529	return(EBUSY);
1530    AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT);
1531    return(0);
1532}
1533
1534static int
1535amr_std_submit_command(struct amr_softc *sc)
1536{
1537    debug_called(3);
1538
1539    if (AMR_SGET_MBSTAT(sc) & AMR_SMBOX_BUSYFLAG)
1540	return(EBUSY);
1541    AMR_SPOST_COMMAND(sc);
1542    return(0);
1543}
1544
1545/********************************************************************************
1546 * Claim any work that the controller has completed; acknowledge completion,
1547 * save details of the completion in (mbsave)
1548 */
1549static int
1550amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
1551{
1552    int		s, worked;
1553    u_int32_t	outd;
1554
1555    debug_called(3);
1556
1557    worked = 0;
1558    s = splbio();
1559
1560    /* work waiting for us? */
1561    if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) {
1562
1563	/* save mailbox, which contains a list of completed commands */
1564	bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave));
1565
1566	/* acknowledge interrupt */
1567	AMR_QPUT_ODB(sc, AMR_QODB_READY);
1568
1569	/* acknowledge that we have the commands */
1570	AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK);
1571
1572#ifndef AMR_QUARTZ_GOFASTER
1573	/*
1574	 * This waits for the controller to notice that we've taken the
1575	 * command from it.  It's very inefficient, and we shouldn't do it,
1576	 * but if we remove this code, we stop completing commands under
1577	 * load.
1578	 *
1579	 * Peter J says we shouldn't do this.  The documentation says we
1580	 * should.  Who is right?
1581	 */
1582	while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK)
1583	    ;				/* XXX aiee! what if it dies? */
1584#endif
1585
1586	worked = 1;			/* got some work */
1587    }
1588
1589    splx(s);
1590    return(worked);
1591}
1592
1593static int
1594amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave)
1595{
1596    int		s, worked;
1597    u_int8_t	istat;
1598
1599    debug_called(3);
1600
1601    worked = 0;
1602    s = splbio();
1603
1604    /* check for valid interrupt status */
1605    istat = AMR_SGET_ISTAT(sc);
1606    if ((istat & AMR_SINTR_VALID) != 0) {
1607	AMR_SPUT_ISTAT(sc, istat);	/* ack interrupt status */
1608
1609	/* save mailbox, which contains a list of completed commands */
1610	bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave));
1611
1612	AMR_SACK_INTERRUPT(sc);		/* acknowledge we have the mailbox */
1613	worked = 1;
1614    }
1615
1616    splx(s);
1617    return(worked);
1618}
1619
1620/********************************************************************************
1621 * Notify the controller of the mailbox location.
1622 */
1623static void
1624amr_std_attach_mailbox(struct amr_softc *sc)
1625{
1626
1627    /* program the mailbox physical address */
1628    AMR_SBYTE_SET(sc, AMR_SMBOX_0, sc->amr_mailboxphys         & 0xff);
1629    AMR_SBYTE_SET(sc, AMR_SMBOX_1, (sc->amr_mailboxphys >>  8) & 0xff);
1630    AMR_SBYTE_SET(sc, AMR_SMBOX_2, (sc->amr_mailboxphys >> 16) & 0xff);
1631    AMR_SBYTE_SET(sc, AMR_SMBOX_3, (sc->amr_mailboxphys >> 24) & 0xff);
1632    AMR_SBYTE_SET(sc, AMR_SMBOX_ENABLE, AMR_SMBOX_ADDR);
1633
1634    /* clear any outstanding interrupt and enable interrupts proper */
1635    AMR_SACK_INTERRUPT(sc);
1636    AMR_SENABLE_INTR(sc);
1637}
1638
1639#ifdef AMR_BOARD_INIT
1640/********************************************************************************
1641 * Initialise the controller
1642 */
1643static int
1644amr_quartz_init(struct amr_softc *sc)
1645{
1646    int		status, ostatus;
1647
1648    device_printf(sc->amr_dev, "initial init status %x\n", AMR_QGET_INITSTATUS(sc));
1649
1650    AMR_QRESET(sc);
1651
1652    ostatus = 0xff;
1653    while ((status = AMR_QGET_INITSTATUS(sc)) != AMR_QINIT_DONE) {
1654	if (status != ostatus) {
1655	    device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_qinit, status));
1656	    ostatus = status;
1657	}
1658	switch (status) {
1659	case AMR_QINIT_NOMEM:
1660	    return(ENOMEM);
1661
1662	case AMR_QINIT_SCAN:
1663	    /* XXX we could print channel/target here */
1664	    break;
1665	}
1666    }
1667    return(0);
1668}
1669
1670static int
1671amr_std_init(struct amr_softc *sc)
1672{
1673    int		status, ostatus;
1674
1675    device_printf(sc->amr_dev, "initial init status %x\n", AMR_SGET_INITSTATUS(sc));
1676
1677    AMR_SRESET(sc);
1678
1679    ostatus = 0xff;
1680    while ((status = AMR_SGET_INITSTATUS(sc)) != AMR_SINIT_DONE) {
1681	if (status != ostatus) {
1682	    device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_sinit, status));
1683	    ostatus = status;
1684	}
1685	switch (status) {
1686	case AMR_SINIT_NOMEM:
1687	    return(ENOMEM);
1688
1689	case AMR_SINIT_INPROG:
1690	    /* XXX we could print channel/target here? */
1691	    break;
1692	}
1693    }
1694    return(0);
1695}
1696#endif
1697
1698/********************************************************************************
1699 ********************************************************************************
1700                                                                        Debugging
1701 ********************************************************************************
1702 ********************************************************************************/
1703
1704/********************************************************************************
1705 * Identify the controller and print some information about it.
1706 */
1707static void
1708amr_describe_controller(struct amr_softc *sc)
1709{
1710    struct amr_prodinfo	*ap;
1711    struct amr_enquiry	*ae;
1712    char		*prod;
1713
1714    /*
1715     * Try to get 40LD product info, which tells us what the card is labelled as.
1716     */
1717    if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0)) != NULL) {
1718	device_printf(sc->amr_dev, "<LSILogic %.80s> Firmware %.16s, BIOS %.16s, %dMB RAM\n",
1719		      ap->ap_product, ap->ap_firmware, ap->ap_bios,
1720		      ap->ap_memsize);
1721
1722	free(ap, M_DEVBUF);
1723	return;
1724    }
1725
1726    /*
1727     * Try 8LD extended ENQUIRY to get controller signature, and use lookup table.
1728     */
1729    if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0)) != NULL) {
1730	prod = amr_describe_code(amr_table_adaptertype, ae->ae_signature);
1731
1732    } else if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0)) != NULL) {
1733
1734	/*
1735	 * Try to work it out based on the PCI signatures.
1736	 */
1737	switch (pci_get_device(sc->amr_dev)) {
1738	case 0x9010:
1739	    prod = "Series 428";
1740	    break;
1741	case 0x9060:
1742	    prod = "Series 434";
1743	    break;
1744	default:
1745	    prod = "unknown controller";
1746	    break;
1747	}
1748    } else {
1749	prod = "unsupported controller";
1750    }
1751
1752    /*
1753     * HP NetRaid controllers have a special encoding of the firmware and
1754     * BIOS versions. The AMI version seems to have it as strings whereas
1755     * the HP version does it with a leading uppercase character and two
1756     * binary numbers.
1757     */
1758
1759    if(ae->ae_adapter.aa_firmware[2] >= 'A' &&
1760       ae->ae_adapter.aa_firmware[2] <= 'Z' &&
1761       ae->ae_adapter.aa_firmware[1] <  ' ' &&
1762       ae->ae_adapter.aa_firmware[0] <  ' ' &&
1763       ae->ae_adapter.aa_bios[2] >= 'A'     &&
1764       ae->ae_adapter.aa_bios[2] <= 'Z'     &&
1765       ae->ae_adapter.aa_bios[1] <  ' '     &&
1766       ae->ae_adapter.aa_bios[0] <  ' ') {
1767
1768	/* this looks like we have an HP NetRaid version of the MegaRaid */
1769
1770    	if(ae->ae_signature == AMR_SIG_438) {
1771    		/* the AMI 438 is a NetRaid 3si in HP-land */
1772    		prod = "HP NetRaid 3si";
1773    	}
1774
1775	device_printf(sc->amr_dev, "<%s> Firmware %c.%02d.%02d, BIOS %c.%02d.%02d, %dMB RAM\n",
1776		      prod, ae->ae_adapter.aa_firmware[2],
1777		      ae->ae_adapter.aa_firmware[1],
1778		      ae->ae_adapter.aa_firmware[0],
1779		      ae->ae_adapter.aa_bios[2],
1780		      ae->ae_adapter.aa_bios[1],
1781		      ae->ae_adapter.aa_bios[0],
1782		      ae->ae_adapter.aa_memorysize);
1783    } else {
1784	device_printf(sc->amr_dev, "<%s> Firmware %.4s, BIOS %.4s, %dMB RAM\n",
1785		      prod, ae->ae_adapter.aa_firmware, ae->ae_adapter.aa_bios,
1786		      ae->ae_adapter.aa_memorysize);
1787    }
1788    free(ae, M_DEVBUF);
1789}
1790
1791#ifdef AMR_DEBUG
1792/********************************************************************************
1793 * Print the command (ac) in human-readable format
1794 */
1795#if 0
1796static void
1797amr_printcommand(struct amr_command *ac)
1798{
1799    struct amr_softc	*sc = ac->ac_sc;
1800    struct amr_sgentry	*sg;
1801    int			i;
1802
1803    device_printf(sc->amr_dev, "cmd %x  ident %d  drive %d\n",
1804		  ac->ac_mailbox.mb_command, ac->ac_mailbox.mb_ident, ac->ac_mailbox.mb_drive);
1805    device_printf(sc->amr_dev, "blkcount %d  lba %d\n",
1806		  ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba);
1807    device_printf(sc->amr_dev, "virtaddr %p  length %lu\n", ac->ac_data, (unsigned long)ac->ac_length);
1808    device_printf(sc->amr_dev, "sg physaddr %08x  nsg %d\n",
1809		  ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem);
1810    device_printf(sc->amr_dev, "ccb %p  bio %p\n", ac->ac_ccb_data, ac->ac_bio);
1811
1812    /* get base address of s/g table */
1813    sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG);
1814    for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++)
1815	device_printf(sc->amr_dev, "  %x/%d\n", sg->sg_addr, sg->sg_count);
1816}
1817#endif
1818#endif
1819