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