Add support for editing mode pages.

This commit is contained in:
Peter Dufault 1995-05-05 20:42:00 +00:00
parent 5134dcebcc
commit 9a8e4e5bdc
2 changed files with 266 additions and 22 deletions

View file

@ -39,7 +39,7 @@
.\" SUCH DAMAGE.
.\"
.\"
.\" $Id: scsi.8,v 1.3 1995/04/28 19:24:38 dufault Exp $
.\" $Id: scsi.8,v 1.4 1995/05/01 12:35:04 dufault Exp $
.\"
.Dd October 11, 1993
.Dt SCSI 8
@ -52,7 +52,7 @@
Usage:
scsi -f device -d debug_level # To set debug level
scsi -f device [-v] -z seconds # To freeze bus
scsi -f device -m page [-P pc] # To read mode pages
scsi -f device -m page [-P pc] [-e] # To read mode pages
scsi -f device -p [-b bus] [-l lun] # To probe all devices
scsi -f device -r [-b bus] [-t targ] [-l lun] # To reprobe a device
scsi -f device [-v] [-s seconds] -c cmd_fmt [arg0 ... argn] # A command...
@ -95,6 +95,8 @@ option is used to read a device mode page. The file
.Fr /usr/share/misc/scsi_modes
is read to look at for how to interpret the mode data. The environment
variable SCSI_MODES can specify a different file to use.
.Pp
.in +.25i
The
.Fr -P
option can be used to specify a page control field. The page control
@ -106,9 +108,14 @@ fields are
3 Saved Values
.Ed
.Pp
Eventually this will also support a
The
.Fr -e
option to permit editing the fields.
option permits you to edit the fields. It will use the editor specified
by your EDITOR environment variable. To store changes permanently,
edit page control 3 using the
.Fr -P
flag.
.in -.25i
.Pp
The
.Fr -p
@ -143,6 +150,7 @@ for full details of which minor devices permit the ioctl, and
.Xr scsi 3
for the full details on how to build up the commands and data phases
using the format arguments.
.in +.25i
.Pp
.Fr -v
turns on more verbose information.
@ -181,6 +189,7 @@ and displayed on the standard output.
can be specified as a hyphen ("-") to indicate that the
.Fr count
bytes of data input should be written to the standard output.
.in -.25i
.Sh EXAMPLES
To verify that the device type for the disk /dev/rsd0c is 0
(direct access device):
@ -193,6 +202,11 @@ To do an inquiry to /dev/rsd2c:
.Bd -literal -offset
root# scsi -f /dev/rsd2c -c "12 0 0 0 64 0" -i 64 "s8 z8 z16 z4"
FUJITSU M2654S-512 010P
.Pp
To edit mode page 1 on /dev/rsd2c, and store it permanently on the
drive:
.Bd -literal -offset
root# scsi -f /dev/rsd2c -m 1 -e -P 3
.Ed
.Pp
.Sh ENVIRONMENT
@ -206,6 +220,8 @@ it back to zero at program exit.
.Pp
The SU_DEBUG_TRUNCATE variable can be set to an integer to limit the
amount of data phase output sent to the debugging file.
.Pp
The EDITOR variable determines the editor to use for the mode editor.
.Sh SEE ALSO
.Xr scsi 4 ,
.Xr scsi 3

View file

