interface.c revision 59138
1251655Sadrian/*- 2251655Sadrian * Copyright (c) 1999 Michael Smith 3251655Sadrian * All rights reserved. 4251655Sadrian * 5251655Sadrian * Redistribution and use in source and binary forms, with or without 6251655Sadrian * modification, are permitted provided that the following conditions 7251655Sadrian * are met: 8251655Sadrian * 1. Redistributions of source code must retain the above copyright 9251655Sadrian * notice, this list of conditions and the following disclaimer. 10251655Sadrian * 2. Redistributions in binary form must reproduce the above copyright 11251655Sadrian * notice, this list of conditions and the following disclaimer in the 12251655Sadrian * documentation and/or other materials provided with the distribution. 13251655Sadrian * 14251655Sadrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15251655Sadrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16251655Sadrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17251655Sadrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18251655Sadrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19251655Sadrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20251655Sadrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21251655Sadrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22251655Sadrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23251655Sadrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24251655Sadrian * SUCH DAMAGE. 25251655Sadrian * 26251655Sadrian * $FreeBSD: cvs2svn/branches/MSMITH/usr.sbin/mlxcontrol/interface.c 59138 2000-04-11 03:01:45Z msmith $ 27251655Sadrian */ 28251655Sadrian 29251655Sadrian#include <fcntl.h> 30251655Sadrian#include <stdio.h> 31251655Sadrian#include <stdlib.h> 32251655Sadrian#include <unistd.h> 33251655Sadrian#include <string.h> 34251655Sadrian#include <cam/scsi/scsi_all.h> 35251655Sadrian 36251655Sadrian#if 0 37251655Sadrian#include <sys/mlxio.h> 38251655Sadrian#include <sys/mlxreg.h> 39251655Sadrian#else 40251655Sadrian#include "../sys/dev/mlx/mlxio.h" 41251655Sadrian#include "../sys/dev/mlx/mlxreg.h" 42251655Sadrian#endif 43251655Sadrian 44251655Sadrian#include "mlxcontrol.h" 45251655Sadrian 46251655Sadrian/******************************************************************************** 47251655Sadrian * Iterate over all mlx devices, call (func) with each ones' path and (arg) 48251655Sadrian */ 49251655Sadrianvoid 50251655Sadrianmlx_foreach(void (*func)(int unit, void *arg), void *arg) 51251655Sadrian{ 52251655Sadrian int i, fd; 53251655Sadrian 54251655Sadrian /* limit total count for sanity */ 55251655Sadrian for (i = 0; i < 64; i++) { 56251655Sadrian /* verify we can open it */ 57251655Sadrian if ((fd = open(ctrlrpath(i), 0)) >= 0) 58251655Sadrian close(fd); 59251655Sadrian /* if we can, do */ 60251655Sadrian if (fd >= 0) { 61251655Sadrian func(i, arg); 62251655Sadrian } 63251655Sadrian } 64251655Sadrian} 65251655Sadrian 66251655Sadrian/******************************************************************************** 67251655Sadrian * Open the controller (unit) and give the fd to (func) along with (arg) 68251655Sadrian */ 69251655Sadrianvoid 70251655Sadrianmlx_perform(int unit, void (*func)(int fd, void *arg), void *arg) 71251655Sadrian{ 72251655Sadrian int fd; 73251655Sadrian 74251655Sadrian if ((fd = open(ctrlrpath(unit), 0)) >= 0) { 75251655Sadrian func(fd, arg); 76251655Sadrian close(fd); 77251655Sadrian } 78251655Sadrian} 79251655Sadrian 80251655Sadrian/******************************************************************************** 81251655Sadrian * Iterate over all mlxd devices, call (func) with each ones' path and (arg) 82251655Sadrian */ 83251655Sadrianvoid 84251655Sadrianmlxd_foreach_ctrlr(int unit, void *arg) 85251655Sadrian{ 86251655Sadrian struct mlxd_foreach_action *ma = (struct mlxd_foreach_action *)arg; 87251655Sadrian int i, fd; 88251655Sadrian 89251655Sadrian /* Get the device */ 90251655Sadrian if ((fd = open(ctrlrpath(unit), 0)) < 0) 91251730Sadrian return; 92251655Sadrian 93251655Sadrian for (i = -1; ;) { 94251655Sadrian /* Get the unit number of the next child device */ 95251655Sadrian if (ioctl(fd, MLX_NEXT_CHILD, &i) < 0) 96251655Sadrian return; 97251655Sadrian 98251655Sadrian /* check that we can open this unit */ 99251655Sadrian if ((fd = open(drivepath(i), 0)) >= 0) 100251655Sadrian close(fd); 101251655Sadrian /* if we can, do */ 102251655Sadrian if (fd >= 0) { 103251655Sadrian ma->func(i, ma->arg); 104251655Sadrian } 105251655Sadrian } 106251730Sadrian} 107251730Sadrian 108251730Sadrianvoid 109251730Sadrianmlxd_foreach(void (*func)(int unit, void *arg), void *arg) 110251730Sadrian{ 111251730Sadrian struct mlxd_foreach_action ma; 112251730Sadrian 113251730Sadrian ma.func = func; 114251730Sadrian ma.arg = arg; 115251730Sadrian mlx_foreach(mlxd_foreach_ctrlr, &ma); 116251730Sadrian} 117251730Sadrian 118251655Sadrian/******************************************************************************** 119251655Sadrian * Find the controller that manages the drive (unit), return controller number 120251655Sadrian * and system drive number on that controller. 121251655Sadrian */ 122251655Sadrianstatic struct 123251655Sadrian{ 124251655Sadrian int unit; 125251655Sadrian int ctrlr; 126251655Sadrian int sysdrive; 127251655Sadrian} mlxd_find_ctrlr_param; 128251655Sadrian 129251655Sadrianstatic void 130251655Sadrianmlxd_find_ctrlr_search(int unit, void *arg) 131251655Sadrian{ 132251655Sadrian int i, fd; 133251655Sadrian 134251655Sadrian /* Get the device */ 135251655Sadrian if ((fd = open(ctrlrpath(unit), 0)) >= 0) { 136251655Sadrian for (i = -1; ;) { 137251655Sadrian /* Get the unit number of the next child device */ 138251655Sadrian if (ioctl(fd, MLX_NEXT_CHILD, &i) < 0) 139251655Sadrian break; 140251655Sadrian 141251655Sadrian /* is this child the unit we want? */ 142251655Sadrian if (i == mlxd_find_ctrlr_param.unit) { 143251655Sadrian mlxd_find_ctrlr_param.ctrlr = unit; 144251655Sadrian if (ioctl(fd, MLX_GET_SYSDRIVE, &i) == 0) 145251655Sadrian mlxd_find_ctrlr_param.sysdrive = i; 146251655Sadrian } 147251655Sadrian } 148251655Sadrian close(fd); 149251655Sadrian } 150251655Sadrian} 151251655Sadrian 152251655Sadrianint 153251655Sadrianmlxd_find_ctrlr(int unit, int *ctrlr, int *sysdrive) 154251655Sadrian{ 155251655Sadrian mlxd_find_ctrlr_param.unit = unit; 156251655Sadrian mlxd_find_ctrlr_param.ctrlr = -1; 157251655Sadrian mlxd_find_ctrlr_param.sysdrive = -1; 158251655Sadrian 159251655Sadrian mlx_foreach(mlxd_find_ctrlr_search, NULL); 160251655Sadrian if ((mlxd_find_ctrlr_param.ctrlr != -1) && (mlxd_find_ctrlr_param.sysdrive != -1)) { 161251655Sadrian *ctrlr = mlxd_find_ctrlr_param.ctrlr; 162251655Sadrian *sysdrive = mlxd_find_ctrlr_param.sysdrive; 163251655Sadrian return(0); 164251655Sadrian } 165251655Sadrian return(1); 166251655Sadrian} 167251655Sadrian 168251655Sadrian 169251655Sadrian/******************************************************************************** 170251655Sadrian * Send a command to the controller on (fd) 171251655Sadrian */ 172251655Sadrian 173251655Sadrianvoid 174251655Sadrianmlx_command(int fd, void *arg) 175251655Sadrian{ 176251655Sadrian struct mlx_usercommand *cmd = (struct mlx_usercommand *)arg; 177251655Sadrian int error; 178251655Sadrian 179251655Sadrian error = ioctl(fd, MLX_COMMAND, cmd); 180251655Sadrian if (error != 0) 181251655Sadrian cmd->mu_error = error; 182251655Sadrian} 183251655Sadrian 184251655Sadrian/******************************************************************************** 185251655Sadrian * Perform an ENQUIRY2 command and return information related to the controller 186251655Sadrian * (unit) 187251655Sadrian */ 188251655Sadrianint 189251655Sadrianmlx_enquiry(int unit, struct mlx_enquiry2 *enq) 190251655Sadrian{ 191251655Sadrian struct mlx_usercommand cmd; 192251655Sadrian 193251655Sadrian /* build the command */ 194251655Sadrian cmd.mu_datasize = sizeof(*enq); 195251655Sadrian cmd.mu_buf = enq; 196251655Sadrian cmd.mu_bufptr = 8; 197251655Sadrian cmd.mu_command[0] = MLX_CMD_ENQUIRY2; 198251655Sadrian 199251655Sadrian /* hand it off for processing */ 200251655Sadrian mlx_perform(unit, mlx_command, (void *)&cmd); 201251655Sadrian 202251655Sadrian return(cmd.mu_status != 0); 203251655Sadrian} 204251655Sadrian 205251655Sadrian 206251655Sadrian/******************************************************************************** 207251655Sadrian * Perform a READ CONFIGURATION command and return information related to the controller 208251655Sadrian * (unit) 209251655Sadrian */ 210251655Sadrianint 211251655Sadrianmlx_read_configuration(int unit, struct mlx_core_cfg *cfg) 212251655Sadrian{ 213251655Sadrian struct mlx_usercommand cmd; 214251655Sadrian 215251655Sadrian /* build the command */ 216251655Sadrian cmd.mu_datasize = sizeof(*cfg); 217251655Sadrian cmd.mu_buf = cfg; 218251655Sadrian cmd.mu_bufptr = 8; 219251655Sadrian cmd.mu_command[0] = MLX_CMD_READ_CONFIG; 220251655Sadrian 221251655Sadrian /* hand it off for processing */ 222251655Sadrian mlx_perform(unit, mlx_command, (void *)&cmd); 223251655Sadrian 224251655Sadrian return(cmd.mu_status != 0); 225251655Sadrian} 226251655Sadrian 227251655Sadrian/******************************************************************************** 228251655Sadrian * Perform a SCSI INQUIRY command and return pointers to the relevant data. 229251655Sadrian */ 230251655Sadrianint 231251655Sadrianmlx_scsi_inquiry(int unit, int channel, int target, char **vendor, char **device, char **revision) 232251655Sadrian{ 233251655Sadrian struct mlx_usercommand cmd; 234251655Sadrian static struct { 235251655Sadrian struct mlx_dcdb dcdb; 236251655Sadrian union { 237251655Sadrian struct scsi_inquiry_data inq; 238251655Sadrian u_int8_t pad[SHORT_INQUIRY_LENGTH]; 239251655Sadrian } d; 240251655Sadrian } __attribute__ ((packed)) dcdb_cmd; 241251655Sadrian struct scsi_inquiry *inq_cmd = (struct scsi_inquiry *)&dcdb_cmd.dcdb.dcdb_cdb[0]; 242251655Sadrian 243251655Sadrian /* build the command */ 244251655Sadrian cmd.mu_datasize = sizeof(dcdb_cmd); 245251655Sadrian cmd.mu_buf = &dcdb_cmd; 246251655Sadrian cmd.mu_command[0] = MLX_CMD_DIRECT_CDB; 247251655Sadrian 248251655Sadrian /* build the DCDB */ 249251655Sadrian bzero(&dcdb_cmd, sizeof(dcdb_cmd)); 250251655Sadrian dcdb_cmd.dcdb.dcdb_channel = channel; 251251655Sadrian dcdb_cmd.dcdb.dcdb_target = target; 252251655Sadrian dcdb_cmd.dcdb.dcdb_flags = MLX_DCDB_DATA_IN | MLX_DCDB_TIMEOUT_10S; 253251655Sadrian dcdb_cmd.dcdb.dcdb_datasize = SHORT_INQUIRY_LENGTH; 254251655Sadrian dcdb_cmd.dcdb.dcdb_cdb_length = 6; 255251655Sadrian dcdb_cmd.dcdb.dcdb_sense_length = SSD_FULL_SIZE; 256251655Sadrian 257251655Sadrian /* build the cdb */ 258251655Sadrian inq_cmd->opcode = INQUIRY; 259251655Sadrian inq_cmd->length = SHORT_INQUIRY_LENGTH; 260251655Sadrian 261251655Sadrian /* hand it off for processing */ 262251655Sadrian mlx_perform(unit, mlx_command, &cmd); 263251655Sadrian 264251655Sadrian if (cmd.mu_status == 0) { 265251655Sadrian *vendor = &dcdb_cmd.d.inq.vendor[0]; 266251655Sadrian *device = &dcdb_cmd.d.inq.product[0]; 267251655Sadrian *revision = &dcdb_cmd.d.inq.revision[0]; 268251655Sadrian } 269251655Sadrian return(cmd.mu_status); 270251655Sadrian} 271251655Sadrian 272251655Sadrian/******************************************************************************** 273251655Sadrian * Perform a GET DEVICE STATE command and return pointers to the relevant data. 274251655Sadrian */ 275251655Sadrianint 276251655Sadrianmlx_get_device_state(int unit, int channel, int target, struct mlx_phys_drv *drv) 277251655Sadrian{ 278251655Sadrian struct mlx_usercommand cmd; 279251655Sadrian 280251655Sadrian /* build the command */ 281251655Sadrian cmd.mu_datasize = sizeof(*drv); 282251655Sadrian cmd.mu_buf = drv; 283251655Sadrian cmd.mu_bufptr = 8; 284251655Sadrian cmd.mu_command[0] = MLX_CMD_DEVICE_STATE; 285251655Sadrian cmd.mu_command[2] = channel; 286251655Sadrian cmd.mu_command[3] = target; 287251655Sadrian 288251655Sadrian /* hand it off for processing */ 289251655Sadrian mlx_perform(unit, mlx_command, (void *)&cmd); 290251655Sadrian 291251655Sadrian return(cmd.mu_status != 0); 292251655Sadrian} 293251655Sadrian