Deleted Added
full compact
mlx.c (54073) mlx.c (54419)
1/*-
2 * Copyright (c) 1999 Michael Smith
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1999 Michael Smith
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/mlx/mlx.c 54073 1999-12-03 08:41:24Z mdodd $
26 * $FreeBSD: head/sys/dev/mlx/mlx.c 54419 1999-12-11 00:00:13Z msmith $
27 */
28
29/*
30 * Driver for the Mylex DAC960 family of RAID controllers.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>

--- 49 unchanged lines hidden (view full) ---

84static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
85static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
86static void mlx_v3_intaction(struct mlx_softc *sc, int action);
87
88static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
89static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
90static void mlx_v4_intaction(struct mlx_softc *sc, int action);
91
27 */
28
29/*
30 * Driver for the Mylex DAC960 family of RAID controllers.
31 */
32
33#include <sys/param.h>
34#include <sys/systm.h>

--- 49 unchanged lines hidden (view full) ---

84static int mlx_v3_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
85static int mlx_v3_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
86static void mlx_v3_intaction(struct mlx_softc *sc, int action);
87
88static int mlx_v4_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
89static int mlx_v4_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
90static void mlx_v4_intaction(struct mlx_softc *sc, int action);
91
92static int mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc);
93static int mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status);
94static void mlx_v5_intaction(struct mlx_softc *sc, int action);
95
92/*
93 * Status monitoring
94 */
95static void mlx_periodic(void *data);
96static void mlx_periodic_enquiry(struct mlx_command *mc);
97static void mlx_periodic_eventlog_poll(struct mlx_softc *sc);
98static void mlx_periodic_eventlog_respond(struct mlx_command *mc);
99static void mlx_periodic_rebuild(struct mlx_command *mc);

--- 191 unchanged lines hidden (view full) ---

291 sc->mlx_findcomplete = mlx_v3_findcomplete;
292 sc->mlx_intaction = mlx_v3_intaction;
293 break;
294 case MLX_IFTYPE_4:
295 sc->mlx_tryqueue = mlx_v4_tryqueue;
296 sc->mlx_findcomplete = mlx_v4_findcomplete;
297 sc->mlx_intaction = mlx_v4_intaction;
298 break;
96/*
97 * Status monitoring
98 */
99static void mlx_periodic(void *data);
100static void mlx_periodic_enquiry(struct mlx_command *mc);
101static void mlx_periodic_eventlog_poll(struct mlx_softc *sc);
102static void mlx_periodic_eventlog_respond(struct mlx_command *mc);
103static void mlx_periodic_rebuild(struct mlx_command *mc);

--- 191 unchanged lines hidden (view full) ---

295 sc->mlx_findcomplete = mlx_v3_findcomplete;
296 sc->mlx_intaction = mlx_v3_intaction;
297 break;
298 case MLX_IFTYPE_4:
299 sc->mlx_tryqueue = mlx_v4_tryqueue;
300 sc->mlx_findcomplete = mlx_v4_findcomplete;
301 sc->mlx_intaction = mlx_v4_intaction;
302 break;
303 case MLX_IFTYPE_5:
304 sc->mlx_tryqueue = mlx_v5_tryqueue;
305 sc->mlx_findcomplete = mlx_v5_findcomplete;
306 sc->mlx_intaction = mlx_v5_intaction;
307 break;
299 default:
300 device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype);
301 return(ENXIO); /* should never happen */
302 }
303
304 /* disable interrupts before we start talking to the controller */
305 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
306

--- 90 unchanged lines hidden (view full) ---

397 break;
398 case MLX_IFTYPE_4:
399 /* XXX certify firmware versions? */
400 if (sc->mlx_fwminor < 6) {
401 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
402 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
403 }
404 break;
308 default:
309 device_printf(sc->mlx_dev, "attaching unsupported interface version %d\n", sc->mlx_iftype);
310 return(ENXIO); /* should never happen */
311 }
312
313 /* disable interrupts before we start talking to the controller */
314 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
315

--- 90 unchanged lines hidden (view full) ---

