Deleted Added
full compact
mly.c (68877) mly.c (73050)
1/*-
1/*-
2 * Copyright (c) 2000 Michael Smith
2 * Copyright (c) 2000, 2001 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.

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

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 *
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.

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

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 * $FreeBSD: head/sys/dev/mly/mly.c 68877 2000-11-18 15:21:22Z dwmalone $
27 * $FreeBSD: head/sys/dev/mly/mly.c 73050 2001-02-25 22:48:34Z msmith $
28 */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/kernel.h>
34#include <sys/bus.h>
35#include <sys/conf.h>
36#include <sys/ctype.h>
28 */
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/malloc.h>
33#include <sys/kernel.h>
34#include <sys/bus.h>
35#include <sys/conf.h>
36#include <sys/ctype.h>
37#include <sys/ioccom.h>
38#include <sys/stat.h>
37
38#include <machine/bus_memio.h>
39#include <machine/bus.h>
40#include <machine/resource.h>
41#include <sys/rman.h>
42
43#include <cam/scsi/scsi_all.h>
44
45#include <dev/mly/mlyreg.h>
39
40#include <machine/bus_memio.h>
41#include <machine/bus.h>
42#include <machine/resource.h>
43#include <sys/rman.h>
44
45#include <cam/scsi/scsi_all.h>
46
47#include <dev/mly/mlyreg.h>
48#include <dev/mly/mlyio.h>
46#include <dev/mly/mlyvar.h>
47#define MLY_DEFINE_TABLES
48#include <dev/mly/mly_tables.h>
49
50static int mly_get_controllerinfo(struct mly_softc *sc);
51static void mly_scan_devices(struct mly_softc *sc);
52static void mly_rescan_btl(struct mly_softc *sc, int bus, int target);
53static void mly_complete_rescan(struct mly_command *mc);

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

60static void mly_complete_event(struct mly_command *mc);
61static void mly_process_event(struct mly_softc *sc, struct mly_event *me);
62static void mly_periodic(void *data);
63
64static int mly_immediate_command(struct mly_command *mc);
65static int mly_start(struct mly_command *mc);
66static void mly_complete(void *context, int pending);
67
49#include <dev/mly/mlyvar.h>
50#define MLY_DEFINE_TABLES
51#include <dev/mly/mly_tables.h>
52
53static int mly_get_controllerinfo(struct mly_softc *sc);
54static void mly_scan_devices(struct mly_softc *sc);
55static void mly_rescan_btl(struct mly_softc *sc, int bus, int target);
56static void mly_complete_rescan(struct mly_command *mc);

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

