--- sys/sys/ata.h	2007/11/15 16:29:33	1.36.2.1
+++ sys/sys/ata.h	2008/03/17 10:33:23	1.39
@@ -23,7 +23,7 @@
  * (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: src/sys/sys/ata.h,v 1.36.2.1 2007/11/15 16:29:33 scottl Exp $
+ * $FreeBSD: src/sys/sys/ata.h,v 1.39 2008/03/17 10:33:23 phk Exp $
  */
 
 #ifndef _SYS_ATA_H_
@@ -38,6 +38,7 @@ struct ata_params {
 #define ATA_PROTO_ATAPI                 0x8000
 #define ATA_PROTO_ATAPI_12              0x8000
 #define ATA_PROTO_ATAPI_16              0x8001
+#define ATA_PROTO_CFA                   0x848a
 #define ATA_ATAPI_TYPE_MASK             0x1f00
 #define ATA_ATAPI_TYPE_DIRECT           0x0000  /* disk/floppy */
 #define ATA_ATAPI_TYPE_TAPE             0x0100  /* streaming tape */
@@ -432,6 +433,9 @@ struct ata_ioc_request {
 #define IOCATAGMODE             _IOR('a', 102, int)
 #define IOCATASMODE             _IOW('a', 103, int)
 
+#define IOCATAGSPINDOWN		_IOR('a', 104, int)
+#define IOCATASSPINDOWN		_IOW('a', 105, int)
+
 
 struct ata_ioc_raid_config {
 	    int                 lun;
--- sys/dev/ata/ata-all.c	2007/10/04 19:17:15	1.280
+++ sys/dev/ata/ata-all.c	2008/03/17 10:33:23	1.281
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/ata/ata-all.c,v 1.280 2007/10/04 19:17:15 sos Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/ata/ata-all.c,v 1.281 2008/03/17 10:33:23 phk Exp $");
 
 #include "opt_ata.h"
 #include <sys/param.h>
@@ -514,6 +514,12 @@ ata_device_ioctl(device_t dev, u_long cm
     case IOCATAGMODE:
 	*mode = atadev->mode;
 	return 0;
+    case IOCATASSPINDOWN:
+	atadev->spindown = *mode;
+	return 0;
+    case IOCATAGSPINDOWN:
+	*mode = atadev->spindown;
+	return 0;
     default:
 	return ENOTTY;
     }
--- sys/dev/ata/ata-all.h	2008/01/09 08:54:47	1.124.2.2
+++ sys/dev/ata/ata-all.h	2008/03/17 10:33:23	1.128
@@ -23,7 +23,7 @@
  * (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: src/sys/dev/ata/ata-all.h,v 1.124.2.2 2008/01/09 08:54:47 delphij Exp $
+ * $FreeBSD: src/sys/dev/ata/ata-all.h,v 1.128 2008/03/17 10:33:23 phk Exp $
  */
 
 /* ATA register defines */
@@ -403,6 +403,9 @@ struct ata_device {
     struct ata_params           param;          /* ata param structure */
     int                         mode;           /* current transfermode */
     u_int32_t                   max_iosize;     /* max IO size */
+    int				spindown;	/* idle spindown timeout */
+    struct callout              spindown_timer;
+    int                         spindown_state;
     int                         flags;
 #define         ATA_D_USE_CHS           0x0001
 #define         ATA_D_MEDIA_CHANGED     0x0002
@@ -579,56 +582,34 @@ MALLOC_DECLARE(M_ATA);
 
 /* macros to hide busspace uglyness */
 #define ATA_INB(res, offset) \
-	bus_space_read_1(rman_get_bustag((res)), \
-			 rman_get_bushandle((res)), (offset))
+	bus_read_1((res), (offset))
 
 #define ATA_INW(res, offset) \
-	bus_space_read_2(rman_get_bustag((res)), \
-			 rman_get_bushandle((res)), (offset))
+	bus_read_2((res), (offset))
 #define ATA_INL(res, offset) \
-	bus_space_read_4(rman_get_bustag((res)), \
-			 rman_get_bushandle((res)), (offset))
+	bus_read_4((res), (offset))
 #define ATA_INSW(res, offset, addr, count) \
-	bus_space_read_multi_2(rman_get_bustag((res)), \
-			       rman_get_bushandle((res)), \
-			       (offset), (addr), (count))
+	bus_read_multi_2((res), (offset), (addr), (count))
 #define ATA_INSW_STRM(res, offset, addr, count) \
-	bus_space_read_multi_stream_2(rman_get_bustag((res)), \
-				      rman_get_bushandle((res)), \
-				      (offset), (addr), (count))
+	bus_read_multi_stream_2((res), (offset), (addr), (count))
 #define ATA_INSL(res, offset, addr, count) \
-	bus_space_read_multi_4(rman_get_bustag((res)), \
-			       rman_get_bushandle((res)), \
-			       (offset), (addr), (count))
+	bus_read_multi_4((res), (offset), (addr), (count))
 #define ATA_INSL_STRM(res, offset, addr, count) \
-	bus_space_read_multi_stream_4(rman_get_bustag((res)), \
-				      rman_get_bushandle((res)), \
-				      (offset), (addr), (count))
+	bus_read_multi_stream_4((res), (offset), (addr), (count))
 #define ATA_OUTB(res, offset, value) \
-	bus_space_write_1(rman_get_bustag((res)), \
-			  rman_get_bushandle((res)), (offset), (value))
+	bus_write_1((res), (offset), (value))
 #define ATA_OUTW(res, offset, value) \
-	bus_space_write_2(rman_get_bustag((res)), \
-			  rman_get_bushandle((res)), (offset), (value))
+	bus_write_2((res), (offset), (value))
 #define ATA_OUTL(res, offset, value) \
-	bus_space_write_4(rman_get_bustag((res)), \
-			  rman_get_bushandle((res)), (offset), (value))
+	bus_write_4((res), (offset), (value))
 #define ATA_OUTSW(res, offset, addr, count) \
-	bus_space_write_multi_2(rman_get_bustag((res)), \
-				rman_get_bushandle((res)), \
-				(offset), (addr), (count))
+	bus_write_multi_2((res), (offset), (addr), (count))
 #define ATA_OUTSW_STRM(res, offset, addr, count) \
-	bus_space_write_multi_stream_2(rman_get_bustag((res)), \
-				       rman_get_bushandle((res)), \
-				       (offset), (addr), (count))
+	bus_write_multi_stream_2((res), (offset), (addr), (count))
 #define ATA_OUTSL(res, offset, addr, count) \
-	bus_space_write_multi_4(rman_get_bustag((res)), \
-				rman_get_bushandle((res)), \
-				(offset), (addr), (count))
+	bus_write_multi_4((res), (offset), (addr), (count))
 #define ATA_OUTSL_STRM(res, offset, addr, count) \
-	bus_space_write_multi_stream_4(rman_get_bustag((res)), \
-				       rman_get_bushandle((res)), \
-				       (offset), (addr), (count))
+	bus_write_multi_stream_4((res), (offset), (addr), (count))
 
 #define ATA_IDX_INB(ch, idx) \
 	ATA_INB(ch->r_io[idx].res, ch->r_io[idx].offset)
--- sys/dev/ata/ata-disk.c	2007/12/09 19:26:56	1.204.2.1
+++ sys/dev/ata/ata-disk.c	2008/03/17 10:33:23	1.207
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/ata/ata-disk.c,v 1.204.2.1 2007/12/09 19:26:56 delphij Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/ata/ata-disk.c,v 1.207 2008/03/17 10:33:23 phk Exp $");
 
 #include "opt_ata.h"
 #include <sys/param.h>
@@ -162,12 +162,17 @@ ad_attach(device_t dev)
     adp->disk->d_unit = device_get_unit(dev);
     if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
 	adp->disk->d_flags = DISKFLAG_CANFLUSHCACHE;
+    if ((atadev->param.support.command2 & ATA_SUPPORT_CFA) ||
+	atadev->param.config == ATA_PROTO_CFA)
+	adp->disk->d_flags = DISKFLAG_CANDELETE;
     snprintf(adp->disk->d_ident, sizeof(adp->disk->d_ident), "ad:%s",
 	atadev->param.serial);
     disk_create(adp->disk, DISK_VERSION);
     device_add_child(dev, "subdisk", device_get_unit(dev));
     ad_firmware_geom_adjust(dev, adp->disk);
     bus_generic_attach(dev);
+
+    callout_init(&atadev->spindown_timer, 1);
     return 0;
 }
 
@@ -175,6 +180,7 @@ static int
 ad_detach(device_t dev)
 {
     struct ad_softc *adp = device_get_ivars(dev);
+    struct ata_device *atadev = device_get_softc(dev);
     device_t *children;
     int nchildren, i;
 
@@ -182,6 +188,9 @@ ad_detach(device_t dev)
     if (!device_get_ivars(dev))
 	return ENXIO;
     
+    /* destroy the power timeout */
+    callout_drain(&atadev->spindown_timer);
+
     /* detach & delete all children */
     if (!device_get_children(dev, &children, &nchildren)) {
 	for (i = 0; i < nchildren; i++)
@@ -226,6 +235,38 @@ ad_reinit(device_t dev)
     return 0;
 }
 
+static void
+ad_power_callback(struct ata_request *request)
+{
+    device_printf(request->dev, "drive spun down.\n");
+    ata_free_request(request);
+}
+
+static void
+ad_spindown(void *priv)
+{
+    device_t dev = priv;
+    struct ata_device *atadev = device_get_softc(dev);
+    struct ata_request *request;
+
+    if(atadev->spindown == 0)
+	return;
+    device_printf(dev, "Idle, spin down\n");
+    atadev->spindown_state = 1;
+    if (!(request = ata_alloc_request())) {
+	device_printf(dev, "FAILURE - out of memory in ad_spindown\n");
+	return;
+    }
+    request->flags = ATA_R_CONTROL;
+    request->dev = dev;
+    request->timeout = 5;
+    request->retries = 1;
+    request->callback = ad_power_callback;
+    request->u.ata.command = ATA_STANDBY_IMMEDIATE;
+    ata_queue_request(request);
+}
+
+
 static void 
 ad_strategy(struct bio *bp)
 {
@@ -233,6 +274,10 @@ ad_strategy(struct bio *bp)
     struct ata_device *atadev = device_get_softc(dev);
     struct ata_request *request;
 
+    if (atadev->spindown != 0)
+	callout_reset(&atadev->spindown_timer, hz * atadev->spindown,
+	    ad_spindown, dev);
+
     if (!(request = ata_alloc_request())) {
 	device_printf(dev, "FAILURE - out of memory in start\n");
 	biofinish(bp, NULL, ENOMEM);
@@ -243,7 +288,13 @@ ad_strategy(struct bio *bp)
     request->dev = dev;
     request->bio = bp;
     request->callback = ad_done;
-    request->timeout = 5;
+    if (atadev->spindown_state) {
+	device_printf(dev, "request while spun down, starting.\n");
+	atadev->spindown_state = 0;
+	request->timeout = 31;
+    } else {
+	request->timeout = 5;
+    }
     request->retries = 2;
     request->data = bp->bio_data;
     request->bytecount = bp->bio_bcount;
@@ -274,6 +325,12 @@ ad_strategy(struct bio *bp)
 	else
 	    request->u.ata.command = ATA_WRITE;
 	break;
+    case BIO_DELETE:
+	request->flags = ATA_R_CONTROL;
+	request->u.ata.command = ATA_CFA_ERASE;
+	request->transfersize = 0;
+	request->donecount = bp->bio_bcount;
+	break;
     case BIO_FLUSH:
 	request->u.ata.lba = 0;
 	request->u.ata.count = 0;
--- sys/dev/ata/ata-disk.h	2007/02/21 19:07:18	1.52
+++ sys/dev/ata/ata-disk.h	2008/03/17 10:33:23	1.53
@@ -23,7 +23,7 @@
  * (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: src/sys/dev/ata/ata-disk.h,v 1.52 2007/02/21 19:07:18 sos Exp $
+ * $FreeBSD: src/sys/dev/ata/ata-disk.h,v 1.53 2008/03/17 10:33:23 phk Exp $
  */
 
 /* structure describing an ATA disk */
@@ -34,7 +34,7 @@ struct ad_softc {  
     u_int32_t                   transfersize;   /* size of each transfer */
     int                         num_tags;       /* number of tags supported */
     int                         flags;          /* drive flags */
-#define         AD_F_LABELLING          0x0001          
+#define         AD_F_LABELLING          0x0001
 #define         AD_F_CHS_USED           0x0002
 #define         AD_F_32B_ENABLED        0x0004
 #define         AD_F_TAG_ENABLED        0x0008
--- sbin/atacontrol/atacontrol.8	2007/12/02 08:49:23	1.28.2.1
+++ sbin/atacontrol/atacontrol.8	2008/03/17 10:33:23	1.30
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/sbin/atacontrol/atacontrol.8,v 1.28.2.1 2007/12/02 08:49:23 remko Exp $
+.\" $FreeBSD: src/sbin/atacontrol/atacontrol.8,v 1.30 2008/03/17 10:33:23 phk Exp $
 .\"
 .Dd November 28, 2007
 .Dt ATACONTROL 8
@@ -70,6 +70,10 @@
 .Ic cap
 .Ar device
 .Nm
+.Ic spindown
+.Ar device
+.Op Ar seconds
+.Nm
 .Ic list
 .Sh DESCRIPTION
 The
@@ -190,6 +194,10 @@ The device name and manufacture/version 
 .It Ic cap
 Show detailed info about the device on
 .Ar device .
+.It Ic spindown
+Set or report timeout after which the
+.Ar device 
+will be spun down.
 .It Ic info
 Show info about the attached devices on the
 .Ar channel .
--- sbin/atacontrol/atacontrol.c	2007/08/13 18:46:31	1.43
+++ sbin/atacontrol/atacontrol.c	2008/03/17 10:33:23	1.47
@@ -23,7 +23,7 @@
  * (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: src/sbin/atacontrol/atacontrol.c,v 1.43 2007/08/13 18:46:31 jhb Exp $
+ * $FreeBSD: src/sbin/atacontrol/atacontrol.c,v 1.47 2008/03/17 10:33:23 phk Exp $
  */
 
 #include <sys/types.h>
@@ -38,16 +38,7 @@
 #include <string.h>
 #include <sysexits.h>
 
-const char *mode2str(int mode);
-int str2mode(char *str);
-void usage(void);
-int version(int ver);
-void param_print(struct ata_params *parm);
-void cap_print(struct ata_params *parm);
-int ata_cap_print(int fd);
-int info_print(int fd, int channel, int prchan);
-
-const char *
+static const char *
 mode2str(int mode)
 {
 	switch (mode) {
@@ -72,7 +63,7 @@ mode2str(int mode)
 	}
 }
 
-int
+static int
 str2mode(char *str)
 {
 	if (!strcasecmp(str, "BIOSPIO")) return ATA_PIO;
@@ -94,8 +85,8 @@ str2mode(char *str)
 	return -1;
 }
 
-void
-usage()
+static void
+usage(void)
 {
 	fprintf(stderr,
 		"usage:  atacontrol <command> args:\n"
@@ -111,11 +102,12 @@ usage()
 		"        atacontrol status array\n"
 		"        atacontrol mode device [mode]\n"
 		"        atacontrol cap device\n"
+		"        atacontrol spindown device [seconds]\n"
 	);
 	exit(EX_USAGE);
 }
 
-int
+static int
 version(int ver)
 {
 	int bit;
@@ -128,7 +120,7 @@ version(int ver)
 	return 0;
 }
 
-void
+static void
 param_print(struct ata_params *parm)
 {
 	printf("<%.40s/%.8s> ", parm->model, parm->revision);
@@ -144,7 +136,7 @@ param_print(struct ata_params *parm)
 		printf("ATA/ATAPI revision %d\n", version(parm->version_major));
 }
 
-void
+static void
 cap_print(struct ata_params *parm)
 {
 	u_int32_t lbasize = (u_int32_t)parm->lba_size_1 |
@@ -175,6 +167,10 @@ cap_print(struct ata_params *parm)
 	printf("heads                 %d\n", parm->heads);
 	printf("sectors/track         %d\n", parm->sectors);
 
+	if (parm->config == ATA_PROTO_CFA ||
+	    (parm->support.command2 & ATA_SUPPORT_CFA))
+		printf("CFA supported\n");
+
 	printf("lba%ssupported         ",
 		parm->capabilities1 & ATA_SUPPORT_LBA ? " " : " not ");
 	if (lbasize)
@@ -252,18 +248,17 @@ cap_print(struct ata_params *parm)
 		ATA_ACOUSTIC_VENDOR(parm->acoustic));
 }
 
-int
+static void
 ata_cap_print(int fd)
 {
 	struct ata_params params;
 
 	if (ioctl(fd, IOCATAGPARM, &params) < 0)
-		return errno;
+		err(1, "ioctl(IOCATAGPARM)");
 	cap_print(&params);
-	return 0;
 }
 
-int
+static void
 info_print(int fd, int channel, int prchan)
 {
 	struct ata_ioc_devices devices;
@@ -271,7 +266,7 @@ info_print(int fd, int channel, int prch
 	devices.channel = channel;
 
 	if (ioctl(fd, IOCATADEVICES, &devices) < 0)
-		return errno;
+		err(1, "ioctl(IOCATADEVICES)");
 
 	if (prchan)
 		printf("ATA channel %d:\n", channel);
@@ -289,32 +284,81 @@ info_print(int fd, int channel, int prch
 	}
 	else
 		printf("     no device present\n");
-	return 0;
+}
+
+static void
+ata_spindown(int fd, const char *dev, const char *arg)
+{
+	int tmo;
+
+	if (arg != NULL) {
+		tmo = strtoul(arg, NULL, 0);
+		if (ioctl(fd, IOCATASSPINDOWN, &tmo) < 0)
+			err(1, "ioctl(IOCATASSPINDOWN)");
+	} else {
+		if (ioctl(fd, IOCATAGSPINDOWN, &tmo) < 0)
+			err(1, "ioctl(IOCATAGSPINDOWN)");
+		if (tmo == 0)
+			printf("%s: idle spin down disabled\n", dev);
+		else
+			printf("%s: spin down after %d seconds idle\n",
+			    dev, tmo);
+	}
+}
+
+static int
+open_dev(const char *arg, int mode)
+{
+	int disk, fd;
+	char device[64];
+
+	if (!(sscanf(arg, "ad%d", &disk) == 1 ||
+	      sscanf(arg, "acd%d", &disk) == 1 ||
+	      sscanf(arg, "afd%d", &disk) == 1 ||
+	      sscanf(arg, "ast%d", &disk) == 1)) {
+		fprintf(stderr, "atacontrol: Invalid device %s\n", arg);
+		exit(EX_USAGE);
+	}
+	sprintf(device, "/dev/%s", arg);
+	if ((fd = open(device, mode)) < 0)
+		err(1, "device not found");
+	return (fd);
+}
+
+static int
+ar_arg(const char *arg)
+{
+	int array;
+
+	if (!(sscanf(arg, "ar%d", &array) == 1)) {
+		fprintf(stderr, "atacontrol: Invalid array %s\n", arg);
+		exit(EX_USAGE);
+	}
+	return (array);
+}
+
+static int
+ata_arg(const char *arg)
+{
+	int channel;
+
+	if (!(sscanf(arg, "ata%d", &channel) == 1)) {
+		fprintf(stderr, "atacontrol: Invalid channel %s\n", arg);
+		exit(EX_USAGE);
+	}
+	return (channel);
 }
 
 int
 main(int argc, char **argv)
 {
-	int fd;
+	int fd, mode, channel, array;
 
 	if (argc < 2)
 		usage();
 
 	if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 4)) {
-		int disk, mode;
-		char device[64];
-
-		if (!(sscanf(argv[2], "ad%d", &disk) == 1 ||
-		      sscanf(argv[2], "acd%d", &disk) == 1 ||
-		      sscanf(argv[2], "afd%d", &disk) == 1 ||
-		      sscanf(argv[2], "ast%d", &disk) == 1)) {
-			fprintf(stderr, "atacontrol: Invalid device %s\n",
-				argv[2]);
-			exit(EX_USAGE);
-		}
-		sprintf(device, "/dev/%s", argv[2]);
-		if ((fd = open(device, O_RDONLY)) < 0)
-			err(1, "device not found");
+		fd = open_dev(argv[2], O_RDONLY);
 		if (argc == 4) {
 			mode = str2mode(argv[3]);
 			if (ioctl(fd, IOCATASMODE, &mode) < 0)
@@ -328,29 +372,22 @@ main(int argc, char **argv)
 		exit(EX_OK);
 	}
 	if (!strcmp(argv[1], "cap") && argc == 3) {
-		int disk;
-		char device[64];
-
-		if (!(sscanf(argv[2], "ad%d", &disk) == 1 ||
-		      sscanf(argv[2], "acd%d", &disk) == 1 ||
-		      sscanf(argv[2], "afd%d", &disk) == 1 ||
-		      sscanf(argv[2], "ast%d", &disk) == 1)) {
-			fprintf(stderr, "atacontrol: Invalid device %s\n",
-				argv[2]);
-			exit(EX_USAGE);
-		}
-		sprintf(device, "/dev/%s", argv[2]);
-		if ((fd = open(device, O_RDONLY)) < 0)
-			err(1, "device not found");
+		fd = open_dev(argv[2], O_RDONLY);
 		ata_cap_print(fd);
 		exit(EX_OK);
 	}
 
+	if (!strcmp(argv[1], "spindown") && (argc == 3 || argc == 4)) {
+		fd = open_dev(argv[2], O_RDONLY);
+		ata_spindown(fd, argv[2], argv[3]);
+		exit(EX_OK);
+	}
+
 	if ((fd = open("/dev/ata", O_RDWR)) < 0)
 		err(1, "control device not found");
 
 	if (!strcmp(argv[1], "list") && argc == 2) {
-		int maxchannel, channel;
+		int maxchannel;
 
 		if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0)
 			err(1, "ioctl(IOCATAGMAXCHANNEL)");
@@ -359,49 +396,25 @@ main(int argc, char **argv)
 		exit(EX_OK);
 	}
 	if (!strcmp(argv[1], "info") && argc == 3) {
-		int channel;
-
-		if (!(sscanf(argv[2], "ata%d", &channel) == 1)) {
-			fprintf(stderr,
-				"atacontrol: Invalid channel %s\n", argv[2]);
-                        exit(EX_USAGE);
-		}
+		channel = ata_arg(argv[2]);
 		info_print(fd, channel, 0);
 		exit(EX_OK);
 	}
 	if (!strcmp(argv[1], "detach") && argc == 3) {
-		int channel;
-
-		if (!(sscanf(argv[2], "ata%d", &channel) == 1)) {
-			fprintf(stderr,
-				"atacontrol: Invalid channel %s\n", argv[2]);
-                        exit(EX_USAGE);
-		}
+		channel = ata_arg(argv[2]);
 		if (ioctl(fd, IOCATADETACH, &channel) < 0)
 			err(1, "ioctl(IOCATADETACH)");
 		exit(EX_OK);
 	}
 	if (!strcmp(argv[1], "attach") && argc == 3) {
-		int channel;
-
-		if (!(sscanf(argv[2], "ata%d", &channel) == 1)) {
-			fprintf(stderr,
-				"atacontrol: Invalid channel %s\n", argv[2]);
-                        exit(EX_USAGE);
-		}
+		channel = ata_arg(argv[2]);
 		if (ioctl(fd, IOCATAATTACH, &channel) < 0)
 			err(1, "ioctl(IOCATAATTACH)");
 		info_print(fd, channel, 0);
 		exit(EX_OK);
 	}
 	if (!strcmp(argv[1], "reinit") && argc == 3) {
-		int channel;
-
-		if (!(sscanf(argv[2], "ata%d", &channel) == 1)) {
-			fprintf(stderr,
-				"atacontrol: Invalid channel %s\n", argv[2]);
-                        exit(EX_USAGE);
-		}
+		channel = ata_arg(argv[2]);
 		if (ioctl(fd, IOCATAREINIT, &channel) < 0)
 			warn("ioctl(IOCATAREINIT)");
 		info_print(fd, channel, 0);
@@ -479,13 +492,7 @@ main(int argc, char **argv)
 		exit(EX_OK);
 	}
 	if (!strcmp(argv[1], "delete") && argc == 3) {
-		int array;
-
-		if (!(sscanf(argv[2], "ar%d", &array) == 1)) {
-			fprintf(stderr,
-				"atacontrol: Invalid array %s\n", argv[2]);
-                        exit(EX_USAGE);
-		}
+		array = ar_arg(argv[2]);
 		if (ioctl(fd, IOCATARAIDDELETE, &array) < 0)
 			warn("ioctl(IOCATARAIDDELETE)");
 		exit(EX_OK);
@@ -493,11 +500,7 @@ main(int argc, char **argv)
 	if (!strcmp(argv[1], "addspare") && argc == 4) {
 		struct ata_ioc_raid_config config;
 
-		if (!(sscanf(argv[2], "ar%d", &config.lun) == 1)) {
-			fprintf(stderr,
-				"atacontrol: Invalid array %s\n", argv[2]);
-			usage();
-		}
+		config.lun = ar_arg(argv[2]);
 		if (!(sscanf(argv[3], "ad%d", &config.disks[0]) == 1)) {
 			fprintf(stderr,
 				"atacontrol: Invalid disk %s\n", argv[3]);
@@ -508,13 +511,7 @@ main(int argc, char **argv)
 		exit(EX_OK);
 	}
 	if (!strcmp(argv[1], "rebuild") && argc == 3) {
-		int array;
-
-		if (!(sscanf(argv[2], "ar%d", &array) == 1)) {
-			fprintf(stderr,
-				"atacontrol: Invalid array %s\n", argv[2]);
-			usage();
-		}
+		array = ar_arg(argv[2]);
 		if (ioctl(fd, IOCATARAIDREBUILD, &array) < 0)
 			warn("ioctl(IOCATARAIDREBUILD)");
 		else {
@@ -531,11 +528,7 @@ main(int argc, char **argv)
 		struct ata_ioc_raid_status status;
 		int i, lun, state;
 
-		if (!(sscanf(argv[2], "ar%d", &status.lun) == 1)) {
-			fprintf(stderr,
-				"atacontrol: Invalid array %s\n", argv[2]);
-			usage();
-		}
+		status.lun = ar_arg(argv[2]);
 		if (ioctl(fd, IOCATARAIDSTATUS, &status) < 0)
 			err(1, "ioctl(IOCATARAIDSTATUS)");
 
@@ -555,6 +548,7 @@ main(int argc, char **argv)
 			break;
 		case AR_JBOD:
 			printf("JBOD");
+			break;
 		case AR_SPAN:
 			printf("SPAN");
 			break;