406 break;
407 case MLX_IFTYPE_4:
408 /* XXX certify firmware versions? */
409 if (sc->mlx_fwminor < 6) {
410 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
411 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 4.06 or later\n");
412 }
413 break;
414 case MLX_IFTYPE_5:
415 if (sc->mlx_fwminor < 7) {
416 device_printf(sc->mlx_dev, " *** WARNING *** This firmware revision is not recommended\n");
417 device_printf(sc->mlx_dev, " *** WARNING *** Use revision 5.07 or later\n");
418 }
419 break;
405 default:
406 device_printf(sc->mlx_dev, "interface version corrupted to %d\n", sc->mlx_iftype);
407 return(ENXIO); /* should never happen */
408 }
409
410 /*
411 * Create the final set of s/g mappings now that we know how many commands
412 * the controller actually supports.

--- 86 unchanged lines hidden (view full) ---

499
500/********************************************************************************
501 * Disconnect from the controller completely, in preparation for unload.
502 */
503int
504mlx_detach(device_t dev)
505{
506 struct mlx_softc *sc = device_get_softc(dev);
420 default:
421 device_printf(sc->mlx_dev, "interface version corrupted to %d\n", sc->mlx_iftype);
422 return(ENXIO); /* should never happen */
423 }
424
425 /*
426 * Create the final set of s/g mappings now that we know how many commands
427 * the controller actually supports.

--- 86 unchanged lines hidden (view full) ---

514
515/********************************************************************************
516 * Disconnect from the controller completely, in preparation for unload.
517 */
518int
519mlx_detach(device_t dev)
520{
521 struct mlx_softc *sc = device_get_softc(dev);
507 int error;
522 struct mlxd_softc *mlxd;
523 int i, s, error;
508
509 debug("called");
510
524
525 debug("called");
526
527 error = EBUSY;
528 s = splbio();
511 if (sc->mlx_state & MLX_STATE_OPEN)
529 if (sc->mlx_state & MLX_STATE_OPEN)
512 return(EBUSY);
530 goto out;
513
531
532 for (i = 0; i < MLX_MAXDRIVES; i++) {
533 if (sc->mlx_sysdrive[i].ms_disk != 0) {
534 mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
535 if (mlxd->mlxd_flags & MLXD_OPEN) { /* drive is mounted, abort detach */
536 device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't detach\n");
537 goto out;
538 }
539 }
540 }
514 if ((error = mlx_shutdown(dev)))
541 if ((error = mlx_shutdown(dev)))
515 return(error);
542 goto out;
516
517 mlx_free(sc);
518
519 /*
520 * Deregister the control device on last detach.
521 */
522 if (--cdev_registered == 0)
523 cdevsw_remove(&mlx_cdevsw);
543
544 mlx_free(sc);
545
546 /*
547 * Deregister the control device on last detach.
548 */
549 if (--cdev_registered == 0)
550 cdevsw_remove(&mlx_cdevsw);
524
525 return(0);
551 error = 0;
552 out:
553 splx(s);
554 return(error);
526}
527
528/********************************************************************************
529 * Bring the controller down to a dormant state and detach all child devices.
530 *
531 * This function is called before detach, system shutdown, or before performing
532 * an operation which may add or delete system disks. (Call mlx_startup to
533 * resume normal operation.)
534 *
535 * Note that we can assume that the bufq on the controller is empty, as we won't
536 * allow shutdown if any device is open.
537 */
538int
539mlx_shutdown(device_t dev)
540{
541 struct mlx_softc *sc = device_get_softc(dev);
555}
556
557/********************************************************************************
558 * Bring the controller down to a dormant state and detach all child devices.
559 *
560 * This function is called before detach, system shutdown, or before performing
561 * an operation which may add or delete system disks. (Call mlx_startup to
562 * resume normal operation.)
563 *
564 * Note that we can assume that the bufq on the controller is empty, as we won't
565 * allow shutdown if any device is open.
566 */
567int
568mlx_shutdown(device_t dev)
569{
570 struct mlx_softc *sc = device_get_softc(dev);
542 struct mlxd_softc *mlxd;
543 int i, s, error;
544
545 debug("called");
546
547 s = splbio();
548 error = 0;
549
571 int i, s, error;
572
573 debug("called");
574
575 s = splbio();
576 error = 0;
577
550 /* assume we're going to shut down */
551 sc->mlx_state |= MLX_STATE_SHUTDOWN;
578 sc->mlx_state |= MLX_STATE_SHUTDOWN;
552 for (i = 0; i < MLX_MAXDRIVES; i++) {
553 if (sc->mlx_sysdrive[i].ms_disk != 0) {
554 mlxd = device_get_softc(sc->mlx_sysdrive[i].ms_disk);
555 if (mlxd->mlxd_flags & MLXD_OPEN) { /* drive is mounted, abort shutdown */
556 sc->mlx_state &= ~MLX_STATE_SHUTDOWN;
557 device_printf(sc->mlx_sysdrive[i].ms_disk, "still open, can't shutdown\n");
558 error = EBUSY;
559 goto out;
560 }
561 }
562 }
579 sc->mlx_intaction(sc, MLX_INTACTION_DISABLE);
563
564 /* flush controller */
565 device_printf(sc->mlx_dev, "flushing cache...");
566 if (mlx_flush(sc)) {
567 printf("failed\n");
568 } else {
569 printf("done\n");
570 }
571
572 /* delete all our child devices */
573 for (i = 0; i < MLX_MAXDRIVES; i++) {
574 if (sc->mlx_sysdrive[i].ms_disk != 0) {
575 if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
576 goto out;
577 sc->mlx_sysdrive[i].ms_disk = 0;
578 }
579 }
580
580
581 /* flush controller */
582 device_printf(sc->mlx_dev, "flushing cache...");
583 if (mlx_flush(sc)) {
584 printf("failed\n");
585 } else {
586 printf("done\n");
587 }
588
589 /* delete all our child devices */
590 for (i = 0; i < MLX_MAXDRIVES; i++) {
591 if (sc->mlx_sysdrive[i].ms_disk != 0) {
592 if ((error = device_delete_child(sc->mlx_dev, sc->mlx_sysdrive[i].ms_disk)) != 0)
593 goto out;
594 sc->mlx_sysdrive[i].ms_disk = 0;
595 }
596 }
597
581 bus_generic_detach(sc->mlx_dev);
582
583 out:
584 splx(s);
585 return(error);
586}
587
588/********************************************************************************
589 * Bring the controller to a quiescent state, ready for system suspend.
590 */

--- 37 unchanged lines hidden (view full) ---

628/*******************************************************************************
629 * Take an interrupt, or be poked by other code to look for interrupt-worthy
630 * status.
631 */
632void
633mlx_intr(void *arg)
634{
635 struct mlx_softc *sc = (struct mlx_softc *)arg;
598 out:
599 splx(s);
600 return(error);
601}
602
603/********************************************************************************
604 * Bring the controller to a quiescent state, ready for system suspend.
605 */

--- 37 unchanged lines hidden (view full) ---

643/*******************************************************************************
644 * Take an interrupt, or be poked by other code to look for interrupt-worthy
645 * status.
646 */
647void
648mlx_intr(void *arg)
649{
650 struct mlx_softc *sc = (struct mlx_softc *)arg;
636 int worked;
637
638 debug("called");
639
651
652 debug("called");
653
640 /* spin collecting finished commands */
641 worked = 0;
642 while (mlx_done(sc))
643 worked = 1;
644
645 /* did we do anything? */
646 if (worked)
647 mlx_complete(sc);
654 /* collect finished commands, queue anything waiting */
655 mlx_done(sc);
648};
649
650/*******************************************************************************
651 * Receive a buf structure from a child device and queue it on a particular
652 * disk resource, then poke the disk resource to start as much work as it can.
653 */
654int
655mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)

--- 102 unchanged lines hidden (view full) ---