63static void mly_complete_event(struct mly_command *mc);
64static void mly_process_event(struct mly_softc *sc, struct mly_event *me);
65static void mly_periodic(void *data);
66
67static int mly_immediate_command(struct mly_command *mc);
68static int mly_start(struct mly_command *mc);
69static void mly_complete(void *context, int pending);
70
68static int mly_get_slot(struct mly_command *mc);
69static void mly_alloc_command_cluster_map(void *arg, bus_dma_segment_t *segs, int nseg, int error);
70static void mly_alloc_command_cluster(struct mly_softc *sc);
71static void mly_alloc_commands_map(void *arg, bus_dma_segment_t *segs, int nseg, int error);
72static int mly_alloc_commands(struct mly_softc *sc);
71static void mly_map_command(struct mly_command *mc);
72static void mly_unmap_command(struct mly_command *mc);
73
74static int mly_fwhandshake(struct mly_softc *sc);
75
76static void mly_describe_controller(struct mly_softc *sc);
77#ifdef MLY_DEBUG
78static void mly_printstate(struct mly_softc *sc);
79static void mly_print_command(struct mly_command *mc);
80static void mly_print_packet(struct mly_command *mc);
81static void mly_panic(struct mly_softc *sc, char *reason);
82#endif
73static void mly_map_command(struct mly_command *mc);
74static void mly_unmap_command(struct mly_command *mc);
75
76static int mly_fwhandshake(struct mly_softc *sc);
77
78static void mly_describe_controller(struct mly_softc *sc);
79#ifdef MLY_DEBUG
80static void mly_printstate(struct mly_softc *sc);
81static void mly_print_command(struct mly_command *mc);
82static void mly_print_packet(struct mly_command *mc);
83static void mly_panic(struct mly_softc *sc, char *reason);
84#endif
85void mly_print_controller(int controller);
83
86
87static d_open_t mly_user_open;
88static d_close_t mly_user_close;
89static d_ioctl_t mly_user_ioctl;
90static int mly_user_command(struct mly_softc *sc, struct mly_user_command *uc);
91static int mly_user_health(struct mly_softc *sc, struct mly_user_health *uh);
92
93#define MLY_CDEV_MAJOR 158
94
95static struct cdevsw mly_cdevsw = {
96 mly_user_open,
97 mly_user_close,
98 noread,
99 nowrite,
100 mly_user_ioctl,
101 nopoll,
102 nommap,
103 nostrategy,
104 "mly",
105 MLY_CDEV_MAJOR,
106 nodump,
107 nopsize,
108 0,
109 -1
110};
111
84/********************************************************************************
85 ********************************************************************************
86 Device Interface
87 ********************************************************************************
88 ********************************************************************************/
89
90/********************************************************************************
91 * Initialise the controller and softc
92 */
93int
94mly_attach(struct mly_softc *sc)
95{
96 int error;
97
98 debug_called(1);
99
100 /*
101 * Initialise per-controller queues.
102 */
112/********************************************************************************
113 ********************************************************************************
114 Device Interface
115 ********************************************************************************
116 ********************************************************************************/
117
118/********************************************************************************
119 * Initialise the controller and softc
120 */
121int
122mly_attach(struct mly_softc *sc)
123{
124 int error;
125
126 debug_called(1);
127
128 /*
129 * Initialise per-controller queues.
130 */
103 TAILQ_INIT(&sc->mly_freecmds);
104 TAILQ_INIT(&sc->mly_ready);
105 TAILQ_INIT(&sc->mly_completed);
106 TAILQ_INIT(&sc->mly_clusters);
131 mly_initq_free(sc);
132 mly_initq_ready(sc);
133 mly_initq_busy(sc);
134 mly_initq_complete(sc);
107
108#if __FreeBSD_version >= 500005
109 /*
110 * Initialise command-completion task.
111 */
112 TASK_INIT(&sc->mly_task_complete, 0, mly_complete, sc);
113#endif
114

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

119 * Wait for the controller to come ready, handshake with the firmware if required.
120 * This is typically only necessary on platforms where the controller BIOS does not
121 * run.
122 */
123 if ((error = mly_fwhandshake(sc)))
124 return(error);
125
126 /*
135
136#if __FreeBSD_version >= 500005
137 /*
138 * Initialise command-completion task.
139 */
140 TASK_INIT(&sc->mly_task_complete, 0, mly_complete, sc);
141#endif
142

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

147 * Wait for the controller to come ready, handshake with the firmware if required.
148 * This is typically only necessary on platforms where the controller BIOS does not
149 * run.
150 */
151 if ((error = mly_fwhandshake(sc)))
152 return(error);
153
154 /*
127 * Initialise the slot allocator so that we can issue commands.
155 * Allocate command buffers
128 */
156 */
129 sc->mly_max_commands = MLY_SLOT_MAX;
130 sc->mly_last_slot = MLY_SLOT_START;
157 if ((error = mly_alloc_commands(sc)))
158 return(error);
131
132 /*
133 * Obtain controller feature information
134 */
135 if ((error = mly_get_controllerinfo(sc)))
136 return(error);
137
138 /*
159
160 /*
161 * Obtain controller feature information
162 */
163 if ((error = mly_get_controllerinfo(sc)))
164 return(error);
165
166 /*
139 * Update the slot allocator limit based on the controller inquiry.
140 */
141 sc->mly_max_commands = imin(sc->mly_controllerinfo->maximum_parallel_commands, MLY_SLOT_MAX);
142
143 /*
144 * Get the current event counter for health purposes, populate the initial
145 * health status buffer.
146 */
147 if ((error = mly_get_eventstatus(sc)))
148 return(error);
149
150 /*
151 * Enable memory-mailbox mode

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

172 /*
173 * Instigate the first status poll immediately. Rescan completions won't
174 * happen until interrupts are enabled, which should still be before
175 * the SCSI subsystem gets to us. (XXX assuming CAM and interrupt-driven
176 * discovery here...)
177 */
178 mly_periodic((void *)sc);
179
167 * Get the current event counter for health purposes, populate the initial
168 * health status buffer.
169 */
170 if ((error = mly_get_eventstatus(sc)))
171 return(error);
172
173 /*
174 * Enable memory-mailbox mode

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

195 /*
196 * Instigate the first status poll immediately. Rescan completions won't
197 * happen until interrupts are enabled, which should still be before
198 * the SCSI subsystem gets to us. (XXX assuming CAM and interrupt-driven
199 * discovery here...)
200 */
201 mly_periodic((void *)sc);
202
203 /*
204 * Create the control device.
205 */
206 sc->mly_dev_t = make_dev(&mly_cdevsw, device_get_unit(sc->mly_dev), UID_ROOT, GID_OPERATOR,
207 S_IRUSR | S_IWUSR, "mly%d", device_get_unit(sc->mly_dev));
208 sc->mly_dev_t->si_drv1 = sc;
209
180 /* enable interrupts now */
181 MLY_UNMASK_INTERRUPTS(sc);
182
183 return(0);
184}
185
186/********************************************************************************
187 * Bring the controller to a state where it can be safely left alone.

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

365 mly_describe_code(mly_table_device_state, ldi->state));
366 } else if (mc->mc_length == sizeof(*pdi)) {
367 pdi = (struct mly_ioctl_getphysdevinfovalid *)mc->mc_data;
368 bus = pdi->channel;
369 target = pdi->target;
370 sc->mly_btl[bus][target].mb_flags = MLY_BTL_PHYSICAL; /* clears all other flags */
371 sc->mly_btl[bus][target].mb_type = MLY_DEVICE_TYPE_PHYSICAL;
372 sc->mly_btl[bus][target].mb_state = pdi->state;
210 /* enable interrupts now */
211 MLY_UNMASK_INTERRUPTS(sc);
212
213 return(0);
214}
215
216/********************************************************************************
217 * Bring the controller to a state where it can be safely left alone.

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

395 mly_describe_code(mly_table_device_state, ldi->state));
396 } else if (mc->mc_length == sizeof(*pdi)) {
397 pdi = (struct mly_ioctl_getphysdevinfovalid *)mc->mc_data;
398 bus = pdi->channel;
399 target = pdi->target;
400 sc->mly_btl[bus][target].mb_flags = MLY_BTL_PHYSICAL; /* clears all other flags */
401 sc->mly_btl[bus][target].mb_type = MLY_DEVICE_TYPE_PHYSICAL;
402 sc->mly_btl[bus][target].mb_state = pdi->state;
403 sc->mly_btl[bus][target].mb_speed = pdi->speed;
404 sc->mly_btl[bus][target].mb_width = pdi->width;
373 if (pdi->state != MLY_DEVICE_STATE_UNCONFIGURED)
374 sc->mly_btl[bus][target].mb_flags |= MLY_BTL_PROTECTED;
375 debug(2, "BTL rescan for %d:%d returns %s", bus, target,
376 mly_describe_code(mly_table_device_state, pdi->state));
377 } else {
378 mly_printf(sc, "BTL rescan result corrupted\n");
379 }
380 } else {

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

433 int error;
434
435 debug_called(1);
436
437 /* build the ioctl and send it */
438 bzero(&mci, sizeof(mci));
439 mci.sub_ioctl = MDACIOCTL_SETMEMORYMAILBOX;
440 /* set buffer addresses */
405 if (pdi->state != MLY_DEVICE_STATE_UNCONFIGURED)
406 sc->mly_btl[bus][target].mb_flags |= MLY_BTL_PROTECTED;
407 debug(2, "BTL rescan for %d:%d returns %s", bus, target,
408 mly_describe_code(mly_table_device_state, pdi->state));
409 } else {
410 mly_printf(sc, "BTL rescan result corrupted\n");
411 }
412 } else {

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

465 int error;
466
467 debug_called(1);
468
469 /* build the ioctl and send it */
470 bzero(&mci, sizeof(mci));
471 mci.sub_ioctl = MDACIOCTL_SETMEMORYMAILBOX;
472 /* set buffer addresses */
441 mci.param.setmemorymailbox.command_mailbox_physaddr = sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_command);
442 mci.param.setmemorymailbox.status_mailbox_physaddr = sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_status);
443 mci.param.setmemorymailbox.health_buffer_physaddr = sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_health);
473 mci.param.setmemorymailbox.command_mailbox_physaddr =
474 sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_command);
475 mci.param.setmemorymailbox.status_mailbox_physaddr =
476 sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_status);
477 mci.param.setmemorymailbox.health_buffer_physaddr =
478 sc->mly_mmbox_busaddr + offsetof(struct mly_mmbox, mmm_health);
444
445 /* set buffer sizes - abuse of data_size field is revolting */
446 sp = (u_int8_t *)&mci.data_size;
447 sp[0] = ((sizeof(union mly_command_packet) * MLY_MMBOX_COMMANDS) / 1024);
448 sp[1] = (sizeof(union mly_status_packet) * MLY_MMBOX_STATUS) / 1024;
449 mci.param.setmemorymailbox.health_buffer_size = sizeof(union mly_health_region) / 1024;
450
451 debug(1, "memory mailbox at %p (0x%llx/%d 0x%llx/%d 0x%llx/%d", sc->mly_mmbox,
452 mci.param.setmemorymailbox.command_mailbox_physaddr, sp[0],
453 mci.param.setmemorymailbox.status_mailbox_physaddr, sp[1],
479
480 /* set buffer sizes - abuse of data_size field is revolting */
481 sp = (u_int8_t *)&mci.data_size;
482 sp[0] = ((sizeof(union mly_command_packet) * MLY_MMBOX_COMMANDS) / 1024);
483 sp[1] = (sizeof(union mly_status_packet) * MLY_MMBOX_STATUS) / 1024;
484 mci.param.setmemorymailbox.health_buffer_size = sizeof(union mly_health_region) / 1024;
485
486 debug(1, "memory mailbox at %p (0x%llx/%d 0x%llx/%d 0x%llx/%d", sc->mly_mmbox,
487 mci.param.setmemorymailbox.command_mailbox_physaddr, sp[0],
488 mci.param.setmemorymailbox.status_mailbox_physaddr, sp[1],
454 mci.param.setmemorymailbox.health_buffer_physaddr, mci.param.setmemorymailbox.health_buffer_size);
489 mci.param.setmemorymailbox.health_buffer_physaddr,
490 mci.param.setmemorymailbox.health_buffer_size);
455
456 if ((error = mly_ioctl(sc, &mci, NULL, 0, &status, NULL, NULL)))
457 return(error);
458 if (status != 0)
459 return(EIO);
460 sc->mly_state |= MLY_STATE_MMBOX_ACTIVE;
461 debug(1, "memory mailbox active");
462 return(0);

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

