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} |
|