interface.c revision 59138
122347Spst/*- 222347Spst * Copyright (c) 1999 Michael Smith 329964Sache * All rights reserved. 492906Smarkm * 592906Smarkm * Redistribution and use in source and binary forms, with or without 622347Spst * modification, are permitted provided that the following conditions 722347Spst * are met: 822347Spst * 1. Redistributions of source code must retain the above copyright 922347Spst * notice, this list of conditions and the following disclaimer. 1022347Spst * 2. Redistributions in binary form must reproduce the above copyright 1192906Smarkm * notice, this list of conditions and the following disclaimer in the 1292906Smarkm * documentation and/or other materials provided with the distribution. 1359118Skris * 1459118Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1559118Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1659118Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1729964Sache * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1829964Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1929964Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2022347Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2122347Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2222347Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2322347Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2422347Spst * SUCH DAMAGE. 2522347Spst * 2622347Spst * $FreeBSD: cvs2svn/branches/MSMITH/usr.sbin/mlxcontrol/interface.c 59138 2000-04-11 03:01:45Z msmith $ 2722347Spst */ 2822347Spst 2922347Spst#include <fcntl.h> 3022347Spst#include <stdio.h> 3122347Spst#include <stdlib.h> 3229964Sache#include <unistd.h> 3322347Spst#include <string.h> 3422347Spst#include <cam/scsi/scsi_all.h> 3522347Spst 3622347Spst#if 0 3722347Spst#include <sys/mlxio.h> 3822347Spst#include <sys/mlxreg.h> 3922347Spst#else 4022347Spst#include "../sys/dev/mlx/mlxio.h" 4122347Spst#include "../sys/dev/mlx/mlxreg.h" 4222347Spst#endif 4322347Spst 4429964Sache#include "mlxcontrol.h" 4522347Spst 4622347Spst/******************************************************************************** 4722347Spst * Iterate over all mlx devices, call (func) with each ones' path and (arg) 4822347Spst */ 4922347Spstvoid 5022347Spstmlx_foreach(void (*func)(int unit, void *arg), void *arg) 5122347Spst{ 5222347Spst int i, fd; 5322347Spst 5422347Spst /* limit total count for sanity */ 5522347Spst for (i = 0; i < 64; i++) { 5622347Spst /* verify we can open it */ 5722347Spst if ((fd = open(ctrlrpath(i), 0)) >= 0) 5822347Spst close(fd); 5922347Spst /* if we can, do */ 6022347Spst if (fd >= 0) { 6122347Spst func(i, arg); 6222347Spst } 6322347Spst } 6422347Spst} 6522347Spst 6622347Spst/******************************************************************************** 6722347Spst * Open the controller (unit) and give the fd to (func) along with (arg) 6822347Spst */ 6922347Spstvoid 7022347Spstmlx_perform(int unit, void (*func)(int fd, void *arg), void *arg) 7122347Spst{ 7292906Smarkm int fd; 7322347Spst 7422347Spst if ((fd = open(ctrlrpath(unit), 0)) >= 0) { 7522347Spst func(fd, arg); 7622347Spst close(fd); 7722347Spst } 7822347Spst} 7922347Spst 8022347Spst/******************************************************************************** 8122347Spst * Iterate over all mlxd devices, call (func) with each ones' path and (arg) 8222347Spst */ 8322347Spstvoid 8422347Spstmlxd_foreach_ctrlr(int unit, void *arg) 8592906Smarkm{ 8622347Spst struct mlxd_foreach_action *ma = (struct mlxd_foreach_action *)arg; 8722347Spst int i, fd; 8892906Smarkm 8992906Smarkm /* Get the device */ 9092906Smarkm if ((fd = open(ctrlrpath(unit), 0)) < 0) 9192906Smarkm return; 9292906Smarkm 9392906Smarkm for (i = -1; ;) { 9492906Smarkm /* Get the unit number of the next child device */ 9522347Spst if (ioctl(fd, MLX_NEXT_CHILD, &i) < 0) 9622347Spst return; 9722347Spst 9822347Spst /* check that we can open this unit */ 9922347Spst if ((fd = open(drivepath(i), 0)) >= 0) 10022347Spst close(fd); 10122347Spst /* if we can, do */ 10222347Spst if (fd >= 0) { 10322347Spst ma->func(i, ma->arg); 10422347Spst } 10522347Spst } 10622347Spst} 10722347Spst 10822347Spstvoid 10992906Smarkmmlxd_foreach(void (*func)(int unit, void *arg), void *arg) 11092906Smarkm{ 11192906Smarkm struct mlxd_foreach_action ma; 11292906Smarkm 11322347Spst ma.func = func; 11492906Smarkm ma.arg = arg; 11592906Smarkm mlx_foreach(mlxd_foreach_ctrlr, &ma); 11692906Smarkm} 11792906Smarkm 11822347Spst/******************************************************************************** 11922347Spst * Find the controller that manages the drive (unit), return controller number 12022347Spst * and system drive number on that controller. 12122347Spst */ 12222347Spststatic struct 12392906Smarkm{ 12492906Smarkm int unit; 12592906Smarkm int ctrlr; 12692906Smarkm int sysdrive; 12722347Spst} mlxd_find_ctrlr_param; 12822347Spst 12922347Spststatic void 13022347Spstmlxd_find_ctrlr_search(int unit, void *arg) 13122347Spst{ 13292906Smarkm int i, fd; 13392906Smarkm 13492906Smarkm /* Get the device */ 13592906Smarkm if ((fd = open(ctrlrpath(unit), 0)) >= 0) { 13622347Spst for (i = -1; ;) { 13722347Spst /* Get the unit number of the next child device */ 13829964Sache if (ioctl(fd, MLX_NEXT_CHILD, &i) < 0) 13922347Spst break; 14022347Spst 14122347Spst /* is this child the unit we want? */ 14222347Spst if (i == mlxd_find_ctrlr_param.unit) { 14322347Spst mlxd_find_ctrlr_param.ctrlr = unit; 14422347Spst if (ioctl(fd, MLX_GET_SYSDRIVE, &i) == 0) 14522347Spst mlxd_find_ctrlr_param.sysdrive = i; 14622347Spst } 14722347Spst } 14829964Sache close(fd); 14992906Smarkm } 15022347Spst} 15122347Spst 15292906Smarkmint 15322347Spstmlxd_find_ctrlr(int unit, int *ctrlr, int *sysdrive) 15422347Spst{ 15522347Spst mlxd_find_ctrlr_param.unit = unit; 15692906Smarkm mlxd_find_ctrlr_param.ctrlr = -1; 15792906Smarkm mlxd_find_ctrlr_param.sysdrive = -1; 15822347Spst 15992906Smarkm mlx_foreach(mlxd_find_ctrlr_search, NULL); 16022347Spst if ((mlxd_find_ctrlr_param.ctrlr != -1) && (mlxd_find_ctrlr_param.sysdrive != -1)) { 16122347Spst *ctrlr = mlxd_find_ctrlr_param.ctrlr; 16222347Spst *sysdrive = mlxd_find_ctrlr_param.sysdrive; 16322347Spst return(0); 16422347Spst } 16522347Spst return(1); 16622347Spst} 16792906Smarkm 16822347Spst 16922347Spst/******************************************************************************** 17022347Spst * Send a command to the controller on (fd) 17122347Spst */ 17222347Spst 17322347Spstvoid 17422347Spstmlx_command(int fd, void *arg) 17522347Spst{ 17622347Spst struct mlx_usercommand *cmd = (struct mlx_usercommand *)arg; 17722347Spst int error; 17822347Spst 17959118Skris error = ioctl(fd, MLX_COMMAND, cmd); 18022347Spst if (error != 0) 18159118Skris cmd->mu_error = error; 18222347Spst} 18322347Spst 18422347Spst/******************************************************************************** 18529964Sache * Perform an ENQUIRY2 command and return information related to the controller 18692906Smarkm * (unit) 18722347Spst */ 18822347Spstint 18992906Smarkmmlx_enquiry(int unit, struct mlx_enquiry2 *enq) 19022347Spst{ 19122347Spst struct mlx_usercommand cmd; 19222347Spst 19322347Spst /* build the command */ 19422347Spst cmd.mu_datasize = sizeof(*enq); 19522347Spst cmd.mu_buf = enq; 19622347Spst cmd.mu_bufptr = 8; 19722347Spst cmd.mu_command[0] = MLX_CMD_ENQUIRY2; 19822347Spst 19922347Spst /* hand it off for processing */ 20022347Spst mlx_perform(unit, mlx_command, (void *)&cmd); 20122347Spst 20222347Spst return(cmd.mu_status != 0); 20322347Spst} 20422347Spst 20522347Spst 20622347Spst/******************************************************************************** 20722347Spst * Perform a READ CONFIGURATION command and return information related to the controller 20822347Spst * (unit) 20922347Spst */ 21022347Spstint 21122347Spstmlx_read_configuration(int unit, struct mlx_core_cfg *cfg) 21222347Spst{ 21392906Smarkm struct mlx_usercommand cmd; 21422347Spst 21522347Spst /* build the command */ 21622347Spst cmd.mu_datasize = sizeof(*cfg); 21722347Spst cmd.mu_buf = cfg; 21822347Spst cmd.mu_bufptr = 8; 21922347Spst cmd.mu_command[0] = MLX_CMD_READ_CONFIG; 22022347Spst 22122347Spst /* hand it off for processing */ 222 mlx_perform(unit, mlx_command, (void *)&cmd); 223 224 return(cmd.mu_status != 0); 225} 226 227/******************************************************************************** 228 * Perform a SCSI INQUIRY command and return pointers to the relevant data. 229 */ 230int 231mlx_scsi_inquiry(int unit, int channel, int target, char **vendor, char **device, char **revision) 232{ 233 struct mlx_usercommand cmd; 234 static struct { 235 struct mlx_dcdb dcdb; 236 union { 237 struct scsi_inquiry_data inq; 238 u_int8_t pad[SHORT_INQUIRY_LENGTH]; 239 } d; 240 } __attribute__ ((packed)) dcdb_cmd; 241 struct scsi_inquiry *inq_cmd = (struct scsi_inquiry *)&dcdb_cmd.dcdb.dcdb_cdb[0]; 242 243 /* build the command */ 244 cmd.mu_datasize = sizeof(dcdb_cmd); 245 cmd.mu_buf = &dcdb_cmd; 246 cmd.mu_command[0] = MLX_CMD_DIRECT_CDB; 247 248 /* build the DCDB */ 249 bzero(&dcdb_cmd, sizeof(dcdb_cmd)); 250 dcdb_cmd.dcdb.dcdb_channel = channel; 251 dcdb_cmd.dcdb.dcdb_target = target; 252 dcdb_cmd.dcdb.dcdb_flags = MLX_DCDB_DATA_IN | MLX_DCDB_TIMEOUT_10S; 253 dcdb_cmd.dcdb.dcdb_datasize = SHORT_INQUIRY_LENGTH; 254 dcdb_cmd.dcdb.dcdb_cdb_length = 6; 255 dcdb_cmd.dcdb.dcdb_sense_length = SSD_FULL_SIZE; 256 257 /* build the cdb */ 258 inq_cmd->opcode = INQUIRY; 259 inq_cmd->length = SHORT_INQUIRY_LENGTH; 260 261 /* hand it off for processing */ 262 mlx_perform(unit, mlx_command, &cmd); 263 264 if (cmd.mu_status == 0) { 265 *vendor = &dcdb_cmd.d.inq.vendor[0]; 266 *device = &dcdb_cmd.d.inq.product[0]; 267 *revision = &dcdb_cmd.d.inq.revision[0]; 268 } 269 return(cmd.mu_status); 270} 271 272/******************************************************************************** 273 * Perform a GET DEVICE STATE command and return pointers to the relevant data. 274 */ 275int 276mlx_get_device_state(int unit, int channel, int target, struct mlx_phys_drv *drv) 277{ 278 struct mlx_usercommand cmd; 279 280 /* build the command */ 281 cmd.mu_datasize = sizeof(*drv); 282 cmd.mu_buf = drv; 283 cmd.mu_bufptr = 8; 284 cmd.mu_command[0] = MLX_CMD_DEVICE_STATE; 285 cmd.mu_command[2] = channel; 286 cmd.mu_command[3] = target; 287 288 /* hand it off for processing */ 289 mlx_perform(unit, mlx_command, (void *)&cmd); 290 291 return(cmd.mu_status != 0); 292} 293