801
802 /* spinning at splcam is ugly, but we're only used during controller init */
803 s = splcam();
804 if ((error = mly_start(mc)))
805 return(error);
806
807 if (sc->mly_state & MLY_STATE_INTERRUPTS_ON) {
808 /* sleep on the command */
491
492 if ((error = mly_ioctl(sc, &mci, NULL, 0, &status, NULL, NULL)))
493 return(error);
494 if (status != 0)
495 return(EIO);
496 sc->mly_state |= MLY_STATE_MMBOX_ACTIVE;
497 debug(1, "memory mailbox active");
498 return(0);

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

837
838 /* spinning at splcam is ugly, but we're only used during controller init */
839 s = splcam();
840 if ((error = mly_start(mc)))
841 return(error);
842
843 if (sc->mly_state & MLY_STATE_INTERRUPTS_ON) {
844 /* sleep on the command */
809 while(MLY_CMD_STATE(mc) != MLY_CMD_COMPLETE) {
845 while(!(mc->mc_flags & MLY_CMD_COMPLETE)) {
810 tsleep(mc, PRIBIO, "mlywait", 0);
811 }
812 } else {
813 /* spin and collect status while we do */
846 tsleep(mc, PRIBIO, "mlywait", 0);
847 }
848 } else {
849 /* spin and collect status while we do */
814 while(MLY_CMD_STATE(mc) != MLY_CMD_COMPLETE)
850 while(!(mc->mc_flags & MLY_CMD_COMPLETE)) {
815 mly_done(mc->mc_sc);
851 mly_done(mc->mc_sc);
852 }
816 }
817 splx(s);
818 return(0);
819}
820
821/********************************************************************************
822 * Start as much queued I/O as possible on the controller
823 */

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

859{
860 struct mly_softc *sc = mc->mc_sc;
861 union mly_command_packet *pkt;
862 int s;
863
864 debug_called(2);
865
866 /*
853 }
854 splx(s);
855 return(0);
856}
857
858/********************************************************************************
859 * Start as much queued I/O as possible on the controller
860 */

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

896{
897 struct mly_softc *sc = mc->mc_sc;
898 union mly_command_packet *pkt;
899 int s;
900
901 debug_called(2);
902
903 /*
867 * Set the command up for delivery to the controller. This may fail
868 * due to resource shortages.
904 * Set the command up for delivery to the controller.
869 */
905 */
870 if (mly_get_slot(mc))
871 return(EBUSY);
872 mly_map_command(mc);
906 mly_map_command(mc);
907 mc->mc_packet->generic.command_id = mc->mc_slot;
873
874 s = splcam();
908
909 s = splcam();
910
875 /*
876 * Do we have to use the hardware mailbox?
877 */
878 if (!(sc->mly_state & MLY_STATE_MMBOX_ACTIVE)) {
879 /*
880 * Check to see if the controller is ready for us.
881 */
882 if (MLY_IDBR_TRUE(sc, MLY_HM_CMDSENT)) {
883 splx(s);
884 return(EBUSY);
885 }
911 /*
912 * Do we have to use the hardware mailbox?
913 */
914 if (!(sc->mly_state & MLY_STATE_MMBOX_ACTIVE)) {
915 /*
916 * Check to see if the controller is ready for us.
917 */
918 if (MLY_IDBR_TRUE(sc, MLY_HM_CMDSENT)) {
919 splx(s);
920 return(EBUSY);
921 }
886
922 mc->mc_flags |= MLY_CMD_BUSY;
923
887 /*
888 * It's ready, send the command.
889 */
890 MLY_SET_MBOX(sc, sc->mly_command_mailbox, &mc->mc_packetphys);
891 MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_CMDSENT);
892
893 } else { /* use memory-mailbox mode */
894
895 pkt = &sc->mly_mmbox->mmm_command[sc->mly_mmbox_command_index];
896
924 /*
925 * It's ready, send the command.
926 */
927 MLY_SET_MBOX(sc, sc->mly_command_mailbox, &mc->mc_packetphys);
928 MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_CMDSENT);
929
930 } else { /* use memory-mailbox mode */
931
932 pkt = &sc->mly_mmbox->mmm_command[sc->mly_mmbox_command_index];
933
897 /* check to see if the next slot is free yet */
934 /* check to see if the next index is free yet */
898 if (pkt->mmbox.flag != 0) {
899 splx(s);
900 return(EBUSY);
901 }
935 if (pkt->mmbox.flag != 0) {
936 splx(s);
937 return(EBUSY);
938 }
939 mc->mc_flags |= MLY_CMD_BUSY;
902
903 /* copy in new command */
904 bcopy(mc->mc_packet->mmbox.data, pkt->mmbox.data, sizeof(pkt->mmbox.data));
905 /* barrier to ensure completion of previous write before we write the flag */
906 bus_space_barrier(NULL, NULL, 0, 0, BUS_SPACE_BARRIER_WRITE); /* tag/handle? */
907 /* copy flag last */
908 pkt->mmbox.flag = mc->mc_packet->mmbox.flag;
909 /* barrier to ensure completion of previous write before we notify the controller */
910 bus_space_barrier(NULL, NULL, 0, 0, BUS_SPACE_BARRIER_WRITE); /* tag/handle */
911
912 /* signal controller, update index */
913 MLY_SET_REG(sc, sc->mly_idbr, MLY_AM_CMDSENT);
914 sc->mly_mmbox_command_index = (sc->mly_mmbox_command_index + 1) % MLY_MMBOX_COMMANDS;
915 }
916
940
941 /* copy in new command */
942 bcopy(mc->mc_packet->mmbox.data, pkt->mmbox.data, sizeof(pkt->mmbox.data));
943 /* barrier to ensure completion of previous write before we write the flag */
944 bus_space_barrier(NULL, NULL, 0, 0, BUS_SPACE_BARRIER_WRITE); /* tag/handle? */
945 /* copy flag last */
946 pkt->mmbox.flag = mc->mc_packet->mmbox.flag;
947 /* barrier to ensure completion of previous write before we notify the controller */
948 bus_space_barrier(NULL, NULL, 0, 0, BUS_SPACE_BARRIER_WRITE); /* tag/handle */
949
950 /* signal controller, update index */
951 MLY_SET_REG(sc, sc->mly_idbr, MLY_AM_CMDSENT);
952 sc->mly_mmbox_command_index = (sc->mly_mmbox_command_index + 1) % MLY_MMBOX_COMMANDS;
953 }
954
955 mly_enqueue_busy(mc);
917 splx(s);
918 return(0);
919}
920
921/********************************************************************************
922 * Pick up command status from the controller, schedule a completion event
923 */
924void

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