@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: scsi.c,v 1.5 1995/05/01 12:35:05 dufault Exp $
* $Id: scsi.c,v 1.6 1995/05/01 12:54:32 dufault Exp $
*/
#include <stdio.h>
@ -450,6 +450,29 @@ void mode_sense(int fd, u_char *data, int len, int pc, int page)
free(scsireq);
}
void mode_select(int fd, u_char *data, int len, int perm)
{
scsireq_t *scsireq;
scsireq = scsireq_new();
if (scsireq_enter(fd, scsireq_build(scsireq,
len, data, SCCMD_WRITE,
"15 0:7 v:1 {SP} 0 0 v:i1 {Allocation Length} 0", perm, len)) == -1) /* Mode select */
{
scsi_debug(stderr, -1, scsireq);
exit(errno);
}
if (SCSIREQ_ERROR(scsireq))
{
scsi_debug(stderr, 0, scsireq);
exit(-1);
}
free(scsireq);
}
#define START_ENTRY '{'
#define END_ENTRY '}'
@ -541,15 +564,152 @@ static char *mode_lookup(int page)
return (found) ? fmt : 0;
}
static void mode_edit(int fd, int page, int edit, int argc, char *argv[])
/* -------- edit: Mode Select Editor ---------
*/
struct editinfo
{
int can_edit;
int default_value;
} editinfo[64]; /* XXX Bogus fixed size */
static int editind;
static FILE *edit_file;
static char edit_name[L_tmpnam];
static inline void
edit_rewind(void)
{
editind = 0;
}
static void
edit_init(void)
{
edit_rewind();
if (tmpnam(edit_name) == 0) {
perror("tmpnam failed");
exit(errno);
}
if ( (edit_file = fopen(edit_name, "w")) == 0) {
perror(edit_name);
exit(errno);
}
}
static void
edit_check(void *hook, int letter, void *arg, int count, char *name)
{
if (letter != 'i' && letter != 'b') {
fprintf(stderr, "Can't edit format %c.\n", letter);
exit(-1);
}
if (editind >= sizeof(editinfo) / sizeof(editinfo[0])) {
fprintf(stderr, "edit table overflow\n");
exit(ENOMEM);
}
editinfo[editind].can_edit = ((int)arg != 0);
editind++;
}
static void
edit_defaults(void *hook, int letter, void *arg, int count, char *name)
{
if (letter != 'i' && letter != 'b') {
fprintf(stderr, "Can't edit format %c.\n", letter);
exit(-1);
}
editinfo[editind].default_value = ((int)arg);
editind++;
}
static void
edit_report(void *hook, int letter, void *arg, int count, char *name)
{
if (editinfo[editind].can_edit) {
if (letter != 'i' && letter != 'b') {
fprintf(stderr, "Can't report format %c.\n", letter);
exit(-1);
}
fprintf(edit_file, "%s: %d\n", name, (int)arg);
}
editind++;
}
static int
edit_get(void *hook, char *name)
{
struct get_hook *h = (struct get_hook *)hook;
int arg = editinfo[editind].default_value;
if (editinfo[editind].can_edit) {
char line[80];
if (fgets(line, sizeof(line), edit_file) == 0) {
perror("fgets");
exit(errno);
}
line[strlen(line) - 1] = 0;
if (strncmp(name, line, strlen(name)) != 0) {
fprintf(stderr, "Expected \"%s\" and read \"%s\"\n",
name, line);
exit(-1);
}
arg = strtoul(line + strlen(name) + 2, 0, 0);
}
editind++;
return arg;
}
static void
edit_edit(void)
{
char *system_line;
char *editor = getenv("EDITOR");
if (!editor)
editor = "vi";
fclose(edit_file);
system_line = malloc(strlen(editor) + strlen(edit_name) + 6);
sprintf(system_line, "%s %s", editor, edit_name);
system(system_line);
free(system_line);
if ( (edit_file = fopen(edit_name, "r")) == 0) {
perror(edit_name);
exit(errno);
}
}
static void
mode_edit(int fd, int page, int edit, int argc, char *argv[])
{
int i;
u_char data[255];
int mode_data_length;
int block_descriptor_length;
u_char *mode_data;
u_char *mode_parameters;
int page_length;
u_char *mode_pars;
struct mode_header
{
u_char mdl; /* Mode data length */
u_char medium_type;
u_char dev_spec_par;
u_char bdl; /* Block descriptor length */
};
struct mode_page_header
{
u_char page_code;
u_char page_length;
};
struct mode_header *mh;
struct mode_page_header *mph;
char *fmt = mode_lookup(page);
if (!fmt && verbose) {
@ -558,29 +718,97 @@ static void mode_edit(int fd, int page, int edit, int argc, char *argv[])
mode_db, page, (edit ? "edit" : "display"));
}
if (edit)
fprintf(stderr, "Sorry; can't edit yet.\n");
if (edit) {
if (!fmt) {
fprintf(stderr, "Sorry: can't edit without a format.\n");
exit(-1);
}
if (pagectl != 0 && pagectl != 3) {
fprintf(stderr,
"It only makes sense to edit page 0 (current) or page 3 (saved values)\n");
exit(-1);
}
verbose = 1;
mode_sense(fd, data, sizeof(data), 1, page);
mh = (struct mode_header *)data;
mph = (struct mode_page_header *)
(((char *)mh) + sizeof(*mh) + mh->bdl);
mode_pars = (char *)mph + sizeof(*mph);
edit_init();
scsireq_buff_decode_visit(mode_pars, mh->mdl,
fmt, edit_check, 0);
mode_sense(fd, data, sizeof(data), 0, page);
edit_rewind();
scsireq_buff_decode_visit(mode_pars, mh->mdl,
fmt, edit_defaults, 0);
edit_rewind();
scsireq_buff_decode_visit(mode_pars, mh->mdl,
fmt, edit_report, 0);
edit_edit();
edit_rewind();
scsireq_buff_encode_visit(mode_pars, mh->mdl,
fmt, edit_get, 0);
/* Eliminate block descriptors:
*/
bcopy((char *)mph, ((char *)mh) + sizeof(*mh),
sizeof(*mph) + mph->page_length);
mh->bdl = 0;
mph = (struct mode_page_header *) (((char *)mh) + sizeof(*mh));
mode_pars = ((char *)mph) + 2;
#if 0
/* Turn this on to see what you're sending to the
* device:
*/
edit_rewind();
scsireq_buff_decode_visit(mode_pars,
mh->mdl, fmt, arg_put, 0);
#endif
/* Make it permanent if pageselect is three.
*/
mph->page_code &= ~0xC0; /* Clear PS and RESERVED */
mh->mdl = 0; /* Reserved for mode select */
mode_select(fd, (char *)mh,
sizeof(*mh) + mh->bdl + sizeof(*mph) + mph->page_length,
(pagectl == 3));
exit(0);
}
mode_sense(fd, data, sizeof(data), pagectl, page);
/* Skip over the block descriptors.
*/
mode_data_length = data[0];
block_descriptor_length = data[3];
mode_data = data + 4 + block_descriptor_length;
page_length = mode_data[1];
mode_parameters = mode_data + 2;
mh = (struct mode_header *)data;
mph = (struct mode_page_header *)(((char *)mh) + sizeof(*mh) + mh->bdl);
mode_pars = (char *)mph + sizeof(*mph);
if (!fmt) {
for (i = 0; i < mode_data_length; i++) {
printf("%02x%c",mode_parameters[i],
for (i = 0; i < mh->mdl; i++) {
printf("%02x%c",mode_pars[i],
(((i + 1) % 8) == 0) ? '\n' : ' ');
}
putc('\n', stdout);
} else {
verbose = 1;
scsireq_buff_decode_visit(mode_parameters,
mode_data_length, fmt, arg_put, 0);
scsireq_buff_decode_visit(mode_pars,
mh->mdl, fmt, arg_put, 0);
}
}