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