Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sbin/scsictl Add a bunch of stuff from Bob Nestor that fixes...
details: https://anonhg.NetBSD.org/src/rev/4d10fdb32ff4
branches: trunk
changeset: 533282:4d10fdb32ff4
user: mjacob <mjacob%NetBSD.org@localhost>
date: Wed Jun 26 16:04:11 2002 +0000
description:
Add a bunch of stuff from Bob Nestor that fixes format to allow one to
specify device logical blocksize.
Furthermore, it also adds an 'immediate' option, which then sends more modern
devices into formatting in the background. scsictl still waits around and
sends a TEST UNIT READY every 10 seconds and, based upon the sense data
it gets back after the invariable CHECK CONDITION, prints out a progress
indicator (based upon SKSV progress in the sense data).
While we're at it, add a 'tur', 'reserve', 'release', 'start' and 'stop'
functions to the device commands.
Fix a long standing bug in scsi_command- the value in retsts is an integral
value- not a bitmask.
diffstat:
sbin/scsictl/extern.h | 3 +-
sbin/scsictl/scsi_subr.c | 27 +++-
sbin/scsictl/scsictl.8 | 67 +++++++++-
sbin/scsictl/scsictl.c | 325 +++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 404 insertions(+), 18 deletions(-)
diffs (truncated from 551 to 300 lines):
diff -r ab3d15e36703 -r 4d10fdb32ff4 sbin/scsictl/extern.h
--- a/sbin/scsictl/extern.h Wed Jun 26 15:29:43 2002 +0000
+++ b/sbin/scsictl/extern.h Wed Jun 26 16:04:11 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: extern.h,v 1.3 2001/09/05 16:25:17 thorpej Exp $ */
+/* $NetBSD: extern.h,v 1.4 2002/06/26 16:04:11 mjacob Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -48,4 +48,5 @@
void scsi_command __P((int, void *, size_t, void *, size_t, int, int));
void scsi_mode_sense __P((int, u_int8_t, u_int8_t, void *, size_t));
void scsi_mode_select __P((int, u_int8_t, void *, size_t));
+void scsi_request_sense __P((int, void *, size_t));
void scsi_strvis __P((char *, size_t, const char *, size_t));
diff -r ab3d15e36703 -r 4d10fdb32ff4 sbin/scsictl/scsi_subr.c
--- a/sbin/scsictl/scsi_subr.c Wed Jun 26 15:29:43 2002 +0000
+++ b/sbin/scsictl/scsi_subr.c Wed Jun 26 16:04:11 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: scsi_subr.c,v 1.5 2001/09/05 16:25:18 thorpej Exp $ */
+/* $NetBSD: scsi_subr.c,v 1.6 2002/06/26 16:04:12 mjacob Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -87,12 +87,15 @@
return;
/* Some problem; report it and exit. */
- if (req.retsts & SCCMD_TIMEOUT)
+ if (req.retsts == SCCMD_TIMEOUT)
fprintf(stderr, "%s: SCSI command timed out\n", dvname);
- if (req.retsts & SCCMD_BUSY)
+ else if (req.retsts == SCCMD_BUSY)
fprintf(stderr, "%s: device is busy\n", dvname);
- if (req.retsts & SCCMD_SENSE)
+ else if (req.retsts == SCCMD_SENSE)
scsi_print_sense(dvname, &req, 1);
+ else
+ fprintf(stderr, "%s: device had unknown status %x", dvname,
+ req.retsts);
exit(1);
}
@@ -135,6 +138,22 @@
}
void
+scsi_request_sense(fd, buf, len)
+ int fd;
+ void *buf;
+ size_t len;
+{
+ struct scsipi_sense cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ memset(buf, 0, len);
+
+ cmd.opcode = REQUEST_SENSE;
+ cmd.length = len;
+ scsi_command(fd, &cmd, sizeof(cmd), buf, len, 10000, SCCMD_READ);
+}
+
+void
scsi_strvis(sdst, dlen, ssrc, slen)
char *sdst;
size_t dlen;
diff -r ab3d15e36703 -r 4d10fdb32ff4 sbin/scsictl/scsictl.8
--- a/sbin/scsictl/scsictl.8 Wed Jun 26 15:29:43 2002 +0000
+++ b/sbin/scsictl/scsictl.8 Wed Jun 26 16:04:11 2002 +0000
@@ -1,4 +1,4 @@
-.\" $NetBSD: scsictl.8,v 1.13 2001/11/16 11:26:56 wiz Exp $
+.\" $NetBSD: scsictl.8,v 1.14 2002/06/26 16:04:13 mjacob Exp $
.\"
.\" Copyright (c) 1998 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -69,8 +69,41 @@
The following commands are supported for SCSI devices:
.Pp
.Nm format
+.Oo blocksize
+.Oo immediate
+.Oc
+.Oc
.Pp
-(Low level) format the named device.
+(Low level) format the named device. If the optional
+.Li blocksize
+parameter is provided, the device geometry will be modified to
+use the specified
+.Li blocksize.
+If this parameter is different form the Current or Default Mode Page 3
+parameters, the device will update Mode Page 3 at the successful
+completion of the Format. Device geometry may change as a result of
+using a new device
+.Li blocksize.
+When the optional
+.Li blocksize
+parameter is specified, the Defect List on the drive will revert to
+the original primary defect list created at the time of manufacture
+if available. The drive will usually recertify itself
+during the Format and add any other defective blocks to the new Defect
+List. Some disks may not support the ability to change the blocksize and
+may enter a Degraded Mode when fed a Format command of this type. If this
+happens the standard recovery for the drive requires issuing a correct
+Format command, i.e. one without the blocksize parameter.
+.Pp
+When the
+.Li immediate
+parameter is also specified, the disk is instructed to return from the
+format command right away. It continues to format, and every ten seconds
+.Nm
+issues a TEST UNIT READY command to check the associated sense data. This
+associated sense data has a progress indicator which indicates how far
+the format is progressing. Note well that most SCSI disk drives prior to
+a few years ago do not support this option.
.Pp
.Nm identify
.Pp
@@ -90,12 +123,42 @@
grown defect list. This command is only supported on
direct access devices.
.Pp
+.Nm release
+.Pp
+Send a "RELEASE" command to the device to release a reservation on it.
+.Pp
+.Nm reserve
+.Pp
+Send a "RESERVE" command to the device to place a reservation on it.
+.Pp
.Nm reset
.Pp
Reset the device. This command is only supported for devices which
support the
.Li SCIOCRESET
ioctl.
+.Pp
+.Nm reset
+.Pp
+Reset the SCSI bus. This command is only supported if the host adapter
+supports the
+.Li SCBUSIORESET
+ioctl.
+.Pp
+.Nm start
+.Pp
+Send a "START" command to the device. This is useful typically only for
+disk devices.
+.Pp
+.Nm stop
+.Pp
+Send a "STOP" command to the device. This is useful typically only for
+disk devices.
+.Pp
+.Nm tur
+.Pp
+Send a "TEST UNIT READY" command to the device. This is useful for generating
+current device status.
.Sh BUS COMMANDS
The following commands are supported for SCSI busses:
.Pp
diff -r ab3d15e36703 -r 4d10fdb32ff4 sbin/scsictl/scsictl.c
--- a/sbin/scsictl/scsictl.c Wed Jun 26 15:29:43 2002 +0000
+++ b/sbin/scsictl/scsictl.c Wed Jun 26 16:04:11 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: scsictl.c,v 1.15 2002/04/14 03:24:42 tsutsui Exp $ */
+/* $NetBSD: scsictl.c,v 1.16 2002/06/26 16:04:14 mjacob Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -79,13 +79,23 @@
void device_format __P((int, char *[]));
void device_identify __P((int, char *[]));
void device_reassign __P((int, char *[]));
+void device_release __P((int, char *[]));
+void device_reserve __P((int, char *[]));
void device_reset __P((int, char *[]));
+void device_start __P((int, char *[]));
+void device_stop __P((int, char *[]));
+void device_tur __P((int, char *[]));
struct command device_commands[] = {
- { "format", "", device_format },
+ { "format", "[blocksize [immediate]]", device_format },
{ "identify", "", device_identify },
{ "reassign", "blkno [blkno [...]]", device_reassign },
+ { "release", "", device_release },
+ { "reserve", "", device_reserve },
{ "reset", "", device_reset },
+ { "start", "", device_start },
+ { "stop", "", device_stop },
+ { "tur", "", device_tur },
{ NULL, NULL, NULL },
};
@@ -193,39 +203,193 @@
* device_format:
*
* Format a direct access device.
- *
- * XXX Does not handle defect list management or geometry settings.
*/
void
device_format(argc, argv)
int argc;
char *argv[];
{
+ u_int32_t blksize;
+ int i, j, immediate;
+#define PC (65536/10)
+ static int complete[] = {
+ PC*1, PC*2, PC*3, PC*4, PC*5, PC*6, PC*7, PC*8, PC*9, 65536
+ };
+ char *cp, buffer[64];
+ struct scsipi_sense_data sense;
struct scsi_format_unit cmd;
struct {
+ struct scsi_format_unit_defect_list_header header;
+ /* optional initialization pattern */
+ /* optional defect list */
+ } dfl;
+ struct {
struct scsipi_mode_header header;
struct scsi_blk_desc blk_desc;
struct page_disk_format format_page;
- } data;
+ } mode_page;
+ struct {
+ struct scsipi_mode_header header;
+ struct scsi_blk_desc blk_desc;
+ } data_select;
+
+
+ /* Blocksize is an optional argument. */
+ if (argc > 2)
+ usage();
- /* No arguments. */
- if (argc != 0)
- usage();
+ /*
+ * Loop doing Request Sense to clear any pending Unit Attention.
+ *
+ * Multiple conditions may exist on the drive which are returned
+ * in priority order.
+ */
+ for (i = 0; i < 8; i++) {
+ scsi_request_sense(fd, &sense, sizeof (sense));
+ if ((j = sense.flags & SSD_KEY) == SKEY_NO_SENSE)
+ break;
+ }
+ /*
+ * Make sure we cleared any pending Unit Attention
+ */
+ if (j != SKEY_NO_SENSE) {
+ cp = scsi_decode_sense((const unsigned char *) &sense, 2,
+ buffer, sizeof (buffer));
+ errx(1, "failed to clean Unit Attention: %s\n", cp);
+ }
/*
* Get the DISK FORMAT mode page. SCSI-2 recommends specifying the
* interleave read from this page in the FORMAT UNIT command.
*/
- scsi_mode_sense(fd, 0x03, 0x00, &data, sizeof(data));
+ scsi_mode_sense(fd, 0x03, 0x00, &mode_page, sizeof(mode_page));
+
+ j = (mode_page.format_page.bytes_s[0] << 8) |
+ (mode_page.format_page.bytes_s[1]);
+
+ if (j != DEV_BSIZE)
+ printf("current disk sector size: %hd\n", j);
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = SCSI_FORMAT_UNIT;
- memcpy(cmd.interleave, data.format_page.interleave,
+ memcpy(cmd.interleave, mode_page.format_page.interleave,
sizeof(cmd.interleave));
- scsi_command(fd, &cmd, sizeof(cmd), NULL, 0, 6 * 60 * 60 * 1000, 0);
+ /*
+ * The blocksize on the device is only changed if the user
+ * specified a new blocksize. If not specified the blocksize
+ * used for the device will be the Default value in the device.
+ * We don't specify the number of blocks since the format
+ * command will always reformat the entire drive. Also by
+ * not specifying a block count the drive will reset the
+ * block count to the maximum available after the format
+ * completes if the blocksize was changed in the format.
+ * Finally, the new disk geometry will not but updated on
+ * the drive in permanent storage until _AFTER_ the format
+ * completes successfully.
+ */
+ if (argc > 0) {
+ blksize = strtoul(argv[0], &cp, 10);
+ if (*cp != '\0')
+ errx(1, "invalid block size: %s\n", argv[0]);
+
+ memset(&data_select, 0, sizeof(data_select));
Home |
Main Index |
Thread Index |
Old Index