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