1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-01-18 15:30:21 +00:00

Change the way ioctls are issue to ATA.

The most prominent part is that its now possible to issue ata_requests
directly to say acd0, instead of going through the cumbersome /dev/ata
device.
This commit is contained in:
Søren Schmidt 2005-05-16 13:07:27 +00:00
parent b0c77ed9fb
commit 6667b30d15
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=146266
13 changed files with 962 additions and 966 deletions

View File

@ -46,7 +46,7 @@ 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 channel, int device);
int ata_cap_print(int fd);
int info_print(int fd, int channel, int prchan);
const char *
@ -95,7 +95,21 @@ str2mode(char *str)
void
usage()
{
fprintf(stderr, "usage: atacontrol <command> channel [args]\n");
fprintf(stderr,
"usage: atacontrol <command> args:\n"
" atacontrol list\n"
" atacontrol info channel\n"
" atacontrol attach channel\n"
" atacontrol detach channel\n"
" atacontrol reinit channel\n"
" atacontrol create type [interleave] disk0 ... diskN\n"
" atacontrol delete channel\n"
" atacontrol addspare array disk\n"
" atacontrol rebuild array\n"
" atacontrol status array\n"
" atacontrol mode device [mode]\n"
" atacontrol cap device\n"
);
exit(EX_USAGE);
}
@ -187,7 +201,8 @@ cap_print(struct ata_params *parm)
parm->enabled.command1 & ATA_SUPPORT_LOOKAHEAD ? "yes" : "no");
if (parm->satacapabilities && parm->satacapabilities != 0xffff) {
printf("Native Command Queuing (NCQ) %s %s %d/0x%02X\n",
printf("Native Command Queuing (NCQ) %s %s"
" %d/0x%02X\n",
parm->satacapabilities & ATA_SUPPORT_NCQ ?
"yes" : "no", " -",
(parm->satacapabilities & ATA_SUPPORT_NCQ) ?
@ -232,57 +247,39 @@ cap_print(struct ata_params *parm)
}
int
ata_cap_print(int fd, int channel, int device)
ata_cap_print(int fd)
{
struct ata_cmd iocmd;
struct ata_params params;
if (device < 0 || device > 1)
return ENXIO;
bzero(&iocmd, sizeof(struct ata_cmd));
iocmd.channel = channel;
iocmd.device = device;
iocmd.cmd = ATAGPARM;
if (ioctl(fd, IOCATA, &iocmd) < 0)
if (ioctl(fd, IOCATAGPARM, &params) < 0)
return errno;
printf("ATA channel %d, %s", channel, device==0 ? "Master" : "Slave");
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");
cap_print(&params);
return 0;
}
int
info_print(int fd, int channel, int prchan)
{
struct ata_cmd iocmd;
struct ata_ioc_devices devices;
bzero(&iocmd, sizeof(struct ata_cmd));
iocmd.channel = channel;
iocmd.device = -1;
iocmd.cmd = ATAGPARM;
if (ioctl(fd, IOCATA, &iocmd) < 0)
devices.channel = channel;
if (ioctl(fd, IOCATADEVICES, &devices) < 0)
return errno;
if (prchan)
printf("ATA channel %d:\n", channel);
printf("%sMaster: ", prchan ? " " : "");
if (iocmd.u.param.type[0]) {
printf("%4.4s ", iocmd.u.param.name[0]);
param_print(&iocmd.u.param.params[0]);
if (*devices.name[0]) {
printf("%4.4s ", devices.name[0]);
param_print(&devices.params[0]);
}
else
printf(" no device present\n");
printf("%sSlave: ", prchan ? " " : "");
if (iocmd.u.param.type[1]) {
printf("%4.4s ", iocmd.u.param.name[1]);
param_print(&iocmd.u.param.params[1]);
if (*devices.name[1]) {
printf("%4.4s ", devices.name[1]);
param_print(&devices.params[1]);
}
else
printf(" no device present\n");
@ -292,118 +289,158 @@ info_print(int fd, int channel, int prchan)
int
main(int argc, char **argv)
{
struct ata_cmd iocmd;
int fd, maxunit, unit;
if ((fd = open("/dev/ata", O_RDWR)) < 0)
err(1, "control device not found");
int fd;
if (argc < 2)
usage();
bzero(&iocmd, sizeof(struct ata_cmd));
if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 4)) {
int disk, mode;
char device[64];
if (argc > 2 && strcmp(argv[1], "create")) {
int chan;
if (!strcmp(argv[1], "addspare") ||
!strcmp(argv[1], "delete") ||
!strcmp(argv[1], "rebuild") ||
!strcmp(argv[1], "status")) {
if (!(sscanf(argv[2], "%d", &chan) == 1 ||
sscanf(argv[2], "ar%d", &chan) == 1)) {
fprintf(stderr, "atacontrol: Invalid RAID device\n");
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_RDWR)) < 0)
err(1, "device not found");
if (argc == 4) {
mode = str2mode(argv[3]);
if (ioctl(fd, IOCATASMODE, &mode) < 0)
warn("ioctl(IOCATASMODE)");
}
else {
if (!(sscanf(argv[2], "%d", &chan) == 1 ||
sscanf(argv[2], "ata%d", &chan) == 1)) {
fprintf(stderr, "atacontrol: Invalid ATA channel\n");
if (argc == 3 || argc == 4) {
if (ioctl(fd, IOCATAGMODE, &mode) < 0)
err(1, "ioctl(IOCATAGMODE)");
printf("current mode = %s\n", mode2str(mode));
}
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_RDWR)) < 0)
err(1, "device not found");
ata_cap_print(fd);
exit(EX_OK);
}
iocmd.channel = chan;
}
if ((fd = open("/dev/ata", O_RDWR)) < 0)
err(1, "control device not found");
if (!strcmp(argv[1], "list") && argc == 2) {
iocmd.cmd = ATAGMAXCHANNEL;
if (ioctl(fd, IOCATA, &iocmd) < 0)
err(1, "ioctl(ATAGMAXCHANNEL)");
maxunit = iocmd.u.maxchan;
for (unit = 0; unit < maxunit; unit++)
info_print(fd, unit, 1);
}
else if (!strcmp(argv[1], "info") && argc == 3) {
info_print(fd, iocmd.channel, 0);
}
else if (!strcmp(argv[1], "cap") && argc == 4) {
ata_cap_print(fd, iocmd.channel, atoi(argv[3]));
}
else if (!strcmp(argv[1], "enclosure") && argc == 4) {
iocmd.device = atoi(argv[3]);
iocmd.cmd = ATAENCSTAT;
if (ioctl(fd, IOCATA, &iocmd) < 0)
err(1, "ioctl(ATAENCSTAT)");
printf("fan RPM: %d temp: %.1f 5V: %.2f 12V: %.2f\n",
iocmd.u.enclosure.fan,
(double)iocmd.u.enclosure.temp / 10,
(double)iocmd.u.enclosure.v05 / 1000,
(double)iocmd.u.enclosure.v12 / 1000);
}
else if (!strcmp(argv[1], "detach") && argc == 3) {
iocmd.cmd = ATADETACH;
if (ioctl(fd, IOCATA, &iocmd) < 0)
err(1, "ioctl(ATADETACH)");
}
else if (!strcmp(argv[1], "attach") && argc == 3) {
iocmd.cmd = ATAATTACH;
if (ioctl(fd, IOCATA, &iocmd) < 0)
err(1, "ioctl(ATAATTACH)");
info_print(fd, iocmd.channel, 0);
}
else if (!strcmp(argv[1], "reinit") && argc == 3) {
iocmd.cmd = ATAREINIT;
if (ioctl(fd, IOCATA, &iocmd) < 0)
warn("ioctl(ATAREINIT)");
info_print(fd, iocmd.channel, 0);
}
else if (!strcmp(argv[1], "create")) {
int disk, dev, offset;
int maxchannel, channel;
iocmd.cmd = ATARAIDCREATE;
if (ioctl(fd, IOCATAGMAXCHANNEL, &maxchannel) < 0)
err(1, "ioctl(IOCATAGMAXCHANNEL)");
for (channel = 0; channel < maxchannel; channel++)
info_print(fd, channel, 1);
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[3]);
exit(EX_USAGE);
}
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[3]);
exit(EX_USAGE);
}
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[3]);
exit(EX_USAGE);
}
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[3]);
exit(EX_USAGE);
}
if (ioctl(fd, IOCATAREINIT, &channel) < 0)
warn("ioctl(IOCATAREINIT)");
info_print(fd, channel, 0);
exit(EX_OK);
}
if (!strcmp(argv[1], "create")) {
int disk, dev, offset;
struct ata_ioc_raid_config config;
bzero(&config, sizeof(config));
if (argc > 2) {
if (!strcasecmp(argv[2], "RAID0") ||
!strcasecmp(argv[2], "stripe"))
iocmd.u.raid_setup.type = AR_RAID0;
config.type = AR_RAID0;
if (!strcasecmp(argv[2], "RAID1") ||
!strcasecmp(argv[2],"mirror"))
iocmd.u.raid_setup.type = AR_RAID1;
config.type = AR_RAID1;
if (!strcasecmp(argv[2], "RAID0+1") ||
!strcasecmp(argv[2],"RAID10"))
iocmd.u.raid_setup.type = AR_RAID01;
config.type = AR_RAID01;
if (!strcasecmp(argv[2], "RAID5"))
iocmd.u.raid_setup.type = AR_RAID5;
config.type = AR_RAID5;
if (!strcasecmp(argv[2], "SPAN"))
iocmd.u.raid_setup.type = AR_SPAN;
config.type = AR_SPAN;
if (!strcasecmp(argv[2], "JBOD"))
iocmd.u.raid_setup.type = AR_JBOD;
config.type = AR_JBOD;
}
if (!iocmd.u.raid_setup.type) {
fprintf(stderr, "atacontrol: Invalid RAID type\n");
if (!config.type) {
fprintf(stderr, "atacontrol: Invalid RAID type %s\n",
argv[2]);
fprintf(stderr, "atacontrol: Valid RAID types: \n");
fprintf(stderr, " RAID0 | stripe | RAID1 | mirror "
"| RAID0+1 | SPAN | JBOD\n");
fprintf(stderr, " stripe | mirror | "
"RAID0 | RAID1 | RAID0+1 | RAID5 | "
"SPAN | JBOD\n");
exit(EX_USAGE);
}
if (iocmd.u.raid_setup.type == AR_RAID0 ||
iocmd.u.raid_setup.type == AR_RAID01 ||
iocmd.u.raid_setup.type == AR_RAID5) {
if (config.type == AR_RAID0 ||
config.type == AR_RAID01 ||
config.type == AR_RAID5) {
if (argc < 4 ||
!sscanf(argv[3], "%d",
&iocmd.u.raid_setup.interleave) == 1) {
fprintf(stderr, "atacontrol: Invalid interleave\n");
!sscanf(argv[3], "%d", &config.interleave) == 1) {
fprintf(stderr,
"atacontrol: Invalid interleave %s\n",
argv[3]);
exit(EX_USAGE);
}
offset = 4;
@ -412,82 +449,98 @@ main(int argc, char **argv)
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)) {
if (!(sscanf(argv[offset + disk], "ad%d", &dev) == 1)) {
fprintf(stderr,
"atacontrol: Invalid device %s\n",
"atacontrol: Invalid disk %s\n",
argv[offset + disk]);
exit(EX_USAGE);
}
iocmd.u.raid_setup.disks[disk] = dev;
config.disks[disk] = dev;
}
if(disk < 2) {
if ((config.type == AR_RAID1 || config.type == AR_RAID01) &&
disk < 2) {
fprintf(stderr, "atacontrol: At least 2 disks must be "
"specified to create RAID\n");
"specified\n");
exit(EX_USAGE);
}
iocmd.u.raid_setup.total_disks = disk;
if (ioctl(fd, IOCATA, &iocmd) < 0)
err(1, "ioctl(ATARAIDCREATE)");
config.total_disks = disk;
if (ioctl(fd, IOCATARAIDCREATE, &config) < 0)
err(1, "ioctl(IOCATARAIDCREATE)");
else
printf("ar%d created\n", iocmd.u.raid_setup.unit);
printf("ar%d created\n", config.lun);
exit(EX_OK);
}
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], "addspare") && argc == 4) {
int dev;
if (!strcmp(argv[1], "delete") && argc == 3) {
int array;
iocmd.cmd = ATARAIDADDSPARE;
if (!(sscanf(argv[3], "%d", &dev) == 1 ||
sscanf(argv[3], "ad%d", &dev) == 1)) {
if (!(sscanf(argv[2], "ar%d", &array) == 1)) {
fprintf(stderr,
"atacontrol: Invalid device %s\n", argv[3]);
"atacontrol: Invalid array %s\n", argv[3]);
exit(EX_USAGE);
}
if (ioctl(fd, IOCATARAIDDELETE, &array) < 0)
warn("ioctl(IOCATARAIDDELETE)");
exit(EX_OK);
}
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[3]);
usage();
}
iocmd.u.raid_spare.disk = dev;
if (ioctl(fd, IOCATA, &iocmd) < 0)
warn("ioctl(ATARAIDADDSPARE)");
if (!(sscanf(argv[3], "ad%d", &config.disks[0]) == 1)) {
fprintf(stderr,
"atacontrol: Invalid disk %s\n", argv[3]);
usage();
}
else if (!strcmp(argv[1], "rebuild") && argc == 3) {
iocmd.cmd = ATARAIDREBUILD;
if (ioctl(fd, IOCATA, &iocmd) < 0)
warn("ioctl(ATARAIDREBUILD)");
if (ioctl(fd, IOCATARAIDADDSPARE, &config) < 0)
warn("ioctl(IOCATARAIDADDSPARE)");
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[3]);
usage();
}
if (ioctl(fd, IOCATARAIDREBUILD, &array) < 0)
warn("ioctl(IOCATARAIDREBUILD)");
else {
char buffer[128];
sprintf(buffer, "/usr/bin/nice -n 20 /bin/dd "
"if=/dev/ar%d of=/dev/null bs=1m &",
iocmd.channel);
array);
if (system(buffer))
warn("background dd");
}
exit(EX_OK);
}
else if (!strcmp(argv[1], "status") && argc == 3) {
if (!strcmp(argv[1], "status") && argc == 3) {
struct ata_ioc_raid_config config;
int i;
iocmd.cmd = ATARAIDSTATUS;
if (ioctl(fd, IOCATA, &iocmd) < 0)
err(1, "ioctl(ATARAIDSTATUS)");
printf("ar%d: ATA ", iocmd.channel);
switch (iocmd.u.raid_status.type) {
if (ioctl(fd, IOCATARAIDSTATUS, &config) < 0)
err(1, "ioctl(IOCATARAIDSTATUS)");
printf("ar%d: ATA ", config.lun);
switch (config.type) {
case AR_RAID0:
printf("RAID0 stripesize=%d",
iocmd.u.raid_status.interleave);
printf("RAID0 stripesize=%d", config.interleave);
break;
case AR_RAID1:
printf("RAID1");
break;
case AR_RAID01:
printf("RAID0+1 stripesize=%d",
iocmd.u.raid_status.interleave);
printf("RAID0+1 stripesize=%d", config.interleave);
break;
case AR_RAID5:
printf("RAID5 stripesize=%d",
iocmd.u.raid_status.interleave);
printf("RAID5 stripesize=%d", config.interleave);
break;
case AR_JBOD:
printf("JBOD");
@ -496,14 +549,14 @@ main(int argc, char **argv)
break;
}
printf(" subdisks: ");
for (i = 0; i < iocmd.u.raid_status.total_disks; i++) {
if (iocmd.u.raid_status.disks[i] >= 0)
printf("ad%d ", iocmd.u.raid_status.disks[i]);
for (i = 0; i < config.total_disks; i++) {
if (config.disks[i] >= 0)
printf("ad%d ", config.disks[i]);
else
printf("DOWN ");
}
printf("status: ");
switch (iocmd.u.raid_status.status) {
switch (config.status) {
case AR_READY:
printf("READY\n");
break;
@ -512,32 +565,13 @@ main(int argc, char **argv)
break;
case AR_READY | AR_DEGRADED | AR_REBUILDING:
printf("REBUILDING %d%% completed\n",
iocmd.u.raid_status.progress);
config.progress);
break;
default:
printf("BROKEN\n");
}
exit(EX_OK);
}
else if (!strcmp(argv[1], "mode") && (argc == 3 || argc == 5)) {
if (argc == 5) {
iocmd.cmd = ATASMODE;
iocmd.device = -1;
iocmd.u.mode.mode[0] = str2mode(argv[3]);
iocmd.u.mode.mode[1] = str2mode(argv[4]);
if (ioctl(fd, IOCATA, &iocmd) < 0)
warn("ioctl(ATASMODE)");
}
if (argc == 3 || argc == 5) {
iocmd.cmd = ATAGMODE;
iocmd.device = -1;
if (ioctl(fd, IOCATA, &iocmd) < 0)
err(1, "ioctl(ATAGMODE)");
printf("Master = %s \nSlave = %s\n",
mode2str(iocmd.u.mode.mode[0]),
mode2str(iocmd.u.mode.mode[1]));
}
}
else
usage();
exit(EX_OK);
}

View File

@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h>
#endif
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-commands.h>
#include <ata_if.h>
/* device structure */
@ -75,7 +74,7 @@ static void bpack(int8_t *, int8_t *, int);
/* global vars */
MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer");
int (*ata_ioctl_func)(struct ata_cmd *iocmd) = NULL;
int (*ata_raid_ioctl_func)(u_long cmd, caddr_t data) = NULL;
devclass_t ata_devclass;
uma_zone_t ata_request_zone;
uma_zone_t ata_composite_zone;
@ -338,209 +337,167 @@ ata_interrupt(void *data)
* device related interfaces
*/
static int
ata_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
int32_t flag, struct thread *td)
{
struct ata_cmd *iocmd = (struct ata_cmd *)addr;
device_t *children, device = NULL;
struct ata_request *request;
caddr_t buf;
int nchildren, i;
int error = ENOTTY;
device_t device, *children;
struct ata_ioc_devices *devices = (struct ata_ioc_devices *)data;
int *value = (int *)data;
int i, nchildren, error = ENOTTY;
if (cmd != IOCATA)
return ENOTSUP;
if (iocmd->cmd == ATAGMAXCHANNEL) {
iocmd->u.maxchan = devclass_get_maxunit(ata_devclass);
return 0;
}
if (iocmd->channel < 0 ||
iocmd->channel >= devclass_get_maxunit(ata_devclass)) {
switch (cmd) {
case IOCATAGMAXCHANNEL:
*value = devclass_get_maxunit(ata_devclass);
error = 0;
break;
case IOCATAREINIT:
if (*value > devclass_get_maxunit(ata_devclass) ||
!(device = devclass_get_device(ata_devclass, *value)))
return ENXIO;
}
if (!(device = devclass_get_device(ata_devclass, iocmd->channel)))
return ENXIO;
switch (iocmd->cmd) {
case ATAGPARM:
if (!device_get_children(device, &children, &nchildren)) {
struct ata_channel *ch;
if (!(ch = device_get_softc(device)))
return ENXIO;
iocmd->u.param.type[0] =
ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER);
iocmd->u.param.type[1] =
ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE);
for (i = 0; i < nchildren; i++) {
if (children[i] && device_is_attached(children[i])) {
struct ata_device *atadev = device_get_softc(children[i]);
if (atadev->unit == ATA_MASTER) {
strcpy(iocmd->u.param.name[0],
device_get_nameunit(children[i]));
bcopy(&atadev->param, &iocmd->u.param.params[0],
sizeof(struct ata_params));
}
if (atadev->unit == ATA_SLAVE) {
strcpy(iocmd->u.param.name[1],
device_get_nameunit(children[i]));
bcopy(&atadev->param, &iocmd->u.param.params[1],
sizeof(struct ata_params));
}
}
}
free(children, M_TEMP);
error = 0;
}
else
error = ENXIO;
break;
case ATAGMODE:
if (!device_get_children(device, &children, &nchildren)) {
for (i = 0; i < nchildren; i++) {
if (children[i] && device_is_attached(children[i])) {
struct ata_device *atadev = device_get_softc(children[i]);
atadev = device_get_softc(children[i]);
if (atadev->unit == ATA_MASTER)
iocmd->u.mode.mode[0] = atadev->mode;
if (atadev->unit == ATA_SLAVE)
iocmd->u.mode.mode[1] = atadev->mode;
}
free(children, M_TEMP);
}
error = 0;
}
else
error = ENXIO;
break;
case ATASMODE:
if (!device_get_children(device, &children, &nchildren)) {
for (i = 0; i < nchildren; i++) {
if (children[i] && device_is_attached(children[i])) {
struct ata_device *atadev = device_get_softc(children[i]);
if (atadev->unit == ATA_MASTER) {
atadev->mode = iocmd->u.mode.mode[0];
ATA_SETMODE(device, children[i]);
iocmd->u.mode.mode[0] = atadev->mode;
}
if (atadev->unit == ATA_SLAVE) {
atadev->mode = iocmd->u.mode.mode[1];
ATA_SETMODE(device, children[i]);
iocmd->u.mode.mode[1] = atadev->mode;
}
}
}
free(children, M_TEMP);
error = 0;
}
else
error = ENXIO;
break;
case ATAREQUEST:
if (!device_get_children(device, &children, &nchildren)) {
for (i = 0; i < nchildren; i++) {
if (children[i] && device_is_attached(children[i])) {
struct ata_device *atadev = device_get_softc(children[i]);
if (ATA_DEV(atadev->unit) == iocmd->device) {
if (!(buf = malloc(iocmd->u.request.count,
M_ATA, M_NOWAIT))) {
error = ENOMEM;
break;
}
if (!(request = ata_alloc_request())) {
error = ENOMEM;
free(buf, M_ATA);
break;
}
if (iocmd->u.request.flags & ATA_CMD_WRITE) {
error = copyin(iocmd->u.request.data, buf,
iocmd->u.request.count);
if (error) {
free(buf, M_ATA);
ata_free_request(request);
break;
}
}
request->dev = atadev->dev;
if (iocmd->u.request.flags & ATA_CMD_ATAPI) {
request->flags = ATA_R_ATAPI;
bcopy(iocmd->u.request.u.atapi.ccb,
request->u.atapi.ccb, 16);
}
else {
request->u.ata.command =
iocmd->u.request.u.ata.command;
request->u.ata.feature =
iocmd->u.request.u.ata.feature;
request->u.ata.lba = iocmd->u.request.u.ata.lba;
request->u.ata.count = iocmd->u.request.u.ata.count;
}
request->timeout = iocmd->u.request.timeout;
request->data = buf;
request->bytecount = iocmd->u.request.count;
request->transfersize = request->bytecount;
if (iocmd->u.request.flags & ATA_CMD_CONTROL)
request->flags |= ATA_R_CONTROL;
if (iocmd->u.request.flags & ATA_CMD_READ)
request->flags |= ATA_R_READ;
if (iocmd->u.request.flags & ATA_CMD_WRITE)
request->flags |= ATA_R_WRITE;
ata_queue_request(request);
if (!(request->flags & ATA_R_ATAPI)) {
iocmd->u.request.u.ata.command =
request->u.ata.command;
iocmd->u.request.u.ata.feature =
request->u.ata.feature;
iocmd->u.request.u.ata.lba = request->u.ata.lba;
iocmd->u.request.u.ata.count = request->u.ata.count;
}
iocmd->u.request.error = request->result;
if (iocmd->u.request.flags & ATA_CMD_READ)
error = copyout(buf, iocmd->u.request.data,
iocmd->u.request.count);
else
error = 0;
free(buf, M_ATA);
ata_free_request(request);
break;
}
}
}
free(children, M_TEMP);
}
else
error = ENXIO;
break;
case ATAREINIT:
error = ata_reinit(device);
ata_start(device);
break;
case ATAATTACH:
case IOCATAATTACH:
if (*value > devclass_get_maxunit(ata_devclass) ||
!(device = devclass_get_device(ata_devclass, *value)))
return ENXIO;
/* XXX SOS should enable channel HW on controller */
error = ata_attach(device);
break;
case ATADETACH:
case IOCATADETACH:
if (*value > devclass_get_maxunit(ata_devclass) ||
!(device = devclass_get_device(ata_devclass, *value)))
return ENXIO;
error = ata_detach(device);
/* XXX SOS should disable channel HW on controller */
break;
case IOCATADEVICES:
if (devices->channel > devclass_get_maxunit(ata_devclass) ||
!(device = devclass_get_device(ata_devclass, devices->channel)))
return ENXIO;
bzero(devices->name[0], 32);
bzero(&devices->params[0], sizeof(struct ata_params));
bzero(devices->name[1], 32);
bzero(&devices->params[1], sizeof(struct ata_params));
if (!device_get_children(device, &children, &nchildren)) {
for (i = 0; i < nchildren; i++) {
if (children[i] && device_is_attached(children[i])) {
struct ata_device *atadev = device_get_softc(children[i]);
if (atadev->unit == ATA_MASTER) {
strncpy(devices->name[0],
device_get_nameunit(children[i]), 32);
bcopy(&atadev->param, &devices->params[0],
sizeof(struct ata_params));
}
if (atadev->unit == ATA_SLAVE) {
strncpy(devices->name[1],
device_get_nameunit(children[i]), 32);
bcopy(&atadev->param, &devices->params[1],
sizeof(struct ata_params));
}
}
}
free(children, M_TEMP);
error = 0;
}
else
error = ENODEV;
break;
default:
if (ata_ioctl_func)
error = ata_ioctl_func(iocmd);
if (ata_raid_ioctl_func)
error = ata_raid_ioctl_func(cmd, data);
}
return error;
}
int
ata_device_ioctl(device_t dev, u_long cmd, caddr_t data)
{
struct ata_device *atadev = device_get_softc(dev);
struct ata_ioc_request *ioc_request = (struct ata_ioc_request *)data;
struct ata_params *params = (struct ata_params *)data;
int *mode = (int *)data;
struct ata_request *request;
caddr_t buf;
int error;
switch (cmd) {
case IOCATAREQUEST:
if (!(buf = malloc(ioc_request->count, M_ATA, M_NOWAIT))) {
return ENOMEM;
}
if (!(request = ata_alloc_request())) {
free(buf, M_ATA);
return ENOMEM;
}
if (ioc_request->flags & ATA_CMD_WRITE) {
error = copyin(ioc_request->data, buf, ioc_request->count);
if (error) {
free(buf, M_ATA);
ata_free_request(request);
return error;
}
}
request->dev = dev;
if (ioc_request->flags & ATA_CMD_ATAPI) {
request->flags = ATA_R_ATAPI;
bcopy(ioc_request->u.atapi.ccb, request->u.atapi.ccb, 16);
}
else {
request->u.ata.command = ioc_request->u.ata.command;
request->u.ata.feature = ioc_request->u.ata.feature;
request->u.ata.lba = ioc_request->u.ata.lba;
request->u.ata.count = ioc_request->u.ata.count;
}
request->timeout = ioc_request->timeout;
request->data = buf;
request->bytecount = ioc_request->count;
request->transfersize = request->bytecount;
if (ioc_request->flags & ATA_CMD_CONTROL)
request->flags |= ATA_R_CONTROL;
if (ioc_request->flags & ATA_CMD_READ)
request->flags |= ATA_R_READ;
if (ioc_request->flags & ATA_CMD_WRITE)
request->flags |= ATA_R_WRITE;
ata_queue_request(request);
if (!(request->flags & ATA_R_ATAPI)) {
ioc_request->u.ata.command = request->u.ata.command;
ioc_request->u.ata.feature = request->u.ata.feature;
ioc_request->u.ata.lba = request->u.ata.lba;
ioc_request->u.ata.count = request->u.ata.count;
}
ioc_request->error = request->result;
if (ioc_request->flags & ATA_CMD_READ)
error = copyout(buf, ioc_request->data, ioc_request->count);
else
error = 0;
free(buf, M_ATA);
ata_free_request(request);
return error;
case IOCATAGPARM:
bcopy(&atadev->param, params, sizeof(struct ata_params));
return 0;
case IOCATASMODE:
atadev->mode = *mode;
ATA_SETMODE(device_get_parent(dev), dev);
return 0;
case IOCATAGMODE:
*mode = atadev->mode;
return 0;
default:
return ENOTTY;
}
}
static void
ata_boot_attach(void)
{
@ -572,12 +529,7 @@ ata_add_child(device_t parent, struct ata_device *atadev, int unit)
device_t child;
if ((child = device_add_child(parent, NULL, unit))) {
char buffer[64];
device_set_softc(child, atadev);
sprintf(buffer, "%.40s/%.8s",
atadev->param.model, atadev->param.revision);
device_set_desc_copy(child, buffer);
device_quiet(child);
atadev->dev = child;
atadev->max_iosize = DEV_BSIZE;
@ -623,6 +575,7 @@ ata_getparam(device_t parent, struct ata_device *atadev)
if (!error && (isprint(atadev->param.model[0]) ||
isprint(atadev->param.model[1]))) {
struct ata_params *atacap = &atadev->param;
char buffer[64];
#if BYTE_ORDER == BIG_ENDIAN
int16_t *ptr;
@ -645,6 +598,8 @@ ata_getparam(device_t parent, struct ata_device *atadev)
bpack(atacap->revision, atacap->revision, sizeof(atacap->revision));
btrim(atacap->serial, sizeof(atacap->serial));
bpack(atacap->serial, atacap->serial, sizeof(atacap->serial));
sprintf(buffer, "%.40s/%.8s", atacap->model, atacap->revision);
device_set_desc_copy(atadev->dev, buffer);
if (bootverbose)
printf("ata%d-%s: pio=%s wdma=%s udma=%s cable=%s wire\n",
ch->unit, atadev->unit == ATA_MASTER ? "master":"slave",

View File

@ -521,7 +521,7 @@ struct ata_channel {
#define ATA_LED_MASK 0x03
/* externs */
extern int (*ata_ioctl_func)(struct ata_cmd *iocmd);
extern int (*ata_raid_ioctl_func)(u_long cmd, caddr_t data);
extern devclass_t ata_devclass;
extern int ata_wc;
@ -533,6 +533,7 @@ int ata_detach(device_t dev);
int ata_reinit(device_t dev);
int ata_suspend(device_t dev);
int ata_resume(device_t dev);
int ata_device_ioctl(device_t dev, u_long cmd, caddr_t data);
int ata_identify(device_t dev);
void ata_default_registers(device_t dev);
u_int8_t ata_modify_if_48bit(struct ata_request *request);

View File

@ -61,6 +61,7 @@ static void ad_done(struct ata_request *);
static void ad_describe(device_t dev);
static int ad_version(u_int16_t);
static disk_strategy_t ad_strategy;
static disk_ioctl_t ad_ioctl;
static dumper_t ad_dump;
/* local vars */
@ -137,6 +138,7 @@ ad_attach(device_t dev)
/* create the disk device */
adp->disk = disk_alloc();
adp->disk->d_strategy = ad_strategy;
adp->disk->d_ioctl = ad_ioctl;
adp->disk->d_dump = ad_dump;
adp->disk->d_name = "ad";
adp->disk->d_drv1 = dev;
@ -282,6 +284,12 @@ ad_done(struct ata_request *request)
ata_free_request(request);
}
static int
ad_ioctl(struct disk *disk, u_long cmd, void *data, int flag, struct thread *td)
{
return ata_device_ioctl(disk->d_drv1, cmd, data);
}
static int
ad_dump(void *arg, void *virtual, vm_offset_t physical,
off_t offset, size_t length)

View File

@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-commands.h>
#include <dev/ata/ata-pci.h>
#include <ata_if.h>

View File

@ -58,10 +58,10 @@ __FBSDID("$FreeBSD$");
/* prototypes */
static void ata_raid_done(struct ata_request *request);
static void ata_raid_config_changed(struct ar_softc *rdp, int writeback);
static int ata_raid_status(int array, struct raid_status *status);
static int ata_raid_create(struct raid_setup *setup);
static int ata_raid_status(struct ata_ioc_raid_config *config);
static int ata_raid_create(struct ata_ioc_raid_config *config);
static int ata_raid_delete(int array);
static int ata_raid_addspare(int array, int spare);
static int ata_raid_addspare(struct ata_ioc_raid_config *config);
static int ata_raid_rebuild(int array);
static int ata_raid_read_metadata(device_t subdisk);
static int ata_raid_write_metadata(struct ar_softc *rdp);
@ -184,29 +184,31 @@ ata_raid_attach(struct ar_softc *rdp, int writeback)
}
static int
ata_raid_ioctl(struct ata_cmd *iocmd)
ata_raid_ioctl(u_long cmd, caddr_t data)
{
struct ata_ioc_raid_config *config = (struct ata_ioc_raid_config *)data;
int *lun = (int *)data;
int error = EOPNOTSUPP;
switch (iocmd->cmd) {
case ATARAIDSTATUS:
error = ata_raid_status(iocmd->channel, &iocmd->u.raid_status);
switch (cmd) {
case IOCATARAIDSTATUS:
error = ata_raid_status(config);
break;
case ATARAIDCREATE:
error = ata_raid_create(&iocmd->u.raid_setup);
case IOCATARAIDCREATE:
error = ata_raid_create(config);
break;
case ATARAIDDELETE:
error = ata_raid_delete(iocmd->channel);
case IOCATARAIDDELETE:
error = ata_raid_delete(*lun);
break;
case ATARAIDADDSPARE:
error = ata_raid_addspare(iocmd->channel, iocmd->u.raid_spare.disk);
case IOCATARAIDADDSPARE:
error = ata_raid_addspare(config);
break;
case ATARAIDREBUILD:
error = ata_raid_rebuild(iocmd->channel);
case IOCATARAIDREBUILD:
error = ata_raid_rebuild(*lun);
break;
}
return error;
@ -806,30 +808,30 @@ ata_raid_config_changed(struct ar_softc *rdp, int writeback)
}
static int
ata_raid_status(int array, struct raid_status *status)
ata_raid_status(struct ata_ioc_raid_config *config)
{
struct ar_softc *rdp;
int i;
if (!(rdp = ata_raid_arrays[array]))
if (!(rdp = ata_raid_arrays[config->lun]))
return ENXIO;
status->type = rdp->type;
status->total_disks = rdp->total_disks;
config->type = rdp->type;
config->total_disks = rdp->total_disks;
for (i = 0; i < rdp->total_disks; i++ ) {
if ((rdp->disks[i].flags & AR_DF_PRESENT) && rdp->disks[i].dev)
status->disks[i] = device_get_unit(rdp->disks[i].dev);
config->disks[i] = device_get_unit(rdp->disks[i].dev);
else
status->disks[i] = -1;
config->disks[i] = -1;
}
status->interleave = rdp->interleave;
status->status = rdp->status;
status->progress = 100 * rdp->rebuild_lba / rdp->total_sectors;
config->interleave = rdp->interleave;
config->status = rdp->status;
config->progress = 100 * rdp->rebuild_lba / rdp->total_sectors;
return 0;
}
static int
ata_raid_create(struct raid_setup *setup)
ata_raid_create(struct ata_ioc_raid_config *config)
{
struct ar_softc *rdp;
device_t subdisk;
@ -849,14 +851,14 @@ ata_raid_create(struct raid_setup *setup)
return ENOMEM;
}
for (disk = 0; disk < setup->total_disks; disk++) {
for (disk = 0; disk < config->total_disks; disk++) {
if ((subdisk = devclass_get_device(ata_raid_sub_devclass,
setup->disks[disk]))) {
config->disks[disk]))) {
struct ata_raid_subdisk *ars = device_get_softc(subdisk);
/* is device already assigned to another array ? */
if (ars->raid) {
setup->disks[disk] = -1;
config->disks[disk] = -1;
free(rdp, M_AR);
return EBUSY;
}
@ -930,18 +932,18 @@ ata_raid_create(struct raid_setup *setup)
total_disks++;
}
else {
setup->disks[disk] = -1;
config->disks[disk] = -1;
free(rdp, M_AR);
return ENXIO;
}
}
if (total_disks != setup->total_disks) {
if (total_disks != config->total_disks) {
free(rdp, M_AR);
return ENODEV;
}
switch (setup->type) {
switch (config->type) {
case AR_T_JBOD:
case AR_T_SPAN:
case AR_T_RAID0:
@ -972,13 +974,13 @@ ata_raid_create(struct raid_setup *setup)
free(rdp, M_AR);
return EOPNOTSUPP;
}
rdp->type = setup->type;
rdp->type = config->type;
rdp->lun = array;
if (rdp->type == AR_T_RAID0 || rdp->type == AR_T_RAID01 ||
rdp->type == AR_T_RAID5) {
int bit = 0;
while (setup->interleave >>= 1)
while (config->interleave >>= 1)
bit++;
rdp->interleave = 1 << bit;
}
@ -1038,9 +1040,9 @@ ata_raid_create(struct raid_setup *setup)
rdp->status |= AR_S_READY;
/* we are committed to this array, grap the subdisks */
for (disk = 0; disk < setup->total_disks; disk++) {
for (disk = 0; disk < config->total_disks; disk++) {
if ((subdisk = devclass_get_device(ata_raid_sub_devclass,
setup->disks[disk]))) {
config->disks[disk]))) {
struct ata_raid_subdisk *ars = device_get_softc(subdisk);
ars->raid = rdp;
@ -1049,7 +1051,7 @@ ata_raid_create(struct raid_setup *setup)
}
ata_raid_attach(rdp, 1);
ata_raid_arrays[array] = rdp;
setup->unit = array;
config->lun = array;
return 0;
}
@ -1089,13 +1091,13 @@ ata_raid_delete(int array)
}
static int
ata_raid_addspare(int array, int spare)
ata_raid_addspare(struct ata_ioc_raid_config *config)
{
struct ar_softc *rdp;
device_t subdisk;
int disk;
if (!(rdp = ata_raid_arrays[array]))
if (!(rdp = ata_raid_arrays[config->lun]))
return ENXIO;
if (!(rdp->status & AR_S_DEGRADED) || !(rdp->status & AR_S_READY))
return ENXIO;
@ -1111,7 +1113,8 @@ ata_raid_addspare(int array, int spare)
(AR_DF_PRESENT | AR_DF_ONLINE)) && rdp->disks[disk].dev)
continue;
if ((subdisk = devclass_get_device(ata_raid_sub_devclass, spare ))){
if ((subdisk = devclass_get_device(ata_raid_sub_devclass,
config->disks[0] ))) {
struct ata_raid_subdisk *ars = device_get_softc(subdisk);
if (ars->raid)
@ -3136,7 +3139,7 @@ ata_raid_module_event_handler(module_t mod, int what, void *arg)
ata_raid_print_meta(rdp);
ata_raid_attach(rdp, 0);
}
ata_ioctl_func = ata_raid_ioctl;
ata_raid_ioctl_func = ata_raid_ioctl;
return 0;
case MOD_UNLOAD:
@ -3152,7 +3155,7 @@ ata_raid_module_event_handler(module_t mod, int what, void *arg)
#if 0
free(ata_raid_arrays, M_AR);
#endif
ata_ioctl_func = NULL;
ata_raid_ioctl_func = NULL;
return 0;
default:

View File

@ -413,7 +413,7 @@ atapi_action(struct cam_sim *sim, union ccb *ccb)
int tid = ccb_h->target_id;
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE, ("dev reset\n"));
ata_controlcmd(softc->atadev[tid]->dev, ATA_ATAPI_RESET, 0, 0, 0);
ata_controlcmd(softc->atadev[tid]->dev, ATA_DEVICE_RESET, 0, 0, 0);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
return;

View File

@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
#include <geom/geom.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/atapi-cd.h>
#include <dev/ata/ata-commands.h>
#include <ata_if.h>
/* prototypes */
@ -676,7 +675,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
break;
default:
error = ENOTTY;
error = ata_device_ioctl(dev, cmd, addr);
}
return error;
}