931
932 s = splcam();
933 worked = 0;
934
935 /* pick up hardware-mailbox commands */
936 if (MLY_ODBR_TRUE(sc, MLY_HM_STSREADY)) {
937 slot = MLY_GET_REG2(sc, sc->mly_status_mailbox);
938 if (slot < MLY_SLOT_MAX) {
956 splx(s);
957 return(0);
958}
959
960/********************************************************************************
961 * Pick up command status from the controller, schedule a completion event
962 */
963void

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

970
971 s = splcam();
972 worked = 0;
973
974 /* pick up hardware-mailbox commands */
975 if (MLY_ODBR_TRUE(sc, MLY_HM_STSREADY)) {
976 slot = MLY_GET_REG2(sc, sc->mly_status_mailbox);
977 if (slot < MLY_SLOT_MAX) {
939 mc = sc->mly_busycmds[slot];
940 if (mc != NULL) {
941 mc->mc_status = MLY_GET_REG(sc, sc->mly_status_mailbox + 2);
942 mc->mc_sense = MLY_GET_REG(sc, sc->mly_status_mailbox + 3);
943 mc->mc_resid = MLY_GET_REG4(sc, sc->mly_status_mailbox + 4);
944 mly_enqueue_completed(mc);
945 sc->mly_busycmds[slot] = NULL;
946 worked = 1;
947 } else {
948 mly_printf(sc, "got HM completion for nonbusy slot %u\n", slot);
949 }
978 mc = &sc->mly_command[slot - MLY_SLOT_START];
979 mc->mc_status = MLY_GET_REG(sc, sc->mly_status_mailbox + 2);
980 mc->mc_sense = MLY_GET_REG(sc, sc->mly_status_mailbox + 3);
981 mc->mc_resid = MLY_GET_REG4(sc, sc->mly_status_mailbox + 4);
982 mly_remove_busy(mc);
983 mc->mc_flags &= ~MLY_CMD_BUSY;
984 mly_enqueue_complete(mc);
985 worked = 1;
950 } else {
951 /* slot 0xffff may mean "extremely bogus command" */
952 mly_printf(sc, "got HM completion for illegal slot %u\n", slot);
953 }
954 /* unconditionally acknowledge status */
955 MLY_SET_REG(sc, sc->mly_odbr, MLY_HM_STSREADY);
956 MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_STSACK);
957 }

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

963
964 /* check for more status */
965 if (sp->mmbox.flag == 0)
966 break;
967
968 /* get slot number */
969 slot = sp->status.command_id;
970 if (slot < MLY_SLOT_MAX) {
986 } else {
987 /* slot 0xffff may mean "extremely bogus command" */
988 mly_printf(sc, "got HM completion for illegal slot %u\n", slot);
989 }
990 /* unconditionally acknowledge status */
991 MLY_SET_REG(sc, sc->mly_odbr, MLY_HM_STSREADY);
992 MLY_SET_REG(sc, sc->mly_idbr, MLY_HM_STSACK);
993 }

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

999
1000 /* check for more status */
1001 if (sp->mmbox.flag == 0)
1002 break;
1003
1004 /* get slot number */
1005 slot = sp->status.command_id;
1006 if (slot < MLY_SLOT_MAX) {
971 mc = sc->mly_busycmds[slot];
972 if (mc != NULL) {
973 mc->mc_status = sp->status.status;
974 mc->mc_sense = sp->status.sense_length;
975 mc->mc_resid = sp->status.residue;
976 mly_enqueue_completed(mc);
977 sc->mly_busycmds[slot] = NULL;
978 worked = 1;
979 } else {
980 mly_printf(sc, "got AM completion for nonbusy slot %u\n", slot);
981 }
1007 mc = &sc->mly_command[slot - MLY_SLOT_START];
1008 mc->mc_status = sp->status.status;
1009 mc->mc_sense = sp->status.sense_length;
1010 mc->mc_resid = sp->status.residue;
1011 mly_remove_busy(mc);
1012 mc->mc_flags &= ~MLY_CMD_BUSY;
1013 mly_enqueue_complete(mc);
1014 worked = 1;
982 } else {
983 /* slot 0xffff may mean "extremely bogus command" */
1015 } else {
1016 /* slot 0xffff may mean "extremely bogus command" */
984 mly_printf(sc, "got AM completion for illegal slot %u at %d\n", slot, sc->mly_mmbox_status_index);
1017 mly_printf(sc, "got AM completion for illegal slot %u at %d\n",
1018 slot, sc->mly_mmbox_status_index);
985 }
986
1019 }
1020
987 /* clear and move to next slot */
1021 /* clear and move to next index */
988 sp->mmbox.flag = 0;
989 sc->mly_mmbox_status_index = (sc->mly_mmbox_status_index + 1) % MLY_MMBOX_STATUS;
990 }
991 /* acknowledge that we have collected status value(s) */
992 MLY_SET_REG(sc, sc->mly_odbr, MLY_AM_STSREADY);
993 }
994
995 splx(s);

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

