1 /* $NetBSD: util.c,v 1.1 2001/02/04 17:30:37 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.1 2001/02/04 17:30:37 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 <unistd.h> 82 #include <err.h> 83 84 #include "extern.h" 85 86 int 87 mlx_command(struct mlx_usercommand *mu, int bomb) 88 { 89 int rv; 90 91 if ((rv = ioctl(mlxfd, MLX_COMMAND, mu)) != 0 && bomb) 92 err(EXIT_FAILURE, "cmd 0x%02x failed", 93 mu->mu_command[0]); 94 95 return (rv); 96 } 97 98 void 99 mlx_enquiry(struct mlx_enquiry2 *enq) 100 { 101 struct mlx_usercommand mu; 102 struct mlx_enquiry_old meo; 103 104 memset(&mu, 0, sizeof(mu)); 105 106 mu.mu_datasize = sizeof(*enq); 107 mu.mu_buf = enq; 108 mu.mu_bufptr = 8; 109 mu.mu_bufdir = MU_XFER_IN; 110 mu.mu_command[0] = MLX_CMD_ENQUIRY2; 111 112 mlx_command(&mu, 1); 113 114 /* 115 * If we get back a firmware major of 0, this is (probably) an old 116 * controller, so we need to pull the firmware version from the old 117 * enquiry structure. 118 */ 119 if (enq->me_firmware_id[0] == 0) { 120 memset(&mu, 0, sizeof(mu)); 121 122 mu.mu_datasize = sizeof(meo); 123 mu.mu_buf = &meo; 124 mu.mu_bufptr = 8; 125 mu.mu_bufdir = MU_XFER_IN; 126 mu.mu_command[0] = MLX_CMD_ENQUIRY_OLD; 127 128 mlx_command(&mu, 1); 129 130 enq->me_firmware_id[0] = meo.me_fwmajor; 131 enq->me_firmware_id[1] = meo.me_fwminor; 132 enq->me_firmware_id[2] = '0'; 133 enq->me_firmware_id[3] = 0; 134 } 135 } 136 137 void 138 mlx_configuration(struct mlx_core_cfg *cfg, int wr) 139 { 140 struct mlx_usercommand mu; 141 142 memset(&mu, 0, sizeof(mu)); 143 144 mu.mu_datasize = sizeof(*cfg); 145 mu.mu_buf = cfg; 146 mu.mu_bufptr = 8; 147 mu.mu_bufdir = (wr ? MU_XFER_OUT : MU_XFER_IN); 148 mu.mu_command[0] = (wr ? MLX_CMD_WRITE_CONFIG : MLX_CMD_READ_CONFIG); 149 150 mlx_command(&mu, 1); 151 } 152 153 int 154 mlx_get_device_state(int chan, int targ, struct mlx_phys_drv *pd) 155 { 156 struct mlx_usercommand mu; 157 158 memset(&mu, 0, sizeof(mu)); 159 160 mu.mu_datasize = sizeof(*pd); 161 mu.mu_buf = pd; 162 mu.mu_bufptr = 8; 163 mu.mu_bufdir = MU_XFER_IN; 164 mu.mu_command[0] = MLX_CMD_DEVICE_STATE; 165 mu.mu_command[2] = chan; 166 mu.mu_command[3] = targ; 167 168 return (mlx_command(&mu, 0)); 169 } 170 171 int 172 mlx_scsi_inquiry(int chan, int targ, char **vendor, char **device, 173 char **revision) 174 { 175 struct mlx_usercommand mu; 176 static struct { 177 struct mlx_dcdb dcdb; 178 struct scsipi_inquiry_data inq; 179 } __attribute__ ((__packed__)) dcdb_cmd; 180 struct scsipi_inquiry *inq_cmd; 181 int rv; 182 183 inq_cmd = (struct scsipi_inquiry *)&dcdb_cmd.dcdb.dcdb_cdb[0]; 184 185 memset(&mu, 0, sizeof(mu)); 186 mu.mu_datasize = sizeof(dcdb_cmd); 187 mu.mu_buf = &dcdb_cmd; 188 mu.mu_command[0] = MLX_CMD_DIRECT_CDB; 189 mu.mu_bufdir = MU_XFER_IN | MU_XFER_OUT; 190 191 memset(&dcdb_cmd, 0, sizeof(dcdb_cmd)); 192 dcdb_cmd.dcdb.dcdb_target = (chan << 4) | targ; 193 dcdb_cmd.dcdb.dcdb_flags = MLX_DCDB_DATA_IN | MLX_DCDB_TIMEOUT_10S; 194 dcdb_cmd.dcdb.dcdb_datasize = sizeof(dcdb_cmd.inq); 195 dcdb_cmd.dcdb.dcdb_length = 6; 196 dcdb_cmd.dcdb.dcdb_sense_length = 40; 197 198 inq_cmd->opcode = INQUIRY; 199 inq_cmd->length = sizeof(dcdb_cmd.inq); 200 201 if ((rv = mlx_command(&mu, 0)) == 0) { 202 *vendor = &dcdb_cmd.inq.vendor[0]; 203 *device = &dcdb_cmd.inq.product[0]; 204 *revision = &dcdb_cmd.inq.revision[0]; 205 } 206 207 return (rv); 208 } 209 210 void 211 mlx_print_phys_drv(struct mlx_phys_drv *pd, int chn, int targ, 212 const char *prefix) 213 { 214 char *type, *device, *vendor, *revision; 215 216 switch(pd->pd_flags2 & 0x03) { 217 case MLX_PHYS_DRV_DISK: 218 type = "disk"; 219 break; 220 221 case MLX_PHYS_DRV_SEQUENTIAL: 222 type = "tape"; 223 break; 224 225 case MLX_PHYS_DRV_CDROM: 226 type= "cdrom"; 227 break; 228 229 case MLX_PHYS_DRV_OTHER: 230 default: 231 type = "unknown"; 232 break; 233 } 234 235 printf("%s%s%02d%02d ", prefix, type, chn, targ); 236 237 switch(pd->pd_status) { 238 case MLX_PHYS_DRV_DEAD: 239 printf(" (dead) "); 240 break; 241 242 case MLX_PHYS_DRV_WRONLY: 243 printf(" (write-only) "); 244 break; 245 246 case MLX_PHYS_DRV_ONLINE: 247 printf(" (online) "); 248 break; 249 250 case MLX_PHYS_DRV_STANDBY: 251 printf(" (standby) "); 252 break; 253 254 default: 255 printf(" (0x%02x) ", pd->pd_status); 256 break; 257 } 258 259 printf("\n"); 260 if (verbosity == 0) 261 return; 262 263 printf("%s ", prefix); 264 if (!mlx_scsi_inquiry(chn, targ, &vendor, &device, &revision)) 265 printf("'%8.8s' '%16.16s' '%4.4s'", vendor, device, revision); 266 else 267 printf("<IDENTIFY FAILED>"); 268 269 printf(" %dMB ", pd->pd_config_size / 2048); 270 271 if ((pd->pd_flags2 & MLX_PHYS_DRV_FAST20) != 0) 272 printf(" ultra"); 273 else if ((pd->pd_flags2 & MLX_PHYS_DRV_FAST) != 0) 274 printf(" fast"); 275 276 if ((pd->pd_flags2 & MLX_PHYS_DRV_WIDE) != 0) 277 printf(" wide"); 278 279 if ((pd->pd_flags2 & MLX_PHYS_DRV_SYNC) != 0) 280 printf(" sync"); 281 282 if ((pd->pd_flags2 & MLX_PHYS_DRV_TAG) != 0) 283 printf(" tag-enabled"); 284 285 printf("\n"); 286 } 287 288