1 /* $NetBSD: util.c,v 1.4 2002/04/07 20:18:01 ad Exp $ */ 2 3 /*- 4 * Copyright (c) 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /*- 40 * Copyright (c) 1999 Michael Smith 41 * All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 */ 64 65 #ifndef lint 66 #include <sys/cdefs.h> 67 __RCSID("$NetBSD: util.c,v 1.4 2002/04/07 20:18:01 ad Exp $"); 68 #endif /* not lint */ 69 70 #include <sys/types.h> 71 #include <sys/ioctl.h> 72 #include <sys/queue.h> 73 74 #include <dev/ic/mlxreg.h> 75 #include <dev/ic/mlxio.h> 76 77 #include <dev/scsipi/scsipi_all.h> 78 79 #include <stdio.h> 80 #include <stdlib.h> 81 #include <string.h> 82 #include <unistd.h> 83 #include <err.h> 84 85 #include "extern.h" 86 87 int 88 mlx_command(struct mlx_usercommand *mu, int bomb) 89 { 90 int rv; 91 92 if ((rv = ioctl(mlxfd, MLX_COMMAND, mu)) != 0 && bomb) 93 err(EXIT_FAILURE, "cmd 0x%02x failed", 94 mu->mu_command[0]); 95 96 return (rv); 97 } 98 99 void 100 mlx_enquiry(struct mlx_enquiry2 *enq) 101 { 102 struct mlx_usercommand mu; 103 struct mlx_enquiry_old meo; 104 105 memset(&mu, 0, sizeof(mu)); 106 107 mu.mu_datasize = sizeof(*enq); 108 mu.mu_buf = enq; 109 mu.mu_bufptr = 8; 110 mu.mu_bufdir = MU_XFER_IN; 111 mu.mu_command[0] = MLX_CMD_ENQUIRY2; 112 113 mlx_command(&mu, 1); 114 115 /* 116 * If we get back a firmware major of 0, this is (probably) an old 117 * controller, so we need to pull the firmware version from the old 118 * enquiry structure. 119 */ 120 if (enq->me_firmware_id[0] == 0) { 121 memset(&mu, 0, sizeof(mu)); 122 123 mu.mu_datasize = sizeof(meo); 124 mu.mu_buf = &meo; 125 mu.mu_bufptr = 8; 126 mu.mu_bufdir = MU_XFER_IN; 127 mu.mu_command[0] = MLX_CMD_ENQUIRY_OLD; 128 129 mlx_command(&mu, 1); 130 131 enq->me_firmware_id[0] = meo.me_fwmajor; 132 enq->me_firmware_id[1] = meo.me_fwminor; 133 enq->me_firmware_id[2] = 0; 134 enq->me_firmware_id[3] = '0'; 135 } 136 } 137 138 void 139 mlx_configuration(struct mlx_core_cfg *cfg, int wr) 140 { 141 struct mlx_usercommand mu; 142 143 memset(&mu, 0, sizeof(mu)); 144 145 mu.mu_datasize = sizeof(*cfg); 146 mu.mu_buf = cfg; 147 mu.mu_bufptr = 8; 148 mu.mu_bufdir = (wr ? MU_XFER_OUT : MU_XFER_IN); 149 mu.mu_command[0] = (wr ? MLX_CMD_WRITE_CONFIG : MLX_CMD_READ_CONFIG); 150 151 mlx_command(&mu, 1); 152 } 153 154 int 155 mlx_get_device_state(int chan, int targ, struct mlx_phys_drv *pd) 156 { 157 struct mlx_usercommand mu; 158 159 memset(&mu, 0, sizeof(mu)); 160 161 mu.mu_datasize = sizeof(*pd); 162 mu.mu_buf = pd; 163 mu.mu_bufptr = 8; 164 mu.mu_bufdir = MU_XFER_IN; 165 mu.mu_command[0] = MLX_CMD_DEVICE_STATE; 166 mu.mu_command[2] = chan; 167 mu.mu_command[3] = targ; 168 169 return (mlx_command(&mu, 0)); 170 } 171 172 int 173 mlx_scsi_inquiry(int chan, int targ, char **vendor, char **device, 174 char **revision) 175 { 176 struct mlx_usercommand mu; 177 static struct { 178 struct mlx_dcdb dcdb; 179 struct scsipi_inquiry_data inq; 180 } __attribute__ ((__packed__)) dcdb_cmd; 181 struct scsipi_inquiry *inq_cmd; 182 int rv; 183 184 inq_cmd = (struct scsipi_inquiry *)&dcdb_cmd.dcdb.dcdb_cdb[0]; 185 186 memset(&mu, 0, sizeof(mu)); 187 mu.mu_datasize = sizeof(dcdb_cmd); 188 mu.mu_buf = &dcdb_cmd; 189 mu.mu_command[0] = MLX_CMD_DIRECT_CDB; 190 mu.mu_bufdir = MU_XFER_IN | MU_XFER_OUT; 191 192 memset(&dcdb_cmd, 0, sizeof(dcdb_cmd)); 193 dcdb_cmd.dcdb.dcdb_target = (chan << 4) | targ; 194 dcdb_cmd.dcdb.dcdb_flags = MLX_DCDB_DATA_IN | MLX_DCDB_TIMEOUT_10S; 195 dcdb_cmd.dcdb.dcdb_datasize = sizeof(dcdb_cmd.inq); 196 dcdb_cmd.dcdb.dcdb_length = 6; 197 dcdb_cmd.dcdb.dcdb_sense_length = 40; 198 199 inq_cmd->opcode = INQUIRY; 200 inq_cmd->length = sizeof(dcdb_cmd.inq); 201 202 if ((rv = mlx_command(&mu, 0)) == 0) { 203 *vendor = &dcdb_cmd.inq.vendor[0]; 204 *device = &dcdb_cmd.inq.product[0]; 205 *revision = &dcdb_cmd.inq.revision[0]; 206 } 207 208 return (rv); 209 } 210 211 void 212 mlx_print_phys_drv(struct mlx_phys_drv *pd, int chn, int targ, 213 const char *prefix) 214 { 215 char *type, *device, *vendor, *revision; 216 217 switch (pd->pd_flags2 & 0x03) { 218 case MLX_PHYS_DRV_DISK: 219 type = "disk"; 220 break; 221 222 case MLX_PHYS_DRV_SEQUENTIAL: 223 type = "tape"; 224 break; 225 226 case MLX_PHYS_DRV_CDROM: 227 type= "cdrom"; 228 break; 229 230 case MLX_PHYS_DRV_OTHER: 231 default: 232 type = "unknown"; 233 break; 234 } 235 236 printf("%s%s%02d%02d ", prefix, type, chn, targ); 237 238 switch (pd->pd_status) { 239 case MLX_PHYS_DRV_DEAD: 240 printf(" (dead) "); 241 break; 242 243 case MLX_PHYS_DRV_WRONLY: 244 printf(" (write-only) "); 245 break; 246 247 case MLX_PHYS_DRV_ONLINE: 248 printf(" (online) "); 249 break; 250 251 case MLX_PHYS_DRV_STANDBY: 252 printf(" (standby) "); 253 break; 254 255 default: 256 printf(" (0x%02x) ", pd->pd_status); 257 break; 258 } 259 260 printf("\n"); 261 if (verbosity == 0) 262 return; 263 264 printf("%s ", prefix); 265 if (!mlx_scsi_inquiry(chn, targ, &vendor, &device, &revision)) 266 printf("'%8.8s' '%16.16s' '%4.4s'", vendor, device, revision); 267 else 268 printf("<IDENTIFY FAILED>"); 269 270 printf(" %dMB ", pd->pd_config_size / 2048); 271 272 if ((pd->pd_flags2 & MLX_PHYS_DRV_FAST20) != 0) 273 printf(" ultra"); 274 else if ((pd->pd_flags2 & MLX_PHYS_DRV_FAST) != 0) 275 printf(" fast"); 276 277 if ((pd->pd_flags2 & MLX_PHYS_DRV_WIDE) != 0) 278 printf(" wide"); 279 280 if ((pd->pd_flags2 & MLX_PHYS_DRV_SYNC) != 0) 281 printf(" sync"); 282 283 if ((pd->pd_flags2 & MLX_PHYS_DRV_TAG) != 0) 284 printf(" tag-enabled"); 285 286 printf("\n"); 287 } 288