1014 void (* mc_complete)(struct mly_command *mc);
1015
1016
1017 debug_called(2);
1018
1019 /*
1020 * Spin pulling commands off the completed queue and processing them.
1021 */
1022 sp->mmbox.flag = 0;
1023 sc->mly_mmbox_status_index = (sc->mly_mmbox_status_index + 1) % MLY_MMBOX_STATUS;
1024 }
1025 /* acknowledge that we have collected status value(s) */
1026 MLY_SET_REG(sc, sc->mly_odbr, MLY_AM_STSREADY);
1027 }
1028
1029 splx(s);

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

1048 void (* mc_complete)(struct mly_command *mc);
1049
1050
1051 debug_called(2);
1052
1053 /*
1054 * Spin pulling commands off the completed queue and processing them.
1055 */
1022 while ((mc = mly_dequeue_completed(sc)) != NULL) {
1056 while ((mc = mly_dequeue_complete(sc)) != NULL) {
1023
1024 /*
1025 * Free controller resources, mark command complete.
1026 *
1027 * Note that as soon as we mark the command complete, it may be freed
1028 * out from under us, so we need to save the mc_complete field in
1029 * order to later avoid dereferencing mc. (We would not expect to
1030 * have a polling/sleeping consumer with mc_complete != NULL).
1031 */
1032 mly_unmap_command(mc);
1033 mc_complete = mc->mc_complete;
1057
1058 /*
1059 * Free controller resources, mark command complete.
1060 *
1061 * Note that as soon as we mark the command complete, it may be freed
1062 * out from under us, so we need to save the mc_complete field in
1063 * order to later avoid dereferencing mc. (We would not expect to
1064 * have a polling/sleeping consumer with mc_complete != NULL).
1065 */
1066 mly_unmap_command(mc);
1067 mc_complete = mc->mc_complete;
1034 MLY_CMD_SETSTATE(mc, MLY_CMD_COMPLETE);
1068 mc->mc_flags |= MLY_CMD_COMPLETE;
1035
1036 /*
1037 * Call completion handler or wake up sleeping consumer.
1038 */
1039 if (mc_complete != NULL) {
1040 mc_complete(mc);
1041 } else {
1042 wakeup(mc);

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

1058 * a while just to check up on it. While a filesystem is mounted, or I/O is
1059 * active this isn't really an issue.
1060 */
1061 if (sc->mly_mmbox->mmm_health.status.change_counter != sc->mly_event_change) {
1062 sc->mly_event_change = sc->mly_mmbox->mmm_health.status.change_counter;
1063 debug(1, "event change %d, event status update, %d -> %d", sc->mly_event_change,
1064 sc->mly_event_waiting, sc->mly_mmbox->mmm_health.status.next_event);
1065 sc->mly_event_waiting = sc->mly_mmbox->mmm_health.status.next_event;
1069
1070 /*
1071 * Call completion handler or wake up sleeping consumer.
1072 */
1073 if (mc_complete != NULL) {
1074 mc_complete(mc);
1075 } else {
1076 wakeup(mc);

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

1092 * a while just to check up on it. While a filesystem is mounted, or I/O is
1093 * active this isn't really an issue.
1094 */
1095 if (sc->mly_mmbox->mmm_health.status.change_counter != sc->mly_event_change) {
1096 sc->mly_event_change = sc->mly_mmbox->mmm_health.status.change_counter;
1097 debug(1, "event change %d, event status update, %d -> %d", sc->mly_event_change,
1098 sc->mly_event_waiting, sc->mly_mmbox->mmm_health.status.next_event);
1099 sc->mly_event_waiting = sc->mly_mmbox->mmm_health.status.next_event;
1100
1101 /* wake up anyone that might be interested in this */
1102 wakeup(&sc->mly_event_change);
1066 }
1067 if (sc->mly_event_counter != sc->mly_event_waiting)
1068 mly_fetch_event(sc);
1069}
1070
1071/********************************************************************************
1072 ********************************************************************************
1073 Command Buffer Management
1074 ********************************************************************************
1075 ********************************************************************************/
1076
1077/********************************************************************************
1103 }
1104 if (sc->mly_event_counter != sc->mly_event_waiting)
1105 mly_fetch_event(sc);
1106}
1107
1108/********************************************************************************
1109 ********************************************************************************
1110 Command Buffer Management
1111 ********************************************************************************
1112 ********************************************************************************/
1113
1114/********************************************************************************
1078 * Give a command a slot in our lookup table, so that we can recover it when
1079 * the controller returns the slot number.
1080 *
1081 * Slots are freed in mly_done().
1082 */
1083static int
1084mly_get_slot(struct mly_command *mc)
1085{
1086 struct mly_softc *sc = mc->mc_sc;
1087 u_int16_t slot;
1088 int tries;
1089
1090 debug_called(3);
1091
1092 if (mc->mc_flags & MLY_CMD_SLOTTED)
1093 return(0);
1094
1095 /*
1096 * Optimisation for the controller-busy case - check to see whether
1097 * we are already over the limit and stop immediately.
1098 */
1099 if (sc->mly_busy_count >= sc->mly_max_commands)
1100 return(EBUSY);
1101
1102 /*
1103 * Scan forward from the last slot that we assigned looking for a free
1104 * slot. Don't scan more than the maximum number of commands that we
1105 * support (we should never reach the limit here due to the optimisation
1106 * above)
1107 */
1108 slot = sc->mly_last_slot;
1109 for (tries = sc->mly_max_commands; tries > 0; tries--) {
1110 if (sc->mly_busycmds[slot] == NULL) {
1111 sc->mly_busycmds[slot] = mc;
1112 mc->mc_slot = slot;
1113 mc->mc_packet->generic.command_id = slot;
1114 mc->mc_flags |= MLY_CMD_SLOTTED;
1115 sc->mly_last_slot = slot;
1116 return(0);
1117 }
1118 slot++;
1119 if (slot >= MLY_SLOT_MAX)
1120 slot = MLY_SLOT_START;
1121 }
1122 return(EBUSY);
1123}
1124
1125/********************************************************************************
1126 * Allocate a command.
1127 */
1128int
1129mly_alloc_command(struct mly_softc *sc, struct mly_command **mcp)
1130{
1131 struct mly_command *mc;
1132
1133 debug_called(3);
1134
1115 * Allocate a command.
1116 */
1117int
1118mly_alloc_command(struct mly_softc *sc, struct mly_command **mcp)
1119{
1120 struct mly_command *mc;
1121
1122 debug_called(3);
1123
1135 if ((mc = mly_dequeue_free(sc)) == NULL) {
1136 mly_alloc_command_cluster(sc);
1137 mc = mly_dequeue_free(sc);
1138 }
1139 if (mc != NULL)
1140 TAILQ_REMOVE(&sc->mly_freecmds, mc, mc_link);
1141
1142 if (mc == NULL)
1124 if ((mc = mly_dequeue_free(sc)) == NULL)
1143 return(ENOMEM);
1144
1125 return(ENOMEM);
1126
1145 MLY_CMD_SETSTATE(mc, MLY_CMD_SETUP);
1146 *mcp = mc;
1147 return(0);
1148}
1149
1150/********************************************************************************
1151 * Release a command back to the freelist.
1152 */
1153void
1154mly_release_command(struct mly_command *mc)
1155{
1156 debug_called(3);
1157
1158 /*
1159 * Fill in parts of the command that may cause confusion if
1160 * a consumer doesn't when we are later allocated.
1161 */
1127 *mcp = mc;
1128 return(0);
1129}
1130
1131/********************************************************************************
1132 * Release a command back to the freelist.
1133 */
1134void
1135mly_release_command(struct mly_command *mc)
1136{
1137 debug_called(3);
1138
1139 /*
1140 * Fill in parts of the command that may cause confusion if
1141 * a consumer doesn't when we are later allocated.
1142 */
1162 MLY_CMD_SETSTATE(mc, MLY_CMD_FREE);
1163 mc->mc_data = NULL;
1164 mc->mc_flags = 0;
1165 mc->mc_complete = NULL;
1166 mc->mc_private = NULL;
1167
1168 /*
1169 * By default, we set up to overwrite the command packet with
1170 * sense information.
1171 */
1172 mc->mc_packet->generic.sense_buffer_address = mc->mc_packetphys;
1173 mc->mc_packet->generic.maximum_sense_size = sizeof(union mly_command_packet);
1174
1175 mly_enqueue_free(mc);
1176}
1177
1178/********************************************************************************
1143 mc->mc_data = NULL;
1144 mc->mc_flags = 0;
1145 mc->mc_complete = NULL;
1146 mc->mc_private = NULL;
1147
1148 /*
1149 * By default, we set up to overwrite the command packet with
1150 * sense information.
1151 */
1152 mc->mc_packet->generic.sense_buffer_address = mc->mc_packetphys;
1153 mc->mc_packet->generic.maximum_sense_size = sizeof(union mly_command_packet);
1154
1155 mly_enqueue_free(mc);
1156}
1157
1158/********************************************************************************
1179 * Map helper for command cluster allocation.
1180 *
1181 * Note that there are never more command packets in a cluster than will fit in
1182 * a page, so there is no need to look at anything other than the base of the
1183 * allocation (which will be page-aligned).
1159 * Map helper for command allocation.
1184 */
1185static void
1160 */
1161static void
1186mly_alloc_command_cluster_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1162mly_alloc_commands_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1187{
1163{
1188 struct mly_command_cluster *mcc = (struct mly_command_cluster *)arg;
1164 struct mly_softc *sc = (struct mly_softc *)arg
1189
1190 debug_called(2);
1191
1165
1166 debug_called(2);
1167
1192 mcc->mcc_packetphys = segs[0].ds_addr;
1168 sc->mly_packetphys = segs[0].ds_addr;
1193}
1194
1195/********************************************************************************
1169}
1170
1171/********************************************************************************
1196 * Allocate and initialise a cluster of commands.
1172 * Allocate and initialise command and packet structures.
1197 */
1173 */
1198static void
1199mly_alloc_command_cluster(struct mly_softc *sc)
1174static int
1175mly_alloc_commands(struct mly_softc *sc)
1200{
1176{
1201 struct mly_command_cluster *mcc;
1202 struct mly_command *mc;
1203 int i;
1204
1177 struct mly_command *mc;
1178 int i;
1179
1205 debug_called(1);
1180 /*
1181 * Allocate enough space for all the command packets in one chunk and
1182 * map them permanently into controller-visible space.
1183 */
1184 if (bus_dmamem_alloc(sc->mly_packet_dmat, (void **)&sc->mly_packet,
1185 BUS_DMA_NOWAIT, &sc->mly_packetmap)) {
1186 return(ENOMEM);
1187 }
1188 bus_dmamap_load(sc->mly_packet_dmat, sc->mly_packetmap, sc->mly_packet,
1189 MLY_MAXCOMMANDS * sizeof(union mly_command_packet),
1190 mly_alloc_commands_map, sc, 0);
1206
1191
1207 mcc = malloc(sizeof(struct mly_command_cluster), M_DEVBUF, M_NOWAIT);
1208 if (mcc != NULL) {
1209
1210 /*
1211 * Allocate enough space for all the command packets for this cluster and
1212 * map them permanently into controller-visible space.
1213 */
1214 if (bus_dmamem_alloc(sc->mly_packet_dmat, (void **)&mcc->mcc_packet,
1215 BUS_DMA_NOWAIT, &mcc->mcc_packetmap)) {
1216 free(mcc, M_DEVBUF);
1217 return;
1218 }
1219 bus_dmamap_load(sc->mly_packet_dmat, mcc->mcc_packetmap, mcc->mcc_packet,
1220 MLY_CMD_CLUSTERCOUNT * sizeof(union mly_command_packet),
1221 mly_alloc_command_cluster_map, mcc, 0);
1222
1223 mly_enqueue_cluster(sc, mcc);
1224 for (i = 0; i < MLY_CMD_CLUSTERCOUNT; i++) {
1225 mc = &mcc->mcc_command[i];
1226 bzero(mc, sizeof(*mc));
1227 mc->mc_sc = sc;
1228 mc->mc_packet = mcc->mcc_packet + i;
1229 mc->mc_packetphys = mcc->mcc_packetphys + (i * sizeof(union mly_command_packet));
1230 if (!bus_dmamap_create(sc->mly_buffer_dmat, 0, &mc->mc_datamap))
1231 mly_release_command(mc);
1232 }
1192 for (i = 0; i < MLY_MAXCOMMANDS; i++) {
1193 mc = &sc->mly_command[i];
1194 bzero(mc, sizeof(*mc));
1195 mc->mc_sc = sc;
1196 mc->mc_slot = MLY_SLOT_START + i;
1197 mc->mc_packet = sc->mly_packet + i;
1198 mc->mc_packetphys = sc->mly_packetphys + (i * sizeof(union mly_command_packet));
1199 if (!bus_dmamap_create(sc->mly_buffer_dmat, 0, &mc->mc_datamap))
1200 mly_release_command(mc);
1233 }
1201 }
1202 return(0);
1234}
1235
1236/********************************************************************************
1203}
1204
1205/********************************************************************************
1237 * Command-mapping helper function - populate this command slot's s/g table
1238 * with the s/g entries for this command.
1206 * Command-mapping helper function - populate this command's s/g table
1207 * with the s/g entries for its data.
1239 */
1240static void
1241mly_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1242{
1243 struct mly_command *mc = (struct mly_command *)arg;
1244 struct mly_softc *sc = mc->mc_sc;
1245 struct mly_command_generic *gen = &(mc->mc_packet->generic);
1246 struct mly_sg_entry *sg;
1247 int i, tabofs;
1248
1249 debug_called(3);
1250
1251 /* can we use the transfer structure directly? */
1252 if (nseg <= 2) {
1253 sg = &gen->transfer.direct.sg[0];
1254 gen->command_control.extended_sg_table = 0;
1255 } else {
1208 */
1209static void
1210mly_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1211{
1212 struct mly_command *mc = (struct mly_command *)arg;
1213 struct mly_softc *sc = mc->mc_sc;
1214 struct mly_command_generic *gen = &(mc->mc_packet->generic);
1215 struct mly_sg_entry *sg;
1216 int i, tabofs;
1217
1218 debug_called(3);
1219
1220 /* can we use the transfer structure directly? */
1221 if (nseg <= 2) {
1222 sg = &gen->transfer.direct.sg[0];
1223 gen->command_control.extended_sg_table = 0;
1224 } else {
1256 tabofs = (mc->mc_slot * MLY_MAXSGENTRIES);
1225 tabofs = ((mc->mc_slot - MLY_SLOT_START) * MLY_MAXSGENTRIES);
1257 sg = sc->mly_sg_table + tabofs;
1258 gen->transfer.indirect.entries[0] = nseg;
1259 gen->transfer.indirect.table_physaddr[0] = sc->mly_sg_busaddr + (tabofs * sizeof(struct mly_sg_entry));
1260 gen->command_control.extended_sg_table = 1;
1261 }
1262
1263 /* copy the s/g table */
1264 for (i = 0; i < nseg; i++) {

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

1515 */
1516static void
1517mly_print_command(struct mly_command *mc)
1518{
1519 struct mly_softc *sc = mc->mc_sc;
1520
1521 mly_printf(sc, "COMMAND @ %p\n", mc);
1522 mly_printf(sc, " slot %d\n", mc->mc_slot);
1226 sg = sc->mly_sg_table + tabofs;
1227 gen->transfer.indirect.entries[0] = nseg;
1228 gen->transfer.indirect.table_physaddr[0] = sc->mly_sg_busaddr + (tabofs * sizeof(struct mly_sg_entry));
1229 gen->command_control.extended_sg_table = 1;
1230 }
1231
1232 /* copy the s/g table */
1233 for (i = 0; i < nseg; i++) {

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

1484 */
1485static void
1486mly_print_command(struct mly_command *mc)
1487{
1488 struct mly_softc *sc = mc->mc_sc;
1489
1490 mly_printf(sc, "COMMAND @ %p\n", mc);
1491 mly_printf(sc, " slot %d\n", mc->mc_slot);
1523 mly_printf(sc, " state %d\n", MLY_CMD_STATE(mc));
1524 mly_printf(sc, " status 0x%x\n", mc->mc_status);
1525 mly_printf(sc, " sense len %d\n", mc->mc_sense);
1526 mly_printf(sc, " resid %d\n", mc->mc_resid);
1527 mly_printf(sc, " packet %p/0x%llx\n", mc->mc_packet, mc->mc_packetphys);
1528 if (mc->mc_packet != NULL)
1529 mly_print_packet(mc);
1530 mly_printf(sc, " data %p/%d\n", mc->mc_data, mc->mc_length);
1492 mly_printf(sc, " status 0x%x\n", mc->mc_status);
1493 mly_printf(sc, " sense len %d\n", mc->mc_sense);
1494 mly_printf(sc, " resid %d\n", mc->mc_resid);
1495 mly_printf(sc, " packet %p/0x%llx\n", mc->mc_packet, mc->mc_packetphys);
1496 if (mc->mc_packet != NULL)
1497 mly_print_packet(mc);
1498 mly_printf(sc, " data %p/%d\n", mc->mc_data, mc->mc_length);
1531 mly_printf(sc, " flags %b\n", mc->mc_flags, "\20\11slotted\12mapped\13priority\14datain\15dataout\n");
1499 mly_printf(sc, " flags %b\n", mc->mc_flags, "\20\1busy\2complete\3slotted\4mapped\5datain\6dataout\n");
1532 mly_printf(sc, " complete %p\n", mc->mc_complete);
1533 mly_printf(sc, " private %p\n", mc->mc_private);
1534}
1535
1536/********************************************************************************
1537 * Print a command packet
1538 */
1539static void

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

1701 */
1702static void
1703mly_panic(struct mly_softc *sc, char *reason)
1704{
1705 mly_printstate(sc);
1706 panic(reason);
1707}
1708#endif
1500 mly_printf(sc, " complete %p\n", mc->mc_complete);
1501 mly_printf(sc, " private %p\n", mc->mc_private);
1502}
1503
1504/********************************************************************************
1505 * Print a command packet
1506 */
1507static void

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

1669 */
1670static void
1671mly_panic(struct mly_softc *sc, char *reason)
1672{
1673 mly_printstate(sc);
1674 panic(reason);
1675}
1676#endif
1677
1678/********************************************************************************
1679 * Print queue statistics, callable from DDB.
1680 */
1681void
1682mly_print_controller(int controller)
1683{
1684 struct mly_softc *sc;
1685
1686 if ((sc = devclass_get_softc(devclass_find("mly"), controller)) == NULL) {
1687 printf("mly: controller %d invalid\n", controller);
1688 } else {
1689 device_printf(sc->mly_dev, "queue curr max\n");
1690 device_printf(sc->mly_dev, "free %04d/%04d\n",
1691 sc->mly_qstat[MLYQ_FREE].q_length, sc->mly_qstat[MLYQ_FREE].q_max);
1692 device_printf(sc->mly_dev, "ready %04d/%04d\n",
1693 sc->mly_qstat[MLYQ_READY].q_length, sc->mly_qstat[MLYQ_READY].q_max);
1694 device_printf(sc->mly_dev, "busy %04d/%04d\n",
1695 sc->mly_qstat[MLYQ_BUSY].q_length, sc->mly_qstat[MLYQ_BUSY].q_max);
1696 device_printf(sc->mly_dev, "complete %04d/%04d\n",
1697 sc->mly_qstat[MLYQ_COMPLETE].q_length, sc->mly_qstat[MLYQ_COMPLETE].q_max);
1698 }
1699}
1700
1701
1702/********************************************************************************
1703 ********************************************************************************
1704 Control device interface
1705 ********************************************************************************
1706 ********************************************************************************/
1707
1708/********************************************************************************
1709 * Accept an open operation on the control device.
1710 */
1711static int
1712mly_user_open(dev_t dev, int flags, int fmt, struct proc *p)
1713{
1714 int unit = minor(dev);
1715 struct mly_softc *sc = devclass_get_softc(devclass_find("mly"), unit);
1716
1717 sc->mly_state |= MLY_STATE_OPEN;
1718 return(0);
1719}
1720
1721/********************************************************************************
1722 * Accept the last close on the control device.
1723 */
1724static int
1725mly_user_close(dev_t dev, int flags, int fmt, struct proc *p)
1726{
1727 int unit = minor(dev);
1728 struct mly_softc *sc = devclass_get_softc(devclass_find("mly"), unit);
1729
1730 sc->mly_state &= ~MLY_STATE_OPEN;
1731 return (0);
1732}
1733
1734/********************************************************************************
1735 * Handle controller-specific control operations.
1736 */
1737static int
1738mly_user_ioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
1739{
1740 struct mly_softc *sc = (struct mly_softc *)dev->si_drv1;
1741 struct mly_user_command *uc = (struct mly_user_command *)addr;
1742 struct mly_user_health *uh = (struct mly_user_health *)addr;
1743
1744 switch(cmd) {
1745 case MLYIO_COMMAND:
1746 return(mly_user_command(sc, uc));
1747 case MLYIO_HEALTH:
1748 return(mly_user_health(sc, uh));
1749 default:
1750 return(ENOIOCTL);
1751 }
1752}
1753
1754/********************************************************************************
1755 * Execute a command passed in from userspace.
1756 *
1757 * The control structure contains the actual command for the controller, as well
1758 * as the user-space data pointer and data size, and an optional sense buffer
1759 * size/pointer. On completion, the data size is adjusted to the command
1760 * residual, and the sense buffer size to the size of the returned sense data.
1761 *
1762 */
1763static int
1764mly_user_command(struct mly_softc *sc, struct mly_user_command *uc)
1765{
1766 struct mly_command *mc;
1767 int error, s;
1768
1769 /* allocate a command */
1770 if (mly_alloc_command(sc, &mc)) {
1771 error = ENOMEM;
1772 goto out; /* XXX Linux version will wait for a command */
1773 }
1774
1775 /* handle data size/direction */
1776 mc->mc_length = (uc->DataTransferLength >= 0) ? uc->DataTransferLength : -uc->DataTransferLength;
1777 if (mc->mc_length > 0) {
1778 if ((mc->mc_data = malloc(mc->mc_length, M_DEVBUF, M_NOWAIT)) == NULL) {
1779 error = ENOMEM;
1780 goto out;
1781 }
1782 }
1783 if (uc->DataTransferLength > 0) {
1784 mc->mc_flags |= MLY_CMD_DATAIN;
1785 bzero(mc->mc_data, mc->mc_length);
1786 }
1787 if (uc->DataTransferLength < 0) {
1788 mc->mc_flags |= MLY_CMD_DATAOUT;
1789 if ((error = copyin(uc->DataTransferBuffer, mc->mc_data, mc->mc_length)) != 0)
1790 goto out;
1791 }
1792
1793 /* copy the controller command */
1794 bcopy(&uc->CommandMailbox, mc->mc_packet, sizeof(uc->CommandMailbox));
1795
1796 /* clear command completion handler so that we get woken up */
1797 mc->mc_complete = NULL;
1798
1799 /* execute the command */
1800 s = splcam();
1801 mly_requeue_ready(mc);
1802 mly_startio(sc);
1803 while (!(mc->mc_flags & MLY_CMD_COMPLETE))
1804 tsleep(mc, PRIBIO, "mlyioctl", 0);
1805 splx(s);
1806
1807 /* return the data to userspace */
1808 if (uc->DataTransferLength > 0)
1809 if ((error = copyout(mc->mc_data, uc->DataTransferBuffer, mc->mc_length)) != 0)
1810 goto out;
1811
1812 /* return the sense buffer to userspace */
1813 if ((uc->RequestSenseLength > 0) && (mc->mc_sense > 0)) {
1814 if ((error = copyout(mc->mc_packet, uc->RequestSenseBuffer,
1815 min(uc->RequestSenseLength, mc->mc_sense))) != 0)
1816 goto out;
1817 }
1818
1819 /* return command results to userspace (caller will copy out) */
1820 uc->DataTransferLength = mc->mc_resid;
1821 uc->RequestSenseLength = min(uc->RequestSenseLength, mc->mc_sense);
1822 uc->CommandStatus = mc->mc_status;
1823 error = 0;
1824
1825 out:
1826 if (mc->mc_data != NULL)
1827 free(mc->mc_data, M_DEVBUF);
1828 if (mc != NULL)
1829 mly_release_command(mc);
1830 return(error);
1831}
1832
1833/********************************************************************************
1834 * Return health status to userspace. If the health change index in the user
1835 * structure does not match that currently exported by the controller, we
1836 * return the current status immediately. Otherwise, we block until either
1837 * interrupted or new status is delivered.
1838 */
1839static int
1840mly_user_health(struct mly_softc *sc, struct mly_user_health *uh)
1841{
1842 struct mly_health_status mh;
1843 int error, s;
1844
1845 /* fetch the current health status from userspace */
1846 if ((error = copyin(uh->HealthStatusBuffer, &mh, sizeof(mh))) != 0)
1847 return(error);
1848
1849 /* spin waiting for a status update */
1850 s = splcam();
1851 error = EWOULDBLOCK;
1852 while ((error != 0) && (sc->mly_event_change == mh.change_counter))
1853 error = tsleep(&sc->mly_event_change, PRIBIO | PCATCH, "mlyhealth", 0);
1854 splx(s);
1855
1856 /* copy the controller's health status buffer out (there is a race here if it changes again) */
1857 error = copyout(&sc->mly_mmbox->mmm_health.status, uh->HealthStatusBuffer,
1858 sizeof(uh->HealthStatusBuffer));
1859 return(error);
1860}