summaryrefslogtreecommitdiffstats
path: root/sbin/atacontrol
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2002-03-27 10:59:53 +0000
committersos <sos@FreeBSD.org>2002-03-27 10:59:53 +0000
commit143359e9171b057813b73ea2e1fcb78f82dc2845 (patch)
tree1c719763284ac0282eb26162f42c875093bb3d45 /sbin/atacontrol
parent3bb9163271874f3cdba2326c16e8f35837a58e79 (diff)
downloadFreeBSD-src-143359e9171b057813b73ea2e1fcb78f82dc2845.zip
FreeBSD-src-143359e9171b057813b73ea2e1fcb78f82dc2845.tar.gz
Add support for creating/deleting ATA RAID's
Sponsored by: Advanis
Diffstat (limited to 'sbin/atacontrol')
-rw-r--r--sbin/atacontrol/atacontrol.836
-rw-r--r--sbin/atacontrol/atacontrol.c207
2 files changed, 161 insertions, 82 deletions
diff --git a/sbin/atacontrol/atacontrol.8 b/sbin/atacontrol/atacontrol.8
index 1b46de9..6d8bd53 100644
--- a/sbin/atacontrol/atacontrol.8
+++ b/sbin/atacontrol/atacontrol.8
@@ -34,7 +34,7 @@
.Sh SYNOPSIS
.Nm
.Aq Ar command
-.Ar channel Op Ar args
+.Ar args
.Pp
.Nm
.Ic attach
@@ -46,6 +46,12 @@
.Ic reinit
.Ar channel
.Nm
+.Ic create
+.Ar type [interleave] disk0 ... diskN
+.Nm
+.Ic delete
+.Ar raid
+.Nm
.Ic rebuild
.Ar raid
.Nm
@@ -56,6 +62,9 @@
.Ic info
.Ar channel
.Nm
+.Ic cap
+.Ar channel device
+.Nm
.Ic list
.Sh DESCRIPTION
.Nm
@@ -92,6 +101,24 @@ initialized to the parameters the ATA driver has stored internally.
Devices that has gone bad and no longer responds to the probe, or devices
that has physically been removed are removed from the kernel.
Likewise are devices that show up during a reset, probed and attached.
+.It Ic create
+Create a
+.Ar type
+ATA RAID. The Type can be RAID0 (stripe), RAID1 (mirror), RAID0+1 or
+SPAN (JBOD). In case the RAID has a RAID0 component the
+.Ar interleave
+must be specified in number of sectors. The RAID will be created
+of the individual disks named
+.Ar disk0 ... diskN.
+.Pp
+Allthough the ATA driver allows for creating an ATA RAID on disks on any
+controller, there are restrictions. It is only possible to boot on
+an array if its either located on a "real" ATA RAID controller like
+the Promise or Highpoint controllers, or if the RAID declared is of
+RAID1 or SPAN type, in case of a SPAN the partition to boot must
+reside on the first disk in the SPAN.
+.It Ic delete
+Deletes a RAID array on a RAID capable ATA controller.
.It Ic rebuild
Rebuild a RAID1 array on a RAID capable ATA controller.
.It Ic mode
@@ -113,8 +140,11 @@ and the mode will remain unchanged.
.It Ic info
Show info about the attached devices on the
.Ar channel ,
-currently only the device
-name and manufacture/version strings are shown.
+the device name and manufacture/version strings are shown.
+.It Ic cap
+Show detailed info about the device on
+.Ar channel device
+where device is 0 for master and 1 for slave.
.It Ic list
Show info about all attached devices on all active controllers.
.El
diff --git a/sbin/atacontrol/atacontrol.c b/sbin/atacontrol/atacontrol.c
index f6be451..e339a25 100644
--- a/sbin/atacontrol/atacontrol.c
+++ b/sbin/atacontrol/atacontrol.c
@@ -106,68 +106,77 @@ param_print(struct ata_params *parm)
}
void
-aparam_print(struct ata_params *parm)
+cap_print(struct ata_params *parm)
{
- printf(" disk model name %.40s\n", parm->model);
- printf(" firmware revision %.8s\n", parm->revision);
- printf(" ata / atapi revision %d\n", version(parm->version_major));
-
- printf(" number of cylinders %d\n", parm->cylinders);
- printf(" number of heads %d\n", parm->heads);
- printf(" sectors per track %d\n", parm->sectors);
+ printf("\n");
+ printf("ATA/ATAPI revision %d\n", version(parm->version_major));
+ printf("device model %.40s\n", parm->model);
+ printf("firmware revision %.8s\n", parm->revision);
+
+ printf("cylinders %d\n", parm->cylinders);
+ printf("heads %d\n", parm->heads);
+ printf("sectors/track %d\n", parm->sectors);
- printf(" lba support %s\n", parm->support_lba ? "yes" : "no");
- printf(" lba sectors %d\n", parm->lba_size);
- printf(" dma support %s\n", parm->support_dma ? "yes" : "no");
- printf(" queueing support %s\n", parm->support_queueing ? "yes" : "no");
- if(parm->support_queueing)
- printf(" length %d\n", parm->queuelen);
-
- printf(" SMART support %s\n", parm->support.smart ? "yes" : "no");
- if(parm->support.smart)
- printf(" enabled %s\n", parm->enabled.smart ? "yes" : "no");
-
- printf(" security support %s\n", parm->support.smart ? "yes" : "no");
- if(parm->support.smart)
- printf(" enabled %s\n", parm->enabled.smart ? "yes" : "no");
-
- printf(" power management support %s\n", parm->support.power_mngt ? "yes" : "no");
- if(parm->support.power_mngt)
- printf(" enabled %s\n", parm->enabled.power_mngt ? "yes" : "no");
-
- printf(" write cache support %s\n", parm->support.write_cache ? "yes" : "no");
- if(parm->support.write_cache)
- printf(" enabled %s\n", parm->enabled.write_cache ? "yes" : "no");
-
- printf(" look ahead support %s\n", parm->support.look_ahead ? "yes" : "no");
- if(parm->support.look_ahead)
- printf(" enabled %s\n", parm->enabled.look_ahead ? "yes" : "no");
-
- printf(" microcode download support %s\n", parm->support.microcode ? "yes" : "no");
- if(parm->support.microcode)
- printf(" enabled %s\n", parm->enabled.microcode ? "yes" : "no");
-
- printf(" rd/wr dma queued support %s\n", parm->support.queued ? "yes" : "no");
- if(parm->support.queued)
- printf(" enabled %s\n", parm->enabled.queued ? "yes" : "no");
-
- printf(" advanced power management support %s\n", parm->support.apm ? "yes" : "no");
- if(parm->support.apm)
- {
- printf(" enabled %s\n", parm->enabled.apm ? "yes" : "no");
- printf(" value %d / 0x%02x\n", parm->apm_value, parm->apm_value);
- }
- printf(" automatic acoustic management support %s\n", parm->support.auto_acoustic ? "yes" : "no");
- if(parm->support.auto_acoustic)
- {
- printf(" enabled %s\n", parm->enabled.auto_acoustic ? "yes" : "no");
- printf(" automatic acoustic management current value %d / 0x%02x\n", parm->current_acoustic, parm->current_acoustic);
- printf(" recommended value %d / 0x%02x\n", parm->vendor_acoustic, parm->vendor_acoustic);
- }
+ printf("lba%ssupported ", parm->support_lba ? " " : " not ");
+ if (parm->lba_size)
+ printf("%d sectors\n", parm->lba_size);
+ else
+ printf("\n");
+
+ printf("lba48%ssupported ", parm->support.address48 ? " " : " not ");
+ if (parm->lba_size48)
+ printf("%lld sectors\n", parm->lba_size48);
+ else
+ printf("\n");
+ printf("dma%ssupported\n", parm->support_dma ? " " : " not");
+
+ printf("overlap%ssupported\n", parm->support_queueing ? " " : " not ");
+
+ printf("\nFeature Support Enable Value Vendor\n");
+
+ printf("write cache %s %s\n",
+ parm->support.write_cache ? "yes" : "no",
+ parm->enabled.write_cache ? "yes" : "no");
+
+ printf("read ahead %s %s\n",
+ parm->support.look_ahead ? "yes" : "no",
+ parm->enabled.look_ahead ? "yes" : "no");
+
+ printf("dma queued %s %s %d/%02X\n",
+ parm->support.queued ? "yes" : "no",
+ parm->enabled.queued ? "yes" : "no",
+ parm->queuelen, parm->queuelen);
+
+ printf("SMART %s %s\n",
+ parm->support.smart ? "yes" : "no",
+ parm->enabled.smart ? "yes" : "no");
+
+ printf("microcode download %s %s\n",
+ parm->support.microcode ? "yes" : "no",
+ parm->enabled.microcode ? "yes" : "no");
+
+ printf("security %s %s\n",
+ parm->support.smart ? "yes" : "no",
+ parm->enabled.smart ? "yes" : "no");
+
+ printf("power management %s %s\n",
+ parm->support.power_mngt ? "yes" : "no",
+ parm->enabled.power_mngt ? "yes" : "no");
+
+ printf("advanced power management %s %s %d/%02X\n",
+ parm->support.apm ? "yes" : "no",
+ parm->enabled.apm ? "yes" : "no",
+ parm->apm_value, parm->apm_value);
+
+ printf("automatic acoustic management %s %s %d/%02X %d/%02X\n",
+ parm->support.auto_acoustic ? "yes" : "no",
+ parm->enabled.auto_acoustic ? "yes" : "no",
+ parm->current_acoustic, parm->current_acoustic,
+ parm->vendor_acoustic, parm->vendor_acoustic);
}
int
-ata_params_print(int fd, int channel, int master)
+ata_cap_print(int fd, int channel, int device)
{
struct ata_cmd iocmd;
@@ -180,20 +189,14 @@ ata_params_print(int fd, int channel, int master)
if (ioctl(fd, IOCATA, &iocmd) < 0)
return errno;
- if(master)
- master = 1;
- master = !master;
-
- printf("ATA channel %d, %s", channel, master==0 ? "Master" : "Slave");
+ printf("ATA channel %d, %s", channel, device==0 ? "Master" : "Slave");
- if (iocmd.u.param.type[master]) {
- printf(", device %s:\n", iocmd.u.param.name[master]);
- aparam_print(&iocmd.u.param.params[master]);
+ if (iocmd.u.param.type[device]) {
+ printf(", device %s:\n", iocmd.u.param.name[device]);
+ cap_print(&iocmd.u.param.params[device]);
}
else
- {
printf(": no device present\n");
- }
return 0;
}
@@ -231,7 +234,6 @@ int
main(int argc, char **argv)
{
struct ata_cmd iocmd;
- int master;
int fd;
if ((fd = open("/dev/ata", O_RDWR)) < 0)
@@ -242,17 +244,23 @@ main(int argc, char **argv)
bzero(&iocmd, sizeof(struct ata_cmd));
- if (argc > 2) {
+ if (argc > 2 && strcmp(argv[1], "create")) {
int chan;
- if (!(sscanf(argv[2], "%d", &chan) == 1 ||
- sscanf(argv[2], "ata%d", &chan) == 1))
- usage();
+
+ if (!strcmp(argv[1], "delete") ||
+ !strcmp(argv[1], "rebuild")) {
+ if (!(sscanf(argv[2], "%d", &chan) == 1 ||
+ sscanf(argv[2], "ar%d", &chan) == 1))
+ usage();
+ }
+ else {
+ if (!(sscanf(argv[2], "%d", &chan) == 1 ||
+ sscanf(argv[2], "ata%d", &chan) == 1))
+ usage();
+ }
iocmd.channel = chan;
}
- if (argc > 3)
- master = atoi(argv[3]);
-
if (!strcmp(argv[1], "list") && argc == 2) {
int unit = 0;
@@ -261,8 +269,8 @@ main(int argc, char **argv)
else if (!strcmp(argv[1], "info") && argc == 3) {
info_print(fd, iocmd.channel, 0);
}
- else if (!strcmp(argv[1], "parm") && argc == 4) {
- ata_params_print(fd, iocmd.channel, master);
+ else if (!strcmp(argv[1], "cap") && argc == 4) {
+ ata_cap_print(fd, iocmd.channel, atoi(argv[3]));
}
else if (!strcmp(argv[1], "detach") && argc == 3) {
iocmd.cmd = ATADETACH;
@@ -282,9 +290,50 @@ main(int argc, char **argv)
info_print(fd, iocmd.channel, 0);
}
else if (!strcmp(argv[1], "rebuild") && argc == 3) {
- iocmd.cmd = ATAREBUILD;
+ iocmd.cmd = ATARAIDREBUILD;
+ if (ioctl(fd, IOCATA, &iocmd) < 0)
+ warn("ioctl(ATARAIDREBUILD)");
+ }
+ else if (!strcmp(argv[1], "delete") && argc == 3) {
+ iocmd.cmd = ATARAIDDELETE;
+ if (ioctl(fd, IOCATA, &iocmd) < 0)
+ warn("ioctl(ATARAIDDELETE)");
+ }
+ else if (!strcmp(argv[1], "create")) {
+ int disk, dev, offset;
+
+ iocmd.cmd = ATARAIDCREATE;
+ if (!strcmp(argv[2], "RAID0") || !strcmp(argv[2], "stripe"))
+ iocmd.u.raid_setup.type = 1;
+ if (!strcmp(argv[2], "RAID1") || !strcmp(argv[2],"mirror"))
+ iocmd.u.raid_setup.type = 2;
+ if (!strcmp(argv[2], "RAID0+1"))
+ iocmd.u.raid_setup.type = 3;
+ if (!strcmp(argv[2], "SPAN") || !strcmp(argv[2], "JBOD"))
+ iocmd.u.raid_setup.type = 4;
+ if (!iocmd.u.raid_setup.type)
+ usage();
+
+ if (iocmd.u.raid_setup.type & 1) {
+ if (!sscanf(argv[3], "%d",
+ &iocmd.u.raid_setup.interleave) == 1)
+ usage();
+ offset = 4;
+ }
+ else
+ offset = 3;
+
+ for (disk = 0; disk < 16 && (offset + disk) < argc; disk++) {
+ if (!(sscanf(argv[offset + disk], "%d", &dev) == 1 ||
+ sscanf(argv[offset + disk], "ad%d", &dev) == 1))
+ usage();
+ iocmd.u.raid_setup.disks[disk] = dev;
+ }
+ iocmd.u.raid_setup.total_disks = disk;
if (ioctl(fd, IOCATA, &iocmd) < 0)
- warn("ioctl(ATAREBUILD)");
+ warn("ioctl(ATARAIDCREATE)");
+ else
+ printf("ar%d created\n", iocmd.u.raid_setup.unit);
}
else if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 5)) {
if (argc == 5) {
OpenPOWER on IntegriCloud