View File

@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
static disk_open_t afd_open;
static disk_close_t afd_close;
static disk_strategy_t afd_strategy;
static disk_ioctl_t afd_ioctl;
static int afd_sense(device_t);
static void afd_describe(device_t);
static void afd_done(struct ata_request *);
@ -103,6 +104,7 @@ afd_attach(device_t dev)
fdp->disk->d_open = afd_open;
fdp->disk->d_close = afd_close;
fdp->disk->d_strategy = afd_strategy;
fdp->disk->d_ioctl = afd_ioctl;
fdp->disk->d_name = "afd";
fdp->disk->d_drv1 = dev;
if (ch->dma)
@ -281,6 +283,12 @@ afd_done(struct ata_request *request)
ata_free_request(request);
}
static int
afd_ioctl(struct disk *disk, u_long cmd, void *data, int flag,struct thread *td)
{
return ata_device_ioctl(disk->d_drv1, cmd, data);
}
static int
afd_sense(device_t dev)
{

View File

@ -263,7 +263,7 @@ ast_close(struct cdev *cdev, int flags, int fmt, struct thread *td)
}
static int
ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t addr, int flag, struct thread *td)
ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int flag, struct thread *td)
{
device_t dev = cdev->si_drv1;
struct ast_softc *stp = device_get_ivars(dev);
@ -272,7 +272,7 @@ ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t addr, int flag, struct thread *
switch (cmd) {
case MTIOCGET:
{
struct mtget *g = (struct mtget *) addr;
struct mtget *g = (struct mtget *) data;
bzero(g, sizeof(struct mtget));
g->mt_type = 7;
@ -291,7 +291,7 @@ ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t addr, int flag, struct thread *
case MTIOCTOP:
{
int i;
struct mtop *mt = (struct mtop *)addr;
struct mtop *mt = (struct mtop *)data;
switch ((int16_t) (mt->mt_op)) {
@ -353,7 +353,7 @@ ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t addr, int flag, struct thread *
if ((error = ast_read_position(dev, 0, &position)))
break;
*(u_int32_t *)addr = position.tape;
*(u_int32_t *)data = position.tape;
}
break;
@ -363,20 +363,20 @@ ast_ioctl(struct cdev *cdev, u_long cmd, caddr_t addr, int flag, struct thread *
if ((error = ast_read_position(dev, 1, &position)))
break;
*(u_int32_t *)addr = position.tape;
*(u_int32_t *)data = position.tape;
}
break;
case MTIOCSLOCATE:
error = ast_locate(dev, 0, *(u_int32_t *)addr);
error = ast_locate(dev, 0, *(u_int32_t *)data);
break;
case MTIOCHLOCATE:
error = ast_locate(dev, 1, *(u_int32_t *)addr);
error = ast_locate(dev, 1, *(u_int32_t *)data);
break;
default:
error = ENOTTY;
error = ata_device_ioctl(dev, cmd, data);
}
return error;
}

View File

@ -192,6 +192,7 @@ struct ata_params {
/*255*/ u_int16_t integrity;
} __packed;
/* ATA transfer modes */
#define ATA_MODE_MASK 0x0f
#define ATA_DMA_MASK 0xf0
@ -216,32 +217,42 @@ struct ata_params {
#define ATA_SA150 0x47
#define ATA_DMA_MAX 0x4f
/* ATA commands */
#define ATA_NOP 0x00 /* NOP command */
#define ATA_NOP 0x00 /* NOP */
#define ATA_NF_FLUSHQUEUE 0x00 /* flush queued cmd's */
#define ATA_NF_AUTOPOLL 0x01 /* start autopoll function */
#define ATA_ATAPI_RESET 0x08 /* reset ATAPI device */
#define ATA_READ 0x20 /* read command */
#define ATA_READ48 0x24 /* read command */
#define ATA_READ_DMA48 0x25 /* read w/DMA command */
#define ATA_READ_DMA_QUEUED48 0x26 /* read w/DMA QUEUED command */
#define ATA_READ_MUL48 0x29 /* read multi command */
#define ATA_WRITE 0x30 /* write command */
#define ATA_WRITE48 0x34 /* write command */
#define ATA_WRITE_DMA48 0x35 /* write w/DMA command */
#define ATA_WRITE_DMA_QUEUED48 0x36 /* write w/DMA QUEUED command */
#define ATA_WRITE_MUL48 0x39 /* write multi command */
#define ATA_DEVICE_RESET 0x08 /* reset device */
#define ATA_READ 0x20 /* read */
#define ATA_READ48 0x24 /* read 48bit LBA */
#define ATA_READ_DMA48 0x25 /* read DMA 48bit LBA */
#define ATA_READ_DMA_QUEUED48 0x26 /* read DMA QUEUED 48bit LBA */
#define ATA_READ_MUL48 0x29 /* read multi 48bit LBA */
#define ATA_WRITE 0x30 /* write */
#define ATA_WRITE48 0x34 /* write 48bit LBA */
#define ATA_WRITE_DMA48 0x35 /* write DMA 48bit LBA */
#define ATA_WRITE_DMA_QUEUED48 0x36 /* write DMA QUEUED 48bit LBA*/
#define ATA_WRITE_MUL48 0x39 /* write multi 48bit LBA */
#define ATA_READ_FPDMA_QUEUED 0x60 /* read DMA NCQ */
#define ATA_WRITE_FPDMA_QUEUED 0x61 /* write DMA NCQ */
#define ATA_SEEK 0x70 /* seek */
#define ATA_PACKET_CMD 0xa0 /* packet command */
#define ATA_ATAPI_IDENTIFY 0xa1 /* get ATAPI params*/
#define ATA_SERVICE 0xa2 /* service command */
#define ATA_READ_MUL 0xc4 /* read multi command */
#define ATA_WRITE_MUL 0xc5 /* write multi command */
#define ATA_SET_MULTI 0xc6 /* set multi size command */
#define ATA_READ_DMA_QUEUED 0xc7 /* read w/DMA QUEUED command */
#define ATA_READ_DMA 0xc8 /* read w/DMA command */
#define ATA_WRITE_DMA 0xca /* write w/DMA command */
#define ATA_WRITE_DMA_QUEUED 0xcc /* write w/DMA QUEUED command */
#define ATA_SLEEP 0xe6 /* sleep command */
#define ATA_CFA_ERASE 0xc0 /* CFA erase */
#define ATA_READ_MUL 0xc4 /* read multi */
#define ATA_WRITE_MUL 0xc5 /* write multi */
#define ATA_SET_MULTI 0xc6 /* set multi size */
#define ATA_READ_DMA_QUEUED 0xc7 /* read DMA QUEUED */
#define ATA_READ_DMA 0xc8 /* read DMA */
#define ATA_WRITE_DMA 0xca /* write DMA */
#define ATA_WRITE_DMA_QUEUED 0xcc /* write DMA QUEUED */
#define ATA_STANDBY_IMMEDIATE 0xe0 /* standby immediate */
#define ATA_IDLE_IMMEDIATE 0xe1 /* idle immediate */
#define ATA_STANDBY_CMD 0xe2 /* standby */
#define ATA_IDLE_CMD 0xe3 /* idle */
#define ATA_READ_BUFFER 0xe4 /* read buffer */
#define ATA_SLEEP 0xe6 /* sleep */
#define ATA_FLUSHCACHE 0xe7 /* flush cache to disk */
#define ATA_FLUSHCACHE48 0xea /* flush cache to disk */
#define ATA_ATA_IDENTIFY 0xec /* get ATA params */
@ -255,6 +266,10 @@ struct ata_params {
#define ATA_SF_DIS_RELIRQ 0xdd /* disable release interrupt */
#define ATA_SF_ENAB_SRVIRQ 0x5e /* enable service interrupt */
#define ATA_SF_DIS_SRVIRQ 0xde /* disable service interrupt */
#define ATA_SECURITY_FREEE_LOCK 0xf5 /* freeze security config */
#define ATA_READ_NATIVE_MAX_ADDDRESS 0xf8 /* read native max address */
#define ATA_SET_MAX_ADDRESS 0xf9 /* set max address */
/* ATAPI commands */
#define ATAPI_TEST_UNIT_READY 0x00 /* check if device is ready */
@ -314,39 +329,21 @@ struct ata_params {
#define ATAPI_READ_CD 0xbe /* read data */
#define ATAPI_POLL_DSC 0xff /* poll DSC status bit */
struct ata_cmd {
struct ata_ioc_devices {
int channel;
int device;
int cmd;
#define ATAGMAXCHANNEL 0x0101
#define ATAGPARM 0x0102
#define ATAGMODE 0x0103
#define ATASMODE 0x0104
#define ATAREQUEST 0x0108
#define ATAREINIT 0x0110
#define ATAATTACH 0x0111
#define ATADETACH 0x0112
#define ATARAIDCREATE 0x0120
#define ATARAIDDELETE 0x0121
#define ATARAIDSTATUS 0x0122
#define ATARAIDADDSPARE 0x0123
#define ATARAIDREBUILD 0x0124
#define ATAENCSTAT 0x0130
union {
int maxchan;
struct {
int type[2];
char name[2][32];
struct ata_params params[2];
} param;
};
struct {
int mode[2];
} mode;
/* pr channel ATA ioctl calls */
#define IOCATAGMAXCHANNEL _IOR('a', 1, int)
#define IOCATAREINIT _IOW('a', 2, int)
#define IOCATAATTACH _IOW('a', 3, int)
#define IOCATADETACH _IOW('a', 4, int)
#define IOCATADEVICES _IOWR('a', 5, struct ata_ioc_devices)
struct {
struct ata_ioc_request {
union {
struct {
u_int8_t command;
@ -368,29 +365,27 @@ struct ata_cmd {
int timeout;
int error;
} request;
};
struct raid_setup {
/* pr device ATA ioctl calls */
#define IOCATAREQUEST _IOWR('a', 100, struct ata_ioc_request)
#define IOCATAGPARM _IOR('a', 101, struct ata_params)
#define IOCATAGMODE _IOR('a', 102, int)
#define IOCATASMODE _IOW('a', 103, int)
struct ata_ioc_raid_config {
int lun;
int type;
#define AR_JBOD 0x01
#define AR_SPAN 0x02
#define AR_RAID0 0x04
#define AR_RAID1 0x08
#define AR_RAID01 0x10
#define AR_RAID3 0x20
#define AR_RAID4 0x40
#define AR_RAID5 0x80
#define AR_JBOD 0x0001
#define AR_SPAN 0x0002
#define AR_RAID0 0x0004
#define AR_RAID1 0x0008
#define AR_RAID01 0x0010
#define AR_RAID3 0x0020
#define AR_RAID4 0x0040
#define AR_RAID5 0x0080
int total_disks;
int disks[16];
int interleave;
int unit;
} raid_setup;
struct raid_status {
int type;
int total_disks;
int disks[16];
int interleave;
int status;
#define AR_READY 1
@ -398,21 +393,15 @@ struct ata_cmd {
#define AR_REBUILDING 4
int progress;
} raid_status;
struct {
int disk;
} raid_spare;
struct {
int fan;
int temp;
int v05;
int v12;
} enclosure;
} u;
int total_disks;
int disks[16];
};
#define IOCATA _IOWR('a', 1, struct ata_cmd)
/* ATA RAID ioctl calls */
#define IOCATARAIDCREATE _IOW('a', 200, struct ata_ioc_raid_config)
#define IOCATARAIDDELETE _IOW('a', 201, int)
#define IOCATARAIDSTATUS _IOR('a', 202, struct ata_ioc_raid_config)
#define IOCATARAIDADDSPARE _IOW('a', 203, struct ata_ioc_raid_config)
#define IOCATARAIDREBUILD _IOW('a', 204, int)
#endif /* _SYS_ATA_H_ */