This is an overhaul of the mode page handling in camcontrol as well as
related patches. These include: * Mode page editting can be scripted. This involves two things: first, if stdin is not a tty, changes are read from stdin rather than invoking $EDITOR. Second, and more importantly, not all modepage entries must be included in the change set. This means that camcontrol can now gracefully handle more intrusive editting from the $EDITOR, including removal or rearrangement of lines. It also means that you can do stuff like: # echo "WCE: 1" | camcontrol modepage da3 -m 8 -e # newfs /dev/da3 # echo "WCE: 0" | camcontrol modepage da3 -m 8 -e * Range-checking on user-supplied input values. modeedit.c now uses the field width specifiers to determine the maximum allowable value for a field. If the user enters a value larger than the maximum, it clips the value to the max and warns the user. This also involved patching cam_cmdparse.c to be more consistent with regards to the "count" parameter to arg_put (previously is was the length of strings and 1 for all integral types). The cam_cdbparse(3) man page was also updated to reflect the revised semantics. * In the process, I removed the 64 entry limit on mode pages (not that we were even close to hitting that limit). This was a nice side-effect of the other changes. * Technically, the new mode editting functionality allows editting of character array entries in mode pages (type 'c' or 'z'), however since buff_encode doesn't grok them it is currently useless. * Camcontrol gained two new options related to mode pages: -l and -b. The former lists all available mode pages for a given device. The latter forces mode page display in binary format (the default when no mode page definition was found in scsi_modes). * Added support for mode page names to scsi_modes. Allows names to be displayed alongside mode numbers in the mode page listing. Updated scsi_modes to use the new functionality. This also adds the semicolon into the scsi_modes syntax as an optional mode page definition terminator. This is needed to name pages without providing a page format definition. * Updated scsi_all.h to include a structure describing mode page headers. * Added $FreeBSD$ line to scsi_modes. Inspired by: dwhite Reviewed by: ken
This commit is contained in:
parent
4f0682b0f3
commit
7e32b20d95
@ -444,9 +444,9 @@ function.
|
||||
.It Fa val
|
||||
is a void pointer to the value being passed into the function.
|
||||
.It Fa count
|
||||
is the number of arguments being passed into the
|
||||
is the size of the value being passed into the
|
||||
.Fn arg_put
|
||||
function. At present this will only be set to 1.
|
||||
function. The argument format determines the unit of measure.
|
||||
.It Fa name
|
||||
This is a text description of the field, if one was provided in the
|
||||
.Fa fmt .
|
||||
|
@ -119,7 +119,8 @@ do_buff_decode(u_int8_t *databuf, size_t len,
|
||||
if (arg_put) \
|
||||
(*arg_put)(puthook, (letter == 't' ? \
|
||||
'b' : letter), \
|
||||
(void *)((long)(ARG)), 1, field_name); \
|
||||
(void *)((long)(ARG)), width, \
|
||||
field_name); \
|
||||
else \
|
||||
*(va_arg(ap, int *)) = (ARG); \
|
||||
assigned++; \
|
||||
|
@ -2,7 +2,7 @@
|
||||
MAINTAINER=ken@FreeBSD.ORG
|
||||
|
||||
PROG= camcontrol
|
||||
SRCS= camcontrol.c modeedit.c
|
||||
SRCS= camcontrol.c modeedit.c util.c
|
||||
MAN8= camcontrol.8
|
||||
SDIR= ${.CURDIR}/../../sys
|
||||
|
||||
|
@ -87,9 +87,9 @@
|
||||
.Ic modepage
|
||||
.Op device id
|
||||
.Op generic args
|
||||
.Aq Fl m Ar page
|
||||
.Aq Fl m Ar page \*(Ba Fl l
|
||||
.Op Fl P Ar pgctl
|
||||
.Op Fl e
|
||||
.Op Fl b | Fl e
|
||||
.Op Fl d
|
||||
.Nm camcontrol
|
||||
.Ic cmd
|
||||
@ -317,11 +317,23 @@ command takes several arguments:
|
||||
.Bl -tag -width 012345678901
|
||||
.It Fl d
|
||||
Disable block descriptors for mode sense.
|
||||
.It Fl b
|
||||
Displays mode page data in binary format.
|
||||
.It Fl e
|
||||
This flag allows the user to edit values in the mode page.
|
||||
This flag allows the user to edit values in the mode page. The user may
|
||||
either edit mode page values with the text editor pointed to by his
|
||||
.Ev EDITOR
|
||||
environment variable, or supply mode page values via standard input, using
|
||||
the same format that
|
||||
.Nm camcontrol
|
||||
uses to display mode page values. The editor will be invoked if
|
||||
.Nm camcontrol
|
||||
detects that standard input is terminal.
|
||||
.It Fl l
|
||||
Lists all available mode pages.
|
||||
.It Fl m Ar mode_page
|
||||
This specifies the number of the mode page the user would like to view
|
||||
and/or edit. This argument is mandatory.
|
||||
and/or edit. This argument is mandatory unless -l is specified.
|
||||
.It Fl P Ar pgctl
|
||||
This allows the user to specify the page control field. Possible values are:
|
||||
.Bl -tag -width xxx -compact
|
||||
|
@ -124,7 +124,7 @@ struct camcontrol_opts option_table[] = {
|
||||
{"defectlist", CAM_ARG_READ_DEFECTS, readdefect_opts},
|
||||
{"devlist", CAM_ARG_DEVTREE, NULL},
|
||||
{"periphlist", CAM_ARG_DEVLIST, NULL},
|
||||
{"modepage", CAM_ARG_MODE_PAGE, "dem:P:"},
|
||||
{"modepage", CAM_ARG_MODE_PAGE, "bdelm:P:"},
|
||||
{"tags", CAM_ARG_TAG, "N:q"},
|
||||
{"negotiate", CAM_ARG_RATE, negotiate_opts},
|
||||
{"rate", CAM_ARG_RATE, negotiate_opts},
|
||||
@ -1554,15 +1554,22 @@ modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
|
||||
int retry_count, int timeout)
|
||||
{
|
||||
int c, mode_page = -1, page_control = 0;
|
||||
int binary = 0, list = 0;
|
||||
|
||||
while ((c = getopt(argc, argv, combinedopt)) != -1) {
|
||||
switch(c) {
|
||||
case 'b':
|
||||
binary = 1;
|
||||
break;
|
||||
case 'd':
|
||||
arglist |= CAM_ARG_DBD;
|
||||
break;
|
||||
case 'e':
|
||||
arglist |= CAM_ARG_MODE_EDIT;
|
||||
break;
|
||||
case 'l':
|
||||
list = 1;
|
||||
break;
|
||||
case 'm':
|
||||
mode_page = strtol(optarg, NULL, 0);
|
||||
if (mode_page < 0)
|
||||
@ -1580,11 +1587,17 @@ modepage(struct cam_device *device, int argc, char **argv, char *combinedopt,
|
||||
}
|
||||
}
|
||||
|
||||
if (mode_page == -1)
|
||||
if (mode_page == -1 && list == 0)
|
||||
errx(1, "you must specify a mode page!");
|
||||
|
||||
mode_edit(device, mode_page, page_control, arglist & CAM_ARG_DBD,
|
||||
arglist & CAM_ARG_MODE_EDIT, retry_count, timeout);
|
||||
if (list) {
|
||||
mode_list(device, page_control, arglist & CAM_ARG_DBD,
|
||||
retry_count, timeout);
|
||||
} else {
|
||||
mode_edit(device, mode_page, page_control,
|
||||
arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary,
|
||||
retry_count, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2975,8 +2988,8 @@ usage(int verbose)
|
||||
" camcontrol rescan <bus[:target:lun]>\n"
|
||||
" camcontrol reset <bus[:target:lun]>\n"
|
||||
" camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n"
|
||||
" camcontrol modepage [dev_id][generic args] <-m page> [-P pagectl]\n"
|
||||
" [-e][-d]\n"
|
||||
" camcontrol modepage [dev_id][generic args] <-m page | -l>\n"
|
||||
" [-P pagectl][-e | -b][-d]\n"
|
||||
" camcontrol cmd [dev_id][generic args] <-c cmd [args]>\n"
|
||||
" [-i len fmt|-o len fmt [args]]\n"
|
||||
" camcontrol debug [-I][-T][-S][-c] <all|bus[:target[:lun]]|off>\n"
|
||||
@ -3022,6 +3035,7 @@ usage(int verbose)
|
||||
"modepage arguments:\n"
|
||||
"-m page specify the mode page to view or edit\n"
|
||||
"-e edit the specified mode page\n"
|
||||
"-b force view to binary mode\n"
|
||||
"-d disable block descriptors for mode sense\n"
|
||||
"-P pgctl page control field 0-3\n"
|
||||
"defects arguments:\n"
|
||||
|
@ -46,7 +46,9 @@ void mode_sense(struct cam_device *device, int mode_page, int page_control,
|
||||
void mode_select(struct cam_device *device, int save_pages, int retry_count,
|
||||
int timeout, u_int8_t *data, int datalen);
|
||||
void mode_edit(struct cam_device *device, int page, int page_control, int dbd,
|
||||
int edit, int retry_count, int timeout);
|
||||
int edit, int binary, int retry_count, int timeout);
|
||||
void mode_list(struct cam_device *device, int page_control, int dbd,
|
||||
int retry_count, int timeout);
|
||||
char *cget(void *hook, char *name);
|
||||
int iget(void *hook, char *name);
|
||||
void arg_put(void *hook, int letter, void *arg, int count, char *name);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -48,22 +48,15 @@ static const char rcsid[] =
|
||||
"$FreeBSD$";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/file.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <camlib.h>
|
||||
#include "camcontrol.h"
|
||||
|
||||
int verbose = 0;
|
||||
int verbose;
|
||||
|
||||
/* iget: Integer argument callback
|
||||
*/
|
||||
@ -157,347 +150,3 @@ arg_put(void *hook, int letter, void *arg, int count, char *name)
|
||||
if (verbose)
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
#define START_ENTRY '{'
|
||||
#define END_ENTRY '}'
|
||||
|
||||
static void
|
||||
skipwhite(FILE *f)
|
||||
{
|
||||
int c;
|
||||
|
||||
skip_again:
|
||||
|
||||
while (isspace(c = getc(f)))
|
||||
;
|
||||
|
||||
if (c == '#') {
|
||||
while ((c = getc(f)) != '\n' && c != EOF)
|
||||
;
|
||||
goto skip_again;
|
||||
}
|
||||
|
||||
ungetc(c, f);
|
||||
}
|
||||
|
||||
/* mode_lookup: Lookup a format description for a given page.
|
||||
*/
|
||||
char *mode_db = "/usr/share/misc/scsi_modes";
|
||||
static char *
|
||||
mode_lookup(int page)
|
||||
{
|
||||
char *new_db;
|
||||
FILE *modes;
|
||||
int match, next, found, c;
|
||||
static char fmt[4096]; /* XXX This should be with strealloc */
|
||||
int page_desc;
|
||||
new_db = getenv("SCSI_MODES");
|
||||
|
||||
if (new_db)
|
||||
mode_db = new_db;
|
||||
|
||||
modes = fopen(mode_db, "r");
|
||||
if (modes == 0)
|
||||
return 0;
|
||||
|
||||
next = 0;
|
||||
found = 0;
|
||||
|
||||
while (!found) {
|
||||
|
||||
skipwhite(modes);
|
||||
|
||||
if (fscanf(modes, "%i", &page_desc) != 1)
|
||||
break;
|
||||
|
||||
if (page_desc == page)
|
||||
found = 1;
|
||||
|
||||
skipwhite(modes);
|
||||
if (getc(modes) != START_ENTRY)
|
||||
errx(1, "expected %c", START_ENTRY);
|
||||
|
||||
match = 1;
|
||||
while (match != 0) {
|
||||
c = getc(modes);
|
||||
if (c == EOF) {
|
||||
warnx("expected %c", END_ENTRY);
|
||||
}
|
||||
|
||||
if (c == START_ENTRY) {
|
||||
match++;
|
||||
}
|
||||
if (c == END_ENTRY) {
|
||||
match--;
|
||||
if (match == 0)
|
||||
break;
|
||||
}
|
||||
if (found && c != '\n') {
|
||||
if (next >= sizeof(fmt))
|
||||
errx(1, "buffer overflow");
|
||||
|
||||
fmt[next++] = (u_char)c;
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt[next] = 0;
|
||||
|
||||
return (found) ? fmt : 0;
|
||||
}
|
||||
|
||||
/* -------- edit: Mode Select Editor ---------
|
||||
*/
|
||||
struct editinfo
|
||||
{
|
||||
int can_edit;
|
||||
int default_value;
|
||||
} editinfo[64]; /* XXX Bogus fixed size */
|
||||
|
||||
static int editind;
|
||||
volatile int edit_opened;
|
||||
static FILE *edit_file;
|
||||
static char edit_name[L_tmpnam];
|
||||
|
||||
static inline void
|
||||
edit_rewind(void)
|
||||
{
|
||||
editind = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
edit_done(void)
|
||||
{
|
||||
int opened;
|
||||
|
||||
sigset_t all, prev;
|
||||
sigfillset(&all);
|
||||
|
||||
(void)sigprocmask(SIG_SETMASK, &all, &prev);
|
||||
|
||||
opened = (int)edit_opened;
|
||||
edit_opened = 0;
|
||||
|
||||
(void)sigprocmask(SIG_SETMASK, &prev, 0);
|
||||
|
||||
if (opened)
|
||||
{
|
||||
if (fclose(edit_file))
|
||||
warn("%s", edit_name);
|
||||
if (unlink(edit_name))
|
||||
warn("%s", edit_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
edit_init(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
edit_rewind();
|
||||
strlcpy(edit_name, "/tmp/camXXXXXX", sizeof(edit_name));
|
||||
if ((fd = mkstemp(edit_name)) == -1)
|
||||
errx(1, "mkstemp failed");
|
||||
if ((edit_file = fdopen(fd, "w")) == 0)
|
||||
err(1, "%s", edit_name);
|
||||
edit_opened = 1;
|
||||
|
||||
atexit(edit_done);
|
||||
}
|
||||
|
||||
static void
|
||||
edit_check(void *hook, int letter, void *arg, int count, char *name)
|
||||
{
|
||||
if (letter != 'i' && letter != 'b')
|
||||
errx(1, "can't edit format %c", letter);
|
||||
|
||||
if (editind >= sizeof(editinfo) / sizeof(editinfo[0]))
|
||||
errx(1, "edit table overflow");
|
||||
|
||||
editinfo[editind].can_edit = (arg != NULL);
|
||||
editind++;
|
||||
}
|
||||
|
||||
static void
|
||||
edit_defaults(void *hook, int letter, void *arg, int count, char *name)
|
||||
{
|
||||
if (letter != 'i' && letter != 'b')
|
||||
errx(1, "can't edit format %c", letter);
|
||||
|
||||
editinfo[editind].default_value = (intptr_t)arg; /* truncated */
|
||||
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')
|
||||
errx(1, "can't report format %c", letter);
|
||||
|
||||
fprintf(edit_file, "%s: %d\n", name, (intptr_t)arg);
|
||||
}
|
||||
|
||||
editind++;
|
||||
}
|
||||
|
||||
static int
|
||||
edit_get(void *hook, char *name)
|
||||
{
|
||||
int arg = editinfo[editind].default_value;
|
||||
|
||||
if (editinfo[editind].can_edit) {
|
||||
char line[80];
|
||||
if (fgets(line, sizeof(line), edit_file) == 0)
|
||||
err(1, "fgets");
|
||||
|
||||
line[strlen(line) - 1] = 0;
|
||||
|
||||
if (strncmp(name, line, strlen(name)) != 0)
|
||||
errx(1, "expected \"%s\" and read \"%s\"", name, line);
|
||||
|
||||
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)
|
||||
err(1, "%s", edit_name);
|
||||
}
|
||||
|
||||
void
|
||||
mode_edit(struct cam_device *device, int page, int page_control, int dbd,
|
||||
int edit, int retry_count, int timeout)
|
||||
{
|
||||
int i;
|
||||
u_char data[255];
|
||||
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) {
|
||||
fprintf(stderr,
|
||||
"No mode data base entry in \"%s\" for page %d; "
|
||||
" binary %s only.\n",
|
||||
mode_db, page, (edit ? "edit" : "display"));
|
||||
}
|
||||
|
||||
if (edit) {
|
||||
if (!fmt)
|
||||
errx(1, "can't edit without a format");
|
||||
|
||||
if (page_control != 0 && page_control != 3)
|
||||
errx(1, "it only makes sense to edit page 0 "
|
||||
"(current) or page 3 (saved values)");
|
||||
|
||||
verbose = 1;
|
||||
|
||||
mode_sense(device, page, 1, dbd, retry_count, timeout,
|
||||
data, sizeof(data));
|
||||
|
||||
mh = (struct mode_header *)data;
|
||||
mph = (struct mode_page_header *)
|
||||
(((char *)mh) + sizeof(*mh) + mh->bdl);
|
||||
|
||||
mode_pars = (char *)mph + sizeof(*mph);
|
||||
|
||||
edit_init();
|
||||
buff_decode_visit(mode_pars, mh->mdl, fmt, edit_check, 0);
|
||||
|
||||
mode_sense(device, page, 0, dbd, retry_count, timeout,
|
||||
data, sizeof(data));
|
||||
|
||||
edit_rewind();
|
||||
buff_decode_visit(mode_pars, mh->mdl, fmt, edit_defaults, 0);
|
||||
|
||||
edit_rewind();
|
||||
buff_decode_visit(mode_pars, mh->mdl, fmt, edit_report, 0);
|
||||
|
||||
edit_edit();
|
||||
|
||||
edit_rewind();
|
||||
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 = mh->dev_spec_par = 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();
|
||||
buff_decode_visit(mode_pars, mh->mdl, fmt, arg_put, 0);
|
||||
#endif
|
||||
|
||||
edit_done();
|
||||
|
||||
/* Make it permanent if pageselect is three.
|
||||
*/
|
||||
|
||||
mph->page_code &= ~0xC0; /* Clear PS and RESERVED */
|
||||
mh->mdl = 0; /* Reserved for mode select */
|
||||
|
||||
mode_select(device, (page_control == 3), retry_count,
|
||||
timeout, (u_int8_t *)mh, sizeof(*mh) + mh->bdl +
|
||||
sizeof(*mph) + mph->page_length);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mode_sense(device, page, page_control, dbd, retry_count, timeout,
|
||||
data, sizeof(data));
|
||||
|
||||
/* Skip over the block descriptors.
|
||||
*/
|
||||
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 < mh->mdl; i++) {
|
||||
printf("%02x%c",mode_pars[i],
|
||||
(((i + 1) % 8) == 0) ? '\n' : ' ');
|
||||
}
|
||||
putc('\n', stdout);
|
||||
} else {
|
||||
verbose = 1;
|
||||
buff_decode_visit(mode_pars, mh->mdl, fmt, arg_put, NULL);
|
||||
}
|
||||
}
|
||||
|
@ -27,13 +27,14 @@
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
# SUCH DAMAGE.
|
||||
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# The ordering is alphabetical by page name, as it appears in the SCSI spec.
|
||||
|
||||
# ALL DEVICE TYPES
|
||||
|
||||
# Control mode page:
|
||||
0x0a {
|
||||
0x0a "Control Mode Page" {
|
||||
{Reserved} *t7
|
||||
{RLEC} t1
|
||||
{Queue Algorithm Modifier} t4
|
||||
@ -49,8 +50,7 @@
|
||||
{Ready AEN Holdoff Period} i2
|
||||
}
|
||||
|
||||
# Disconnect-Reconnect Page:
|
||||
0x02 {
|
||||
0x02 "Disconnect-Reconnect Page" {
|
||||
{Buffer Full Ratio} i1
|
||||
{Buffer Empty Ratio} i1
|
||||
{Bus Inactivity Limit} i2
|
||||
@ -64,8 +64,7 @@
|
||||
{Reserved} *i1
|
||||
}
|
||||
|
||||
# Peripheral Device Page:
|
||||
0x09 {
|
||||
0x09 "Peripheral Device Page" {
|
||||
{Interface Identifier} i2
|
||||
{Reserved} *i1
|
||||
{Reserved} *i1
|
||||
@ -75,8 +74,7 @@
|
||||
|
||||
|
||||
# DIRECT ACCESS DEVICES
|
||||
# Caching page:
|
||||
0x08 {
|
||||
0x08 "Caching Page" {
|
||||
{IC} t1
|
||||
{ABPF} t1
|
||||
{CAP} t1
|
||||
@ -93,8 +91,7 @@
|
||||
{Maximum Pre-fetch Ceiling} i2
|
||||
}
|
||||
|
||||
# Flexible disk page:
|
||||
0x05 {
|
||||
0x05 "Flexible Disk Page" {
|
||||
{Transfer rate} i2
|
||||
{Number of heads} i1
|
||||
{Sectors per track} i1
|
||||
@ -125,8 +122,7 @@
|
||||
{Reserved} *i1
|
||||
}
|
||||
|
||||
# Format device page:
|
||||
0x03 {
|
||||
0x03 "Format Device Page" {
|
||||
{Tracks per Zone} i2
|
||||
{Alternate Sectors per Zone} i2
|
||||
{Alternate Tracks per Zone} i2
|
||||
@ -143,8 +139,7 @@
|
||||
{Reserved} *t4
|
||||
}
|
||||
|
||||
# Medium types supported page:
|
||||
0x0b {
|
||||
0x0b "Medium Types Supported Page" {
|
||||
{Reserved} *i1
|
||||
{Reserved} *i1
|
||||
{Medium type one supported} i1
|
||||
@ -154,9 +149,9 @@
|
||||
}
|
||||
|
||||
# Notch page (0x0c)
|
||||
0x0c "Notch and Partition Page";
|
||||
|
||||
# Read-Write Error Recovery Page
|
||||
0x01 {
|
||||
0x01 "Read-Write Error Recovery Page" {
|
||||
{AWRE (Auto Write Reallocation Enbld)} t1
|
||||
{ARRE (Auto Read Reallocation Enbld)} t1
|
||||
{TB (Transfer Block)} t1
|
||||
@ -175,8 +170,7 @@
|
||||
{Recovery Time Limit} i2
|
||||
}
|
||||
|
||||
# Rigid Disk Drive Geometry Page
|
||||
0x04 {
|
||||
0x04 "Rigid Disk Drive Geometry Page" {
|
||||
{Number of Cylinders} i3
|
||||
{Number of Heads} i1
|
||||
{Starting Cylinder-Write Precompensation} i3
|
||||
@ -192,8 +186,7 @@
|
||||
{Reserved} *i1
|
||||
}
|
||||
|
||||
# Verify Error Recovery Page
|
||||
0x07 {
|
||||
0x07 "Verify Error Recovery Page" {
|
||||
{Reserved} *t4
|
||||
{EER} t1
|
||||
{PER} t1
|
||||
@ -209,8 +202,7 @@
|
||||
{Verify Recovery Time Limit} i2
|
||||
}
|
||||
|
||||
# CD-ROM Audio Control Parameters Page
|
||||
0x0E {
|
||||
0x0E "CD-ROM Audio Control Parameters Page" {
|
||||
{Reserved} *t5
|
||||
{Immed} t1
|
||||
{SOTC} t1
|
||||
@ -246,7 +238,7 @@
|
||||
{Data Buffer Recovery} t1
|
||||
{Block Identifiers Support} t1
|
||||
{Report Setmarks} t1
|
||||
{AAutomatic Velocity Control} t1
|
||||
{Automatic Velocity Control} t1
|
||||
{Stop on Consecutive Filemarks} t2
|
||||
{Recover Buffer Order} t1
|
||||
{Report Early-Warning} t1
|
||||
@ -259,3 +251,5 @@
|
||||
{Select Data Compression Algorithm} i1
|
||||
{Reserved} *i1
|
||||
}
|
||||
|
||||
0x00 "Vendor-Specific";
|
||||
|
@ -677,7 +677,13 @@ struct scsi_mode_header_10
|
||||
u_int8_t blk_desc_len[2];
|
||||
};
|
||||
|
||||
struct scsi_mode_blk_desc
|
||||
struct scsi_mode_page_header
|
||||
{
|
||||
u_int8_t page_code;
|
||||
u_int8_t page_length;
|
||||
};
|
||||
|
||||
struct scsi_mode_blk_desc
|
||||
{
|
||||
u_int8_t density;
|
||||
u_int8_t nblocks[3];
|
||||
|
Loading…
x
Reference in New Issue
Block a user