758 error = EBUSY;
759 goto detach_out;
760 }
761
762 /* nuke drive */
763 if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
764 goto detach_out;
765 dr->ms_disk = 0;
656};
657
658/*******************************************************************************
659 * Receive a buf structure from a child device and queue it on a particular
660 * disk resource, then poke the disk resource to start as much work as it can.
661 */
662int
663mlx_submit_buf(struct mlx_softc *sc, struct buf *bp)

--- 102 unchanged lines hidden (view full) ---

766 error = EBUSY;
767 goto detach_out;
768 }
769
770 /* nuke drive */
771 if ((error = device_delete_child(sc->mlx_dev, dr->ms_disk)) != 0)
772 goto detach_out;
773 dr->ms_disk = 0;
766 bus_generic_detach(sc->mlx_dev);
767
768 detach_out:
769 if (error) {
770 printf("failed\n");
771 } else {
772 printf("done\n");
773 }
774 return(error);

--- 130 unchanged lines hidden (view full) ---

905
906
907/********************************************************************************
908 ********************************************************************************
909 Status Monitoring
910 ********************************************************************************
911 ********************************************************************************/
912
774
775 detach_out:
776 if (error) {
777 printf("failed\n");
778 } else {
779 printf("done\n");
780 }
781 return(error);

--- 130 unchanged lines hidden (view full) ---

912
913
914/********************************************************************************
915 ********************************************************************************
916 Status Monitoring
917 ********************************************************************************
918 ********************************************************************************/
919
913#define MLX_PERIODIC_ISBUSY(sc) (sc->mlx_polling <= 0)
914#define MLX_PERIODIC_BUSY(sc) atomic_add_int(&sc->mlx_polling, 1);
915#define MLX_PERIODIC_UNBUSY(sc) atomic_subtract_int(&sc->mlx_polling, 1);
916
917/********************************************************************************
918 * Fire off commands to periodically check the status of connected drives.
919 */
920static void
921mlx_periodic(void *data)
922{
923 struct mlx_softc *sc = (struct mlx_softc *)data;
924

--- 23 unchanged lines hidden (view full) ---

948 sysbeep(500, hz);
949 } else {
950 sysbeep((time_second % 5) * 100 + 500, hz/8);
951 }
952
953 /*
954 * Run normal periodic activities?
955 */
920/********************************************************************************
921 * Fire off commands to periodically check the status of connected drives.
922 */
923static void
924mlx_periodic(void *data)
925{
926 struct mlx_softc *sc = (struct mlx_softc *)data;
927

--- 23 unchanged lines hidden (view full) ---

951 sysbeep(500, hz);
952 } else {
953 sysbeep((time_second % 5) * 100 + 500, hz/8);
954 }
955
956 /*
957 * Run normal periodic activities?
958 */
956 } else if (MLX_PERIODIC_ISBUSY(sc)) {
959 } else if (time_second > (sc->mlx_lastpoll + 10)) {
960 sc->mlx_lastpoll = time_second;
957
961
958 /* time to perform a periodic status poll? XXX tuneable interval? */
959 if (time_second > (sc->mlx_lastpoll + 10)) {
960 sc->mlx_lastpoll = time_second;
962 /*
963 * Check controller status.
964 *
965 * XXX Note that this may not actually launch a command in situations of high load.
966 */
967 mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(struct mlx_enquiry), mlx_periodic_enquiry);
961
968
962 /* for caution's sake */
963 if (sc->mlx_polling < 0) {
964 device_printf(sc->mlx_dev, "mlx_polling < 0\n");
965 atomic_set_int(&sc->mlx_polling, 0);
966 }
967
968 /*
969 * Check controller status.
970 */
971 MLX_PERIODIC_BUSY(sc);
972 mlx_enquire(sc, MLX_CMD_ENQUIRY, sizeof(struct mlx_enquiry), mlx_periodic_enquiry);
973
974 /*
975 * Check system drive status.
976 *
977 * XXX This might be better left to event-driven detection, eg. I/O to an offline
978 * drive will detect it's offline, rebuilds etc. should detect the drive is back
979 * online.
980 */
981 MLX_PERIODIC_BUSY(sc);
982 mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
969 /*
970 * Check system drive status.
971 *
972 * XXX This might be better left to event-driven detection, eg. I/O to an offline
973 * drive will detect it's offline, rebuilds etc. should detect the drive is back
974 * online.
975 */
976 mlx_enquire(sc, MLX_CMD_ENQSYSDRIVE, sizeof(struct mlx_enq_sys_drive) * MLX_MAXDRIVES,
983 mlx_periodic_enquiry);
977 mlx_periodic_enquiry);
984 }
985
978
986 /*
987 * Get drive rebuild/check status
988 */
979 /*
980 * Get drive rebuild/check status
981 */
989 if (sc->mlx_rebuild >= 0) {
990 MLX_PERIODIC_BUSY(sc);
982 if (sc->mlx_rebuild >= 0)
991 mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
983 mlx_enquire(sc, MLX_CMD_REBUILDSTAT, sizeof(struct mlx_rebuild_stat), mlx_periodic_rebuild);
992 }
993 } else {
994 /*
995 * If things are still running from the last poll, complain about it.
996 *
997 * XXX If this becomes an issue, we should have some way of telling what
998 * has become stuck.
999 */
1000 device_printf(sc->mlx_dev, "poll still busy (%d)\n", sc->mlx_polling);
1001 }
1002
984 }
985
1003 /* XXX check for wedged/timed out commands? */
986 /* deal with possibly-missed interrupts and timed-out commands */
987 mlx_done(sc);
1004
1005 /* reschedule another poll next second or so */
1006 sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
1007}
1008
1009/********************************************************************************
1010 * Handle the result of an ENQUIRY command instigated by periodic status polling.
1011 */

--- 60 unchanged lines hidden (view full) ---

1072 /* save new state */
1073 dr->ms_state = mes[i].sd_state;
1074 }
1075 }
1076 }
1077 break;
1078 }
1079 default:
988
989 /* reschedule another poll next second or so */
990 sc->mlx_timeout = timeout(mlx_periodic, sc, hz);
991}
992
993/********************************************************************************
994 * Handle the result of an ENQUIRY command instigated by periodic status polling.
995 */

--- 60 unchanged lines hidden (view full) ---

1056 /* save new state */
1057 dr->ms_state = mes[i].sd_state;
1058 }
1059 }
1060 }
1061 break;
1062 }
1063 default:
1064 device_printf(sc->mlx_dev, "%s: unknown command 0x%x", __FUNCTION__, mc->mc_mailbox[0]);
1080 break;
1081 }
1082
1083 out:
1084 free(mc->mc_data, M_DEVBUF);
1085 mlx_releasecmd(mc);
1065 break;
1066 }
1067
1068 out:
1069 free(mc->mc_data, M_DEVBUF);
1070 mlx_releasecmd(mc);
1086 /* this event is done */
1087 MLX_PERIODIC_UNBUSY(sc);
1088}
1089
1090/********************************************************************************
1091 * Instigate a poll for one event log message on (sc).
1092 * We only poll for one message at a time, to keep our command usage down.
1093 */
1094static void
1095mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1096{
1097 struct mlx_command *mc;
1098 void *result = NULL;
1099 int error;
1100
1101 debug("called");
1102
1071}
1072
1073/********************************************************************************
1074 * Instigate a poll for one event log message on (sc).
1075 * We only poll for one message at a time, to keep our command usage down.
1076 */
1077static void
1078mlx_periodic_eventlog_poll(struct mlx_softc *sc)
1079{
1080 struct mlx_command *mc;
1081 void *result = NULL;
1082 int error;
1083
1084 debug("called");
1085
1103 /* presume we are going to create another event */
1104 MLX_PERIODIC_BUSY(sc);
1105
1106 /* get ourselves a command buffer */
1107 error = 1;
1108 if ((mc = mlx_alloccmd(sc)) == NULL)
1109 goto out;
1110 /* allocate the response structure */
1111 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1112 goto out;
1113 /* get a command slot */

--- 16 unchanged lines hidden (view full) ---

1130
1131 error = 0; /* success */
1132 out:
1133 if (error != 0) {
1134 if (mc != NULL)
1135 mlx_releasecmd(mc);
1136 if (result != NULL)
1137 free(result, M_DEVBUF);
1086 /* get ourselves a command buffer */
1087 error = 1;
1088 if ((mc = mlx_alloccmd(sc)) == NULL)
1089 goto out;
1090 /* allocate the response structure */
1091 if ((result = malloc(/*sizeof(struct mlx_eventlog_entry)*/1024, M_DEVBUF, M_NOWAIT)) == NULL)
1092 goto out;
1093 /* get a command slot */

--- 16 unchanged lines hidden (view full) ---

1110
1111 error = 0; /* success */
1112 out:
1113 if (error != 0) {
1114 if (mc != NULL)
1115 mlx_releasecmd(mc);
1116 if (result != NULL)
1117 free(result, M_DEVBUF);
1138 /* abort this event */
1139 MLX_PERIODIC_UNBUSY(sc);
1140 }
1141}
1142
1143/********************************************************************************
1144 * Handle the result of polling for a log message, generate diagnostic output.
1145 * If this wasn't the last message waiting for us, we'll go collect another.
1146 */
1147static char *mlx_sense_messages[] = {

--- 16 unchanged lines hidden (view full) ---

1164mlx_periodic_eventlog_respond(struct mlx_command *mc)
1165{
1166 struct mlx_softc *sc = mc->mc_sc;
1167 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data;
1168 char *reason;
1169
1170 debug("called");
1171
1118 }
1119}
1120
1121/********************************************************************************
1122 * Handle the result of polling for a log message, generate diagnostic output.
1123 * If this wasn't the last message waiting for us, we'll go collect another.
1124 */
1125static char *mlx_sense_messages[] = {

--- 16 unchanged lines hidden (view full) ---

1142mlx_periodic_eventlog_respond(struct mlx_command *mc)
1143{
1144 struct mlx_softc *sc = mc->mc_sc;
1145 struct mlx_eventlog_entry *el = (struct mlx_eventlog_entry *)mc->mc_data;
1146 char *reason;
1147
1148 debug("called");
1149
1150 sc->mlx_lastevent++; /* next message... */
1172 if (mc->mc_status == 0) {
1151 if (mc->mc_status == 0) {
1173 sc->mlx_lastevent++; /* got the message OK */
1174
1175 /* handle event log message */
1176 switch(el->el_type) {
1177 /*
1178 * This is the only sort of message we understand at the moment.
1179 * The tests here are probably incomplete.
1180 */
1181 case MLX_LOGMSG_SENSE: /* sense data */

--- 35 unchanged lines hidden (view full) ---

1217
1218 /* dispose of command and data */
1219 free(mc->mc_data, M_DEVBUF);
1220 mlx_releasecmd(mc);
1221
1222 /* is there another message to obtain? */
1223 if (sc->mlx_lastevent != sc->mlx_currevent)
1224 mlx_periodic_eventlog_poll(sc);
1152
1153 /* handle event log message */
1154 switch(el->el_type) {
1155 /*
1156 * This is the only sort of message we understand at the moment.
1157 * The tests here are probably incomplete.
1158 */
1159 case MLX_LOGMSG_SENSE: /* sense data */

--- 35 unchanged lines hidden (view full) ---

1195
1196 /* dispose of command and data */
1197 free(mc->mc_data, M_DEVBUF);
1198 mlx_releasecmd(mc);
1199
1200 /* is there another message to obtain? */
1201 if (sc->mlx_lastevent != sc->mlx_currevent)
1202 mlx_periodic_eventlog_poll(sc);
1225
1226 /* this event is done */
1227 MLX_PERIODIC_UNBUSY(sc);
1228}
1229
1230/********************************************************************************
1231 * Handle the completion of a rebuild operation.
1232 */
1233static void
1234mlx_periodic_rebuild(struct mlx_command *mc)
1235{

--- 14 unchanged lines hidden (view full) ---

1250 sc->mlx_check = -1;
1251 } else {
1252 device_printf(sc->mlx_dev, "consistency check completed\n");
1253 }
1254 break;
1255 }
1256 free(mc->mc_data, M_DEVBUF);
1257 mlx_releasecmd(mc);
1203}
1204
1205/********************************************************************************
1206 * Handle the completion of a rebuild operation.
1207 */
1208static void
1209mlx_periodic_rebuild(struct mlx_command *mc)
1210{

--- 14 unchanged lines hidden (view full) ---

1225 sc->mlx_check = -1;
1226 } else {
1227 device_printf(sc->mlx_dev, "consistency check completed\n");
1228 }
1229 break;
1230 }
1231 free(mc->mc_data, M_DEVBUF);
1232 mlx_releasecmd(mc);
1258 /* this event is done */
1259 MLX_PERIODIC_UNBUSY(sc);
1260}
1261
1262/********************************************************************************
1263 ********************************************************************************
1264 Channel Pause
1265 ********************************************************************************
1266 ********************************************************************************/
1267

--- 170 unchanged lines hidden (view full) ---

1438 goto out;
1439 /* get a command slot */
1440 if (mlx_getslot(mc))
1441 goto out;
1442
1443 /* build a flush command */
1444 mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1445
1233}
1234
1235/********************************************************************************
1236 ********************************************************************************
1237 Channel Pause
1238 ********************************************************************************
1239 ********************************************************************************/
1240

--- 170 unchanged lines hidden (view full) ---

1411 goto out;
1412 /* get a command slot */
1413 if (mlx_getslot(mc))
1414 goto out;
1415
1416 /* build a flush command */
1417 mlx_make_type2(mc, MLX_CMD_FLUSH, 0, 0, 0, 0, 0, 0, 0, 0);
1418
1446 /* run the command in either polled or wait mode */
1447 if ((sc->mlx_state & MLX_STATE_INTEN) ? mlx_wait_command(mc) : mlx_poll_command(mc))
1419 /* can't assume that interrupts are going to work here, so play it safe */
1420 if (mlx_poll_command(mc))
1448 goto out;
1449
1450 /* command completed OK? */
1451 if (mc->mc_status != 0) {
1452 device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1453 goto out;
1454 }
1455

--- 127 unchanged lines hidden (view full) ---

1583 struct mlx_command *mc;
1584 struct mlxd_softc *mlxd;
1585 struct buf *bp;
1586 int blkcount;
1587 int driveno;
1588 int cmd;
1589 int s;
1590
1421 goto out;
1422
1423 /* command completed OK? */
1424 if (mc->mc_status != 0) {
1425 device_printf(sc->mlx_dev, "FLUSH failed - %s\n", mlx_diagnose_command(mc));
1426 goto out;
1427 }
1428

--- 127 unchanged lines hidden (view full) ---

1556 struct mlx_command *mc;
1557 struct mlxd_softc *mlxd;
1558 struct buf *bp;
1559 int blkcount;
1560 int driveno;
1561 int cmd;
1562 int s;
1563
1564 /* avoid reentrancy */
1565 if (mlx_lock_tas(sc, MLX_LOCK_STARTING))
1566 return;
1567
1591 /* spin until something prevents us from doing any work */
1592 s = splbio();
1593 for (;;) {
1594
1595 /* see if there's work to be done */
1596 if ((bp = bufq_first(&sc->mlx_bufq)) == NULL)
1597 break;
1598 /* get a command */

--- 22 unchanged lines hidden (view full) ---

1621 cmd = MLX_CMD_WRITEOLDSG;
1622 }
1623
1624 /* map the command so the controller can work with it */
1625 mlx_mapcmd(mc);
1626
1627 /* build a suitable I/O command (assumes 512-byte rounded transfers) */
1628 mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1568 /* spin until something prevents us from doing any work */
1569 s = splbio();
1570 for (;;) {
1571
1572 /* see if there's work to be done */
1573 if ((bp = bufq_first(&sc->mlx_bufq)) == NULL)
1574 break;
1575 /* get a command */

--- 22 unchanged lines hidden (view full) ---

1598 cmd = MLX_CMD_WRITEOLDSG;
1599 }
1600
1601 /* map the command so the controller can work with it */
1602 mlx_mapcmd(mc);
1603
1604 /* build a suitable I/O command (assumes 512-byte rounded transfers) */
1605 mlxd = (struct mlxd_softc *)bp->b_dev->si_drv1;
1629 driveno = mlxd->mlxd_drive - &sc->mlx_sysdrive[0];
1606 driveno = mlxd->mlxd_drive - sc->mlx_sysdrive;
1630 blkcount = (bp->b_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1631
1632 if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1633 device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1634 bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
1635
1636 /*
1637 * Build the I/O command. Note that the SG list type bits are set to zero,

--- 11 unchanged lines hidden (view full) ---

1649 if (mlx_start(mc) != 0) {
1650 /* fail the command */
1651 mc->mc_status = MLX_STATUS_WEDGED;
1652 mlx_completeio(mc);
1653 }
1654 s = splbio();
1655 }
1656 splx(s);
1607 blkcount = (bp->b_bcount + MLX_BLKSIZE - 1) / MLX_BLKSIZE;
1608
1609 if ((bp->b_pblkno + blkcount) > sc->mlx_sysdrive[driveno].ms_size)
1610 device_printf(sc->mlx_dev, "I/O beyond end of unit (%u,%d > %u)\n",
1611 bp->b_pblkno, blkcount, sc->mlx_sysdrive[driveno].ms_size);
1612
1613 /*
1614 * Build the I/O command. Note that the SG list type bits are set to zero,

--- 11 unchanged lines hidden (view full) ---

1626 if (mlx_start(mc) != 0) {
1627 /* fail the command */
1628 mc->mc_status = MLX_STATUS_WEDGED;
1629 mlx_completeio(mc);
1630 }
1631 s = splbio();
1632 }
1633 splx(s);
1634 mlx_lock_clr(sc, MLX_LOCK_STARTING);
1657}
1658
1659/********************************************************************************
1660 * Handle completion of an I/O command.
1661 */
1662static void
1663mlx_completeio(struct mlx_command *mc)
1664{

--- 205 unchanged lines hidden (view full) ---

1870 if (mc->mc_flags & MLX_CMD_DATAOUT)
1871 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
1872
1873 bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
1874 }
1875}
1876
1877/********************************************************************************
1635}
1636
1637/********************************************************************************
1638 * Handle completion of an I/O command.
1639 */
1640static void
1641mlx_completeio(struct mlx_command *mc)
1642{

--- 205 unchanged lines hidden (view full) ---

1848 if (mc->mc_flags & MLX_CMD_DATAOUT)
1849 bus_dmamap_sync(sc->mlx_buffer_dmat, mc->mc_dmamap, BUS_DMASYNC_POSTWRITE);
1850
1851 bus_dmamap_unload(sc->mlx_buffer_dmat, mc->mc_dmamap);
1852 }
1853}
1854
1855/********************************************************************************
1878 * Try to deliver (mc) to the controller. Take care of any completed commands
1879 * that we encounter while doing so.
1856 * Try to deliver (mc) to the controller.
1880 *
1881 * Can be called at any interrupt level, with or without interrupts enabled.
1882 */
1883static int
1884mlx_start(struct mlx_command *mc)
1885{
1886 struct mlx_softc *sc = mc->mc_sc;
1857 *
1858 * Can be called at any interrupt level, with or without interrupts enabled.
1859 */
1860static int
1861mlx_start(struct mlx_command *mc)
1862{
1863 struct mlx_softc *sc = mc->mc_sc;
1887 int i, s, done, worked;
1864 int i, s, done;
1888
1889 debug("called");
1890
1891 /* save the slot number as ident so we can handle this command when complete */
1892 mc->mc_mailbox[0x1] = mc->mc_slot;
1893
1894 /* mark the command as currently being processed */
1895 mc->mc_status = MLX_STATUS_BUSY;
1865
1866 debug("called");
1867
1868 /* save the slot number as ident so we can handle this command when complete */
1869 mc->mc_mailbox[0x1] = mc->mc_slot;
1870
1871 /* mark the command as currently being processed */
1872 mc->mc_status = MLX_STATUS_BUSY;
1896
1897 /* assume we don't collect any completed commands */
1898 worked = 0;
1899
1873
1874 /* set a default 60-second timeout XXX tunable? XXX not currently used */
1875 mc->mc_timeout = time_second + 60;
1876
1900 /* spin waiting for the mailbox */
1901 for (i = 100000, done = 0; (i > 0) && !done; i--) {
1902 s = splbio();
1903 if (sc->mlx_tryqueue(sc, mc)) {
1904 done = 1;
1905 /* move command to work queue */
1906 TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
1907 }
1877 /* spin waiting for the mailbox */
1878 for (i = 100000, done = 0; (i > 0) && !done; i--) {
1879 s = splbio();
1880 if (sc->mlx_tryqueue(sc, mc)) {
1881 done = 1;
1882 /* move command to work queue */
1883 TAILQ_INSERT_TAIL(&sc->mlx_work, mc, mc_link);
1884 }
1908 splx(s);
1909 /* check for command completion while we're at it */
1910 if (mlx_done(sc))
1911 worked = 1;
1885 splx(s); /* drop spl to allow completion interrupts */
1912 }
1886 }
1913 /* check to see if we picked up any completed commands */
1914 if (worked)
1915 mlx_complete(sc);
1916
1917 /* command is enqueued */
1918 if (done)
1919 return(0);
1920
1921 /*
1922 * We couldn't get the controller to take the command. Revoke the slot
1923 * that the command was given and return it with a bad status.
1924 */
1925 sc->mlx_busycmd[mc->mc_slot] = NULL;
1926 device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
1927 mc->mc_status = MLX_STATUS_WEDGED;
1887
1888 /* command is enqueued */
1889 if (done)
1890 return(0);
1891
1892 /*
1893 * We couldn't get the controller to take the command. Revoke the slot
1894 * that the command was given and return it with a bad status.
1895 */
1896 sc->mlx_busycmd[mc->mc_slot] = NULL;
1897 device_printf(sc->mlx_dev, "controller wedged (not taking commands)\n");
1898 mc->mc_status = MLX_STATUS_WEDGED;
1899 mlx_complete(sc);
1928 return(EIO);
1929}
1930
1931/********************************************************************************
1900 return(EIO);
1901}
1902
1903/********************************************************************************
1932 * Look at the controller (sc) and see if a command has been completed.
1933 * If so, move the command buffer to the done queue for later collection
1934 * and free the slot for immediate reuse.
1904 * Poll the controller (sc) for completed commands.
1905 * Update command status and free slots for reuse. If any slots were freed,
1906 * new commands may be posted.
1935 *
1907 *
1936 * Returns nonzero if anything was added to the done queue.
1908 * Returns nonzero if one or more commands were completed.
1937 */
1938static int
1939mlx_done(struct mlx_softc *sc)
1940{
1941 struct mlx_command *mc;
1909 */
1910static int
1911mlx_done(struct mlx_softc *sc)
1912{
1913 struct mlx_command *mc;
1942 int s;
1914 int s, result;
1943 u_int8_t slot;
1944 u_int16_t status;
1945
1946 debug("called");
1947
1915 u_int8_t slot;
1916 u_int16_t status;
1917
1918 debug("called");
1919
1948 mc = NULL;
1949 slot = 0;
1920 result = 0;
1950
1921
1951 /* poll for a completed command's identifier and status */
1922 /* loop collecting completed commands */
1952 s = splbio();
1923 s = splbio();
1953 if (sc->mlx_findcomplete(sc, &slot, &status)) {
1954 mc = sc->mlx_busycmd[slot]; /* find command */
1955 if (mc != NULL) { /* paranoia */
1956 if (mc->mc_status == MLX_STATUS_BUSY) {
1957 mc->mc_status = status; /* save status */
1924 for (;;) {
1925 /* poll for a completed command's identifier and status */
1926 if (sc->mlx_findcomplete(sc, &slot, &status)) {
1927 result = 1;
1928 mc = sc->mlx_busycmd[slot]; /* find command */
1929 if (mc != NULL) { /* paranoia */
1930 if (mc->mc_status == MLX_STATUS_BUSY) {
1931 mc->mc_status = status; /* save status */
1958
1932
1959 /* free slot for reuse */
1960 sc->mlx_busycmd[slot] = NULL;
1961 sc->mlx_busycmds--;
1933 /* free slot for reuse */
1934 sc->mlx_busycmd[slot] = NULL;
1935 sc->mlx_busycmds--;
1936 } else {
1937 device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
1938 }
1962 } else {
1939 } else {
1963 device_printf(sc->mlx_dev, "duplicate done event for slot %d\n", slot);
1964 mc = NULL;
1940 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
1965 }
1966 } else {
1941 }
1942 } else {
1967 device_printf(sc->mlx_dev, "done event for nonbusy slot %d\n", slot);
1943 break;
1968 }
1969 }
1944 }
1945 }
1970 splx(s);
1971
1946
1972 if (mc != NULL) {
1973 /* unmap the command's data buffer */
1974 mlx_unmapcmd(mc);
1975 return(1);
1976 }
1977 return(0);
1947 /* if we've completed any commands, try posting some more */
1948 if (result)
1949 mlx_startio(sc);
1950
1951 /* handle completion and timeouts */
1952 mlx_complete(sc);
1953
1954 return(result);
1978}
1979
1980/********************************************************************************
1955}
1956
1957/********************************************************************************
1981 * Handle completion for all commands on (sc)'s done queue.
1958 * Perform post-completion processing for commands on (sc).
1982 */
1983static void
1984mlx_complete(struct mlx_softc *sc)
1985{
1986 struct mlx_command *mc, *nc;
1987 int s, count;
1988
1989 debug("called");
1990
1959 */
1960static void
1961mlx_complete(struct mlx_softc *sc)
1962{
1963 struct mlx_command *mc, *nc;
1964 int s, count;
1965
1966 debug("called");
1967
1968 /* avoid reentrancy XXX might want to signal and request a restart */
1969 if (mlx_lock_tas(sc, MLX_LOCK_COMPLETING))
1970 return;
1971
1991 s = splbio();
1992 count = 0;
1972 s = splbio();
1973 count = 0;
1993
1994 /* scan the list of done commands */
1974
1975 /* scan the list of busy/done commands */
1995 mc = TAILQ_FIRST(&sc->mlx_work);
1996 while (mc != NULL) {
1997 nc = TAILQ_NEXT(mc, mc_link);
1998
1999 /* XXX this is slightly bogus */
2000 if (count++ > (sc->mlx_maxiop * 2))
2001 panic("mlx_work list corrupt!");
2002
1976 mc = TAILQ_FIRST(&sc->mlx_work);
1977 while (mc != NULL) {
1978 nc = TAILQ_NEXT(mc, mc_link);
1979
1980 /* XXX this is slightly bogus */
1981 if (count++ > (sc->mlx_maxiop * 2))
1982 panic("mlx_work list corrupt!");
1983
2003 /* Skip commands that are still busy */
1984 /* Command has been completed in some fashion */
2004 if (mc->mc_status != MLX_STATUS_BUSY) {
1985 if (mc->mc_status != MLX_STATUS_BUSY) {
2005
2006
1986
1987 /* unmap the command's data buffer */
1988 mlx_unmapcmd(mc);
2007 /*
1989 /*
2008 * Does the command have a completion handler?
2009 */
1990 * Does the command have a completion handler?
1991 */
2010 if (mc->mc_complete != NULL) {
2011 /* remove from list and give to handler */
2012 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
2013 mc->mc_complete(mc);
2014
2015 /*
2016 * Is there a sleeper waiting on this command?
2017 */

--- 8 unchanged lines hidden (view full) ---

2026 */
2027 } else {
2028 }
2029 }
2030 mc = nc;
2031 }
2032 splx(s);
2033
1992 if (mc->mc_complete != NULL) {
1993 /* remove from list and give to handler */
1994 TAILQ_REMOVE(&sc->mlx_work, mc, mc_link);
1995 mc->mc_complete(mc);
1996
1997 /*
1998 * Is there a sleeper waiting on this command?
1999 */

--- 8 unchanged lines hidden (view full) ---

2008 */
2009 } else {
2010 }
2011 }
2012 mc = nc;
2013 }
2014 splx(s);
2015
2034 /* queue some more work if there is any */
2035 mlx_startio(sc);
2016 mlx_lock_clr(sc, MLX_LOCK_COMPLETING);
2036}
2037
2038/********************************************************************************
2039 ********************************************************************************
2040 Command Buffer Management
2041 ********************************************************************************
2042 ********************************************************************************/
2043

--- 231 unchanged lines hidden (view full) ---

2275 sc->mlx_state |= MLX_STATE_INTEN;
2276 break;
2277 }
2278}
2279
2280
2281/********************************************************************************
2282 ********************************************************************************
2017}
2018
2019/********************************************************************************
2020 ********************************************************************************
2021 Command Buffer Management
2022 ********************************************************************************
2023 ********************************************************************************/
2024

--- 231 unchanged lines hidden (view full) ---

2256 sc->mlx_state |= MLX_STATE_INTEN;
2257 break;
2258 }
2259}
2260
2261
2262/********************************************************************************
2263 ********************************************************************************
2264 Type 5 interface accessor methods
2265 ********************************************************************************
2266 ********************************************************************************/
2267
2268/********************************************************************************
2269 * Try to give (mc) to the controller. Returns 1 if successful, 0 on failure
2270 * (the controller is not ready to take a command).
2271 *
2272 * Must be called at splbio or in a fashion that prevents reentry.
2273 */
2274static int
2275mlx_v5_tryqueue(struct mlx_softc *sc, struct mlx_command *mc)
2276{
2277 int i;
2278
2279 debug("called");
2280
2281 /* ready for our command? */
2282 if (MLX_V5_GET_IDBR(sc) & MLX_V5_IDB_EMPTY) {
2283 /* copy mailbox data to window */
2284 for (i = 0; i < 13; i++)
2285 MLX_V5_PUT_MAILBOX(sc, i, mc->mc_mailbox[i]);
2286
2287 /* post command */
2288 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_HWMBOX_CMD);
2289 return(1);
2290 }
2291 return(0);
2292}
2293
2294/********************************************************************************
2295 * See if a command has been completed, if so acknowledge its completion
2296 * and recover the slot number and status code.
2297 *
2298 * Must be called at splbio or in a fashion that prevents reentry.
2299 */
2300static int
2301mlx_v5_findcomplete(struct mlx_softc *sc, u_int8_t *slot, u_int16_t *status)
2302{
2303
2304 debug("called");
2305
2306 /* status available? */
2307 if (MLX_V5_GET_ODBR(sc) & MLX_V5_ODB_HWSAVAIL) {
2308 *slot = MLX_V5_GET_STATUS_IDENT(sc); /* get command identifier */
2309 *status = MLX_V5_GET_STATUS(sc); /* get status */
2310
2311 /* acknowledge completion */
2312 MLX_V5_PUT_ODBR(sc, MLX_V5_ODB_HWMBOX_ACK);
2313 MLX_V5_PUT_IDBR(sc, MLX_V5_IDB_SACK);
2314 return(1);
2315 }
2316 return(0);
2317}
2318
2319/********************************************************************************
2320 * Enable/disable interrupts as requested.
2321 *
2322 * Must be called at splbio or in a fashion that prevents reentry.
2323 */
2324static void
2325mlx_v5_intaction(struct mlx_softc *sc, int action)
2326{
2327 debug("called");
2328
2329 switch(action) {
2330 case MLX_INTACTION_DISABLE:
2331 MLX_V5_PUT_IER(sc, MLX_V5_IER_DISINT);
2332 sc->mlx_state &= ~MLX_STATE_INTEN;
2333 break;
2334 case MLX_INTACTION_ENABLE:
2335 MLX_V5_PUT_IER(sc, 0);
2336 sc->mlx_state |= MLX_STATE_INTEN;
2337 break;
2338 }
2339}
2340
2341
2342/********************************************************************************
2343 ********************************************************************************
2283 Debugging
2284 ********************************************************************************
2285 ********************************************************************************/
2286
2287/********************************************************************************
2288 * Return a status message describing (mc)
2289 */
2290static char *mlx_status_messages[] = {

--- 55 unchanged lines hidden (view full) ---

2346
2347 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2348 return(unkmsg);
2349}
2350
2351/*******************************************************************************
2352 * Return a string describing the controller (hwid)
2353 */
2344 Debugging
2345 ********************************************************************************
2346 ********************************************************************************/
2347
2348/********************************************************************************
2349 * Return a status message describing (mc)
2350 */
2351static char *mlx_status_messages[] = {

--- 55 unchanged lines hidden (view full) ---

2407
2408 sprintf(unkmsg, "unknown response 0x%x for command 0x%x", (int)mc->mc_status, (int)mc->mc_mailbox[0]);
2409 return(unkmsg);
2410}
2411
2412/*******************************************************************************
2413 * Return a string describing the controller (hwid)
2414 */
2415static struct
2416{
2417 int hwid;
2418 char *name;
2419} mlx_controller_names[] = {
2420 {0x01, "960P/PD"},
2421 {0x02, "960PL"},
2422 {0x10, "960PG"},
2423 {0x11, "960PJ"},
2424 {0x16, "960PTL"},
2425 {0x20, "1164P"},
2426 {-1, NULL}
2427};
2428
2354static char *
2355mlx_name_controller(u_int32_t hwid)
2356{
2357 static char buf[80];
2429static char *
2430mlx_name_controller(u_int32_t hwid)
2431{
2432 static char buf[80];
2358 char smbuf[16];
2359 char *submodel;
2360 int nchn;
2361
2362 switch(hwid & 0xff) {
2363 case 0x01:
2364 submodel = "P/PD";
2365 break;
2366 case 0x02:
2367 submodel = "PL";
2368 break;
2369 case 0x10:
2370 submodel = "PG";
2371 break;
2372 case 0x11:
2373 submodel = "PJ";
2374 break;
2375 case 0x16:
2376 submodel = "PTL";
2377 break;
2378 default:
2379 sprintf(smbuf, " model 0x%x", hwid & 0xff);
2380 submodel = smbuf;
2381 break;
2433 char *model;
2434 int nchn, i;
2435
2436 for (i = 0, model = NULL; mlx_controller_names[i].name != NULL; i++) {
2437 if ((hwid & 0xff) == mlx_controller_names[i].hwid) {
2438 model = mlx_controller_names[i].name;
2439 break;
2440 }
2382 }
2441 }
2442 if (model == NULL) {
2443 sprintf(buf, " model 0x%x", hwid & 0xff);
2444 model = buf;
2445 }
2383 nchn = (hwid >> 8) & 0xff;
2446 nchn = (hwid >> 8) & 0xff;
2384 sprintf(buf, "DAC960%s, %d channel%s", submodel, nchn, nchn > 1 ? "s" : "");
2447 sprintf(buf, "DAC%s, %d channel%s", model, nchn, nchn > 1 ? "s" : "");
2385 return(buf);
2386}
2387
2388/********************************************************************************
2389 ********************************************************************************
2390 Utility Functions
2391 ********************************************************************************
2392 ********************************************************************************/

--- 20 unchanged lines hidden ---
2448 return(buf);
2449}
2450
2451/********************************************************************************
2452 ********************************************************************************
2453 Utility Functions
2454 ********************************************************************************
2455 ********************************************************************************/

--- 20 unchanged lines hidden ---