mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-14 10:09:48 +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:
parent
b0c77ed9fb
commit
6667b30d15
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=146266
@ -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);
|
||||
}
|
||||
|
||||
@ -176,7 +190,7 @@ cap_print(struct ata_params *parm)
|
||||
parm->capabilities1 & ATA_SUPPORT_OVERLAP ? " " : " not ");
|
||||
|
||||
printf("\nFeature "
|
||||
"Support Enable Value Vendor\n");
|
||||
"Support Enable Value Vendor\n");
|
||||
|
||||
printf("write cache %s %s\n",
|
||||
parm->support.command1 & ATA_SUPPORT_WRITECACHE ? "yes" : "no",
|
||||
@ -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, ¶ms) < 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(¶ms);
|
||||
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");
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
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);
|
||||
}
|
||||
else {
|
||||
if (!(sscanf(argv[2], "%d", &chan) == 1 ||
|
||||
sscanf(argv[2], "ata%d", &chan) == 1)) {
|
||||
fprintf(stderr, "atacontrol: Invalid ATA channel\n");
|
||||
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)");
|
||||
}
|
||||
iocmd.channel = chan;
|
||||
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);
|
||||
}
|
||||
|
||||
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");
|
||||
fprintf(stderr, "atacontrol: Valid RAID types : \n");
|
||||
fprintf(stderr, " RAID0 | stripe | RAID1 | mirror "
|
||||
"| RAID0+1 | SPAN | JBOD\n");
|
||||
if (!config.type) {
|
||||
fprintf(stderr, "atacontrol: Invalid RAID type %s\n",
|
||||
argv[2]);
|
||||
fprintf(stderr, "atacontrol: Valid RAID types: \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();
|
||||
}
|
||||
if (ioctl(fd, IOCATARAIDADDSPARE, &config) < 0)
|
||||
warn("ioctl(IOCATARAIDADDSPARE)");
|
||||
exit(EX_OK);
|
||||
}
|
||||
else if (!strcmp(argv[1], "rebuild") && argc == 3) {
|
||||
iocmd.cmd = ATARAIDREBUILD;
|
||||
if (ioctl(fd, IOCATA, &iocmd) < 0)
|
||||
warn("ioctl(ATARAIDREBUILD)");
|
||||
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();
|
||||
usage();
|
||||
exit(EX_OK);
|
||||
}
|
||||
|
@ -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)) {
|
||||
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;
|
||||
switch (cmd) {
|
||||
case IOCATAGMAXCHANNEL:
|
||||
*value = devclass_get_maxunit(ata_devclass);
|
||||
error = 0;
|
||||
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:
|
||||
case IOCATAREINIT:
|
||||
if (*value > devclass_get_maxunit(ata_devclass) ||
|
||||
!(device = devclass_get_device(ata_devclass, *value)))
|
||||
return ENXIO;
|
||||
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",
|
||||
@ -754,26 +709,26 @@ ata_modify_if_48bit(struct ata_request *request)
|
||||
request->u.ata.count > 256) &&
|
||||
atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) {
|
||||
|
||||
/* translate command into 48bit version */
|
||||
switch (command) {
|
||||
case ATA_READ:
|
||||
command = ATA_READ48; break;
|
||||
case ATA_READ_MUL:
|
||||
command = ATA_READ_MUL48; break;
|
||||
case ATA_READ_DMA:
|
||||
command = ATA_READ_DMA48; break;
|
||||
case ATA_READ_DMA_QUEUED:
|
||||
command = ATA_READ_DMA_QUEUED48; break;
|
||||
case ATA_WRITE:
|
||||
command = ATA_WRITE48; break;
|
||||
case ATA_WRITE_MUL:
|
||||
command = ATA_WRITE_MUL48; break;
|
||||
case ATA_WRITE_DMA:
|
||||
command = ATA_WRITE_DMA48; break;
|
||||
case ATA_WRITE_DMA_QUEUED:
|
||||
command = ATA_WRITE_DMA_QUEUED48; break;
|
||||
case ATA_FLUSHCACHE:
|
||||
command = ATA_FLUSHCACHE48; break;
|
||||
/* translate command into 48bit version */
|
||||
switch (command) {
|
||||
case ATA_READ:
|
||||
command = ATA_READ48; break;
|
||||
case ATA_READ_MUL:
|
||||
command = ATA_READ_MUL48; break;
|
||||
case ATA_READ_DMA:
|
||||
command = ATA_READ_DMA48; break;
|
||||
case ATA_READ_DMA_QUEUED:
|
||||
command = ATA_READ_DMA_QUEUED48; break;
|
||||
case ATA_WRITE:
|
||||
command = ATA_WRITE48; break;
|
||||
case ATA_WRITE_MUL:
|
||||
command = ATA_WRITE_MUL48; break;
|
||||
case ATA_WRITE_DMA:
|
||||
command = ATA_WRITE_DMA48; break;
|
||||
case ATA_WRITE_DMA_QUEUED:
|
||||
command = ATA_WRITE_DMA_QUEUED48; break;
|
||||
case ATA_FLUSHCACHE:
|
||||
command = ATA_FLUSHCACHE48; break;
|
||||
default:
|
||||
return command;
|
||||
}
|
||||
|
@ -163,87 +163,87 @@
|
||||
#define ATA_SC_IPM_DIS_PARTIAL 0x00000100
|
||||
#define ATA_SC_IPM_DIS_SLUMBER 0x00000200
|
||||
|
||||
#define ATA_SACTIVE 16
|
||||
#define ATA_SACTIVE 16
|
||||
|
||||
/* SATA AHCI v1.0 register defines */
|
||||
#define ATA_AHCI_CAP 0x00
|
||||
#define ATA_AHCI_NPMASK 0x1f
|
||||
#define ATA_AHCI_CAP 0x00
|
||||
#define ATA_AHCI_NPMASK 0x1f
|
||||
|
||||
#define ATA_AHCI_GHC 0x04
|
||||
#define ATA_AHCI_GHC_AE 0x80000000
|
||||
#define ATA_AHCI_GHC_IE 0x00000002
|
||||
#define ATA_AHCI_GHC_HR 0x80000001
|
||||
#define ATA_AHCI_GHC 0x04
|
||||
#define ATA_AHCI_GHC_AE 0x80000000
|
||||
#define ATA_AHCI_GHC_IE 0x00000002
|
||||
#define ATA_AHCI_GHC_HR 0x80000001
|
||||
|
||||
#define ATA_AHCI_IS 0x08
|
||||
#define ATA_AHCI_PI 0x0c
|
||||
#define ATA_AHCI_VS 0x10
|
||||
#define ATA_AHCI_IS 0x08
|
||||
#define ATA_AHCI_PI 0x0c
|
||||
#define ATA_AHCI_VS 0x10
|
||||
|
||||
#define ATA_AHCI_OFFSET 0x80
|
||||
#define ATA_AHCI_OFFSET 0x80
|
||||
|
||||
#define ATA_AHCI_P_CLB 0x100
|
||||
#define ATA_AHCI_P_CLBU 0x104
|
||||
#define ATA_AHCI_P_FB 0x108
|
||||
#define ATA_AHCI_P_FBU 0x10c
|
||||
#define ATA_AHCI_P_IS 0x110
|
||||
#define ATA_AHCI_P_IE 0x114
|
||||
#define ATA_AHCI_P_IX_DHR 0x00000001
|
||||
#define ATA_AHCI_P_IX_PS 0x00000002
|
||||
#define ATA_AHCI_P_IX_DS 0x00000004
|
||||
#define ATA_AHCI_P_IX_SDB 0x00000008
|
||||
#define ATA_AHCI_P_IX_UF 0x00000010
|
||||
#define ATA_AHCI_P_IX_DP 0x00000020
|
||||
#define ATA_AHCI_P_IX_PC 0x00000040
|
||||
#define ATA_AHCI_P_IX_DI 0x00000080
|
||||
#define ATA_AHCI_P_CLB 0x100
|
||||
#define ATA_AHCI_P_CLBU 0x104
|
||||
#define ATA_AHCI_P_FB 0x108
|
||||
#define ATA_AHCI_P_FBU 0x10c
|
||||
#define ATA_AHCI_P_IS 0x110
|
||||
#define ATA_AHCI_P_IE 0x114
|
||||
#define ATA_AHCI_P_IX_DHR 0x00000001
|
||||
#define ATA_AHCI_P_IX_PS 0x00000002
|
||||
#define ATA_AHCI_P_IX_DS 0x00000004
|
||||
#define ATA_AHCI_P_IX_SDB 0x00000008
|
||||
#define ATA_AHCI_P_IX_UF 0x00000010
|
||||
#define ATA_AHCI_P_IX_DP 0x00000020
|
||||
#define ATA_AHCI_P_IX_PC 0x00000040
|
||||
#define ATA_AHCI_P_IX_DI 0x00000080
|
||||
|
||||
#define ATA_AHCI_P_IX_PRC 0x00400000
|
||||
#define ATA_AHCI_P_IX_IPM 0x00800000
|
||||
#define ATA_AHCI_P_IX_OF 0x01000000
|
||||
#define ATA_AHCI_P_IX_INF 0x04000000
|
||||
#define ATA_AHCI_P_IX_IF 0x08000000
|
||||
#define ATA_AHCI_P_IX_HBD 0x10000000
|
||||
#define ATA_AHCI_P_IX_HBF 0x20000000
|
||||
#define ATA_AHCI_P_IX_TFE 0x40000000
|
||||
#define ATA_AHCI_P_IX_CPD 0x80000000
|
||||
#define ATA_AHCI_P_IX_PRC 0x00400000
|
||||
#define ATA_AHCI_P_IX_IPM 0x00800000
|
||||
#define ATA_AHCI_P_IX_OF 0x01000000
|
||||
#define ATA_AHCI_P_IX_INF 0x04000000
|
||||
#define ATA_AHCI_P_IX_IF 0x08000000
|
||||
#define ATA_AHCI_P_IX_HBD 0x10000000
|
||||
#define ATA_AHCI_P_IX_HBF 0x20000000
|
||||
#define ATA_AHCI_P_IX_TFE 0x40000000
|
||||
#define ATA_AHCI_P_IX_CPD 0x80000000
|
||||
|
||||
#define ATA_AHCI_P_CMD 0x118
|
||||
#define ATA_AHCI_P_CMD_ST 0x00000001
|
||||
#define ATA_AHCI_P_CMD_SUD 0x00000002
|
||||
#define ATA_AHCI_P_CMD_POD 0x00000004
|
||||
#define ATA_AHCI_P_CMD_CLO 0x00000008
|
||||
#define ATA_AHCI_P_CMD_FRE 0x00000010
|
||||
#define ATA_AHCI_P_CMD_CCS_MASK 0x00001f00
|
||||
#define ATA_AHCI_P_CMD_ISS 0x00002000
|
||||
#define ATA_AHCI_P_CMD_FR 0x00004000
|
||||
#define ATA_AHCI_P_CMD_CR 0x00008000
|
||||
#define ATA_AHCI_P_CMD_CPS 0x00010000
|
||||
#define ATA_AHCI_P_CMD_PMA 0x00020000
|
||||
#define ATA_AHCI_P_CMD_HPCP 0x00040000
|
||||
#define ATA_AHCI_P_CMD_ISP 0x00080000
|
||||
#define ATA_AHCI_P_CMD_CPD 0x00100000
|
||||
#define ATA_AHCI_P_CMD_ATAPI 0x01000000
|
||||
#define ATA_AHCI_P_CMD_DLAE 0x02000000
|
||||
#define ATA_AHCI_P_CMD_ALPE 0x04000000
|
||||
#define ATA_AHCI_P_CMD_ASP 0x08000000
|
||||
#define ATA_AHCI_P_CMD_ICC_MASK 0xf0000000
|
||||
#define ATA_AHCI_P_CMD_NOOP 0x00000000
|
||||
#define ATA_AHCI_P_CMD_ACTIVE 0x10000000
|
||||
#define ATA_AHCI_P_CMD_PARTIAL 0x20000000
|
||||
#define ATA_AHCI_P_CMD_SLUMPER 0x60000000
|
||||
#define ATA_AHCI_P_CMD 0x118
|
||||
#define ATA_AHCI_P_CMD_ST 0x00000001
|
||||
#define ATA_AHCI_P_CMD_SUD 0x00000002
|
||||
#define ATA_AHCI_P_CMD_POD 0x00000004
|
||||
#define ATA_AHCI_P_CMD_CLO 0x00000008
|
||||
#define ATA_AHCI_P_CMD_FRE 0x00000010
|
||||
#define ATA_AHCI_P_CMD_CCS_MASK 0x00001f00
|
||||
#define ATA_AHCI_P_CMD_ISS 0x00002000
|
||||
#define ATA_AHCI_P_CMD_FR 0x00004000
|
||||
#define ATA_AHCI_P_CMD_CR 0x00008000
|
||||
#define ATA_AHCI_P_CMD_CPS 0x00010000
|
||||
#define ATA_AHCI_P_CMD_PMA 0x00020000
|
||||
#define ATA_AHCI_P_CMD_HPCP 0x00040000
|
||||
#define ATA_AHCI_P_CMD_ISP 0x00080000
|
||||
#define ATA_AHCI_P_CMD_CPD 0x00100000
|
||||
#define ATA_AHCI_P_CMD_ATAPI 0x01000000
|
||||
#define ATA_AHCI_P_CMD_DLAE 0x02000000
|
||||
#define ATA_AHCI_P_CMD_ALPE 0x04000000
|
||||
#define ATA_AHCI_P_CMD_ASP 0x08000000
|
||||
#define ATA_AHCI_P_CMD_ICC_MASK 0xf0000000
|
||||
#define ATA_AHCI_P_CMD_NOOP 0x00000000
|
||||
#define ATA_AHCI_P_CMD_ACTIVE 0x10000000
|
||||
#define ATA_AHCI_P_CMD_PARTIAL 0x20000000
|
||||
#define ATA_AHCI_P_CMD_SLUMPER 0x60000000
|
||||
|
||||
#define ATA_AHCI_P_TFD 0x120
|
||||
#define ATA_AHCI_P_SIG 0x124
|
||||
#define ATA_AHCI_P_SSTS 0x128
|
||||
#define ATA_AHCI_P_SCTL 0x12c
|
||||
#define ATA_AHCI_P_SERR 0x130
|
||||
#define ATA_AHCI_P_SACT 0x134
|
||||
#define ATA_AHCI_P_CI 0x138
|
||||
#define ATA_AHCI_P_TFD 0x120
|
||||
#define ATA_AHCI_P_SIG 0x124
|
||||
#define ATA_AHCI_P_SSTS 0x128
|
||||
#define ATA_AHCI_P_SCTL 0x12c
|
||||
#define ATA_AHCI_P_SERR 0x130
|
||||
#define ATA_AHCI_P_SACT 0x134
|
||||
#define ATA_AHCI_P_CI 0x138
|
||||
|
||||
#define ATA_AHCI_CL_SIZE 32
|
||||
#define ATA_AHCI_CL_OFFSET 0
|
||||
#define ATA_AHCI_FB_OFFSET 1024
|
||||
#define ATA_AHCI_CT_OFFSET 1024+256
|
||||
#define ATA_AHCI_CT_SG_OFFSET 128
|
||||
#define ATA_AHCI_CT_SIZE 256
|
||||
#define ATA_AHCI_CL_SIZE 32
|
||||
#define ATA_AHCI_CL_OFFSET 0
|
||||
#define ATA_AHCI_FB_OFFSET 1024
|
||||
#define ATA_AHCI_CT_OFFSET 1024+256
|
||||
#define ATA_AHCI_CT_SG_OFFSET 128
|
||||
#define ATA_AHCI_CT_SIZE 256
|
||||
|
||||
/* DMA register defines */
|
||||
#define ATA_DMA_ENTRIES 256
|
||||
@ -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);
|
||||
|
@ -250,15 +250,15 @@ ata_sata_connect(struct ata_channel *ch)
|
||||
if (bootverbose)
|
||||
device_printf(ch->dev, "SATA connect ready time=%dms\n", timeout * 10);
|
||||
if (timeout < 1000) {
|
||||
if ((ATA_IDX_INB(ch, ATA_CYL_LSB) == ATAPI_MAGIC_LSB) &&
|
||||
if ((ATA_IDX_INB(ch, ATA_CYL_LSB) == ATAPI_MAGIC_LSB) &&
|
||||
(ATA_IDX_INB(ch, ATA_CYL_MSB) == ATAPI_MAGIC_MSB))
|
||||
ch->devices = ATA_ATAPI_MASTER;
|
||||
else
|
||||
else
|
||||
ch->devices = ATA_ATA_MASTER;
|
||||
}
|
||||
if (bootverbose)
|
||||
device_printf(ch->dev, "sata_connect devices=0x%b\n",
|
||||
ch->devices, "\20\3ATAPI_MASTER\1ATA_MASTER");
|
||||
device_printf(ch->dev, "sata_connect devices=0x%b\n",
|
||||
ch->devices, "\20\3ATAPI_MASTER\1ATA_MASTER");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -325,25 +325,25 @@ ata_sata_phy_event(void *context, int dummy)
|
||||
* AHCI v1.0 compliant SATA chipset support functions
|
||||
*/
|
||||
struct ata_ahci_dma_prd {
|
||||
u_int64_t dba;
|
||||
u_int32_t reserved;
|
||||
u_int32_t dbc; /* 0 based */
|
||||
#define ATA_AHCI_PRD_MASK 0x003fffff /* max 4MB */
|
||||
#define ATA_AHCI_PRD_IPC (1<<31)
|
||||
u_int64_t dba;
|
||||
u_int32_t reserved;
|
||||
u_int32_t dbc; /* 0 based */
|
||||
#define ATA_AHCI_PRD_MASK 0x003fffff /* max 4MB */
|
||||
#define ATA_AHCI_PRD_IPC (1<<31)
|
||||
} __packed;
|
||||
|
||||
struct ata_ahci_cmd_tab {
|
||||
u_int8_t cfis[64];
|
||||
u_int8_t acmd[32];
|
||||
u_int8_t reserved[32];
|
||||
struct ata_ahci_dma_prd prd_tab[16];
|
||||
u_int8_t cfis[64];
|
||||
u_int8_t acmd[32];
|
||||
u_int8_t reserved[32];
|
||||
struct ata_ahci_dma_prd prd_tab[16];
|
||||
} __packed;
|
||||
|
||||
struct ata_ahci_cmd_list {
|
||||
u_int16_t cmd_flags;
|
||||
u_int16_t prd_length; /* PRD entries */
|
||||
u_int32_t bytecount;
|
||||
u_int64_t cmd_table_phys; /* 128byte aligned */
|
||||
u_int16_t cmd_flags;
|
||||
u_int16_t prd_length; /* PRD entries */
|
||||
u_int32_t bytecount;
|
||||
u_int64_t cmd_table_phys; /* 128byte aligned */
|
||||
} __packed;
|
||||
|
||||
|
||||
@ -376,7 +376,7 @@ ata_ahci_allocate(device_t dev)
|
||||
|
||||
ch->hw.begin_transaction = ata_ahci_begin_transaction;
|
||||
ch->hw.end_transaction = ata_ahci_end_transaction;
|
||||
ch->hw.command = NULL; /* not used here */
|
||||
ch->hw.command = NULL; /* not used here */
|
||||
|
||||
/* setup the work areas */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset,
|
||||
@ -409,8 +409,8 @@ ata_ahci_setup_fis(u_int8_t *fis, struct ata_request *request)
|
||||
int idx = 0;
|
||||
|
||||
/* XXX SOS add ATAPI commands support later */
|
||||
fis[idx++] = 0x27; /* host to device */
|
||||
fis[idx++] = 0x80; /* command FIS (note PM goes here) */
|
||||
fis[idx++] = 0x27; /* host to device */
|
||||
fis[idx++] = 0x80; /* command FIS (note PM goes here) */
|
||||
fis[idx++] = ata_modify_if_48bit(request);
|
||||
fis[idx++] = request->u.ata.feature;
|
||||
|
||||
@ -460,13 +460,13 @@ ata_ahci_begin_transaction(struct ata_request *request)
|
||||
|
||||
/* if request moves data setup and load SG list */
|
||||
if (request->flags & (ATA_R_READ | ATA_R_WRITE)) {
|
||||
if (ch->dma->load(ch->dev, request->data, request->bytecount,
|
||||
request->flags & ATA_R_READ,
|
||||
if (ch->dma->load(ch->dev, request->data, request->bytecount,
|
||||
request->flags & ATA_R_READ,
|
||||
ctp->prd_tab, &entries)) {
|
||||
device_printf(request->dev, "setting up DMA failed\n");
|
||||
request->result = EIO;
|
||||
return ATA_OP_FINISHED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* setup the command list entry */
|
||||
@ -475,11 +475,11 @@ ata_ahci_begin_transaction(struct ata_request *request)
|
||||
|
||||
clp->prd_length = entries;
|
||||
clp->cmd_flags = (request->flags & ATA_R_WRITE ? (1<<6) : 0) |
|
||||
(request->flags & ATA_R_ATAPI ? (1<<5) : 0) |
|
||||
(fis_size / sizeof(u_int32_t));
|
||||
(request->flags & ATA_R_ATAPI ? (1<<5) : 0) |
|
||||
(fis_size / sizeof(u_int32_t));
|
||||
clp->bytecount = 0;
|
||||
clp->cmd_table_phys = htole64(ch->dma->work_bus + ATA_AHCI_CT_OFFSET +
|
||||
(ATA_AHCI_CT_SIZE * tag));
|
||||
(ATA_AHCI_CT_SIZE * tag));
|
||||
|
||||
/* clear eventual ACTIVE bit */
|
||||
ATA_IDX_OUTL(ch, ATA_SACTIVE, ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << tag));
|
||||
@ -516,7 +516,7 @@ ata_ahci_end_transaction(struct ata_request *request)
|
||||
|
||||
/* record how much data we actually moved */
|
||||
clp = (struct ata_ahci_cmd_list *)
|
||||
(ch->dma->work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE * tag));
|
||||
(ch->dma->work + ATA_AHCI_CL_OFFSET + (ATA_AHCI_CL_SIZE * tag));
|
||||
request->donecount = clp->bytecount;
|
||||
|
||||
/* release SG list etc */
|
||||
@ -542,11 +542,11 @@ ata_ahci_intr(void *data)
|
||||
struct ata_connect_task *tp;
|
||||
int offset = (ch->unit << 7);
|
||||
|
||||
error = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SERR + offset);
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_SERR + offset, error);
|
||||
status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset);
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, status);
|
||||
issued = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset);
|
||||
error = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SERR + offset);
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_SERR + offset, error);
|
||||
status = ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset);
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset, status);
|
||||
issued = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CI + offset);
|
||||
|
||||
/* do we have cold connect surprise */
|
||||
if (status & ATA_AHCI_P_IX_CPD) {
|
||||
@ -554,24 +554,24 @@ ata_ahci_intr(void *data)
|
||||
status, error, issued);
|
||||
}
|
||||
|
||||
/* check for and handle connect events */
|
||||
if ((status & ATA_AHCI_P_IX_PC) &&
|
||||
/* check for and handle connect events */
|
||||
if ((status & ATA_AHCI_P_IX_PC) &&
|
||||
(tp = (struct ata_connect_task *)
|
||||
malloc(sizeof(struct ata_connect_task),
|
||||
M_ATA, M_NOWAIT | M_ZERO))) {
|
||||
malloc(sizeof(struct ata_connect_task),
|
||||
M_ATA, M_NOWAIT | M_ZERO))) {
|
||||
|
||||
device_printf(ch->dev, "CONNECT requested\n");
|
||||
tp->action = ATA_C_ATTACH;
|
||||
tp->dev = ch->dev;
|
||||
TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
|
||||
taskqueue_enqueue(taskqueue_thread, &tp->task);
|
||||
}
|
||||
}
|
||||
|
||||
/* check for and handle disconnect events */
|
||||
if (((status & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) ==
|
||||
/* check for and handle disconnect events */
|
||||
if (((status & (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC)) ==
|
||||
ATA_AHCI_P_IX_PRC) &&
|
||||
(tp = (struct ata_connect_task *)
|
||||
malloc(sizeof(struct ata_connect_task),
|
||||
malloc(sizeof(struct ata_connect_task),
|
||||
M_ATA, M_NOWAIT | M_ZERO))) {
|
||||
|
||||
device_printf(ch->dev, "DISCONNECT requested\n");
|
||||
@ -579,11 +579,11 @@ ata_ahci_intr(void *data)
|
||||
tp->dev = ch->dev;
|
||||
TASK_INIT(&tp->task, 0, ata_sata_phy_event, tp);
|
||||
taskqueue_enqueue(taskqueue_thread, &tp->task);
|
||||
}
|
||||
}
|
||||
|
||||
/* any drive action to take care of ? */
|
||||
if (!(issued & (1<<tag)))
|
||||
ctlr->interrupt[unit].function(ch);
|
||||
/* any drive action to take care of ? */
|
||||
if (!(issued & (1<<tag)))
|
||||
ctlr->interrupt[unit].function(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -604,7 +604,7 @@ ata_ahci_reset(device_t dev)
|
||||
cmd & ~(ATA_AHCI_P_CMD_CR | ATA_AHCI_P_CMD_FR |
|
||||
ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST));
|
||||
|
||||
DELAY(500000); /* XXX SOS this is not entirely wrong */
|
||||
DELAY(500000); /* XXX SOS this is not entirely wrong */
|
||||
|
||||
/* spin up device */
|
||||
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, ATA_AHCI_P_CMD_SUD);
|
||||
@ -1426,10 +1426,10 @@ ata_intel_chipinit(device_t dev)
|
||||
&ctlr->r_rid2, RF_ACTIVE))) {
|
||||
if (bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle) ||
|
||||
bus_setup_intr(dev, ctlr->r_irq, ATA_INTR_FLAGS,
|
||||
ata_ahci_intr, ctlr, &ctlr->handle)) {
|
||||
device_printf(dev, "unable to setup interrupt\n");
|
||||
return ENXIO;
|
||||
}
|
||||
ata_ahci_intr, ctlr, &ctlr->handle)) {
|
||||
device_printf(dev, "unable to setup interrupt\n");
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
/* force all ports active "the legacy way" */
|
||||
pci_write_config(dev, 0x92, pci_read_config(dev, 0x92, 2) | 0x0f,2);
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
||||
@ -667,9 +666,9 @@ ata_generic_command(struct ata_request *request)
|
||||
ATA_IDX_OUTB(ch, ATA_CONTROL, ATA_A_4BIT);
|
||||
|
||||
if (request->flags & ATA_R_ATAPI) {
|
||||
int timeout = 5000;
|
||||
int timeout = 5000;
|
||||
|
||||
/* issue packet command to controller */
|
||||
/* issue packet command to controller */
|
||||
if (request->flags & ATA_R_DMA) {
|
||||
ATA_IDX_OUTB(ch, ATA_FEATURE, ATA_F_DMA);
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_LSB, 0);
|
||||
@ -683,32 +682,32 @@ ata_generic_command(struct ata_request *request)
|
||||
ATA_IDX_OUTB(ch, ATA_COMMAND, ATA_PACKET_CMD);
|
||||
|
||||
/* command interrupt device ? just return and wait for interrupt */
|
||||
if ((atadev->param.config & ATA_DRQ_MASK) == ATA_DRQ_INTR)
|
||||
if ((atadev->param.config & ATA_DRQ_MASK) == ATA_DRQ_INTR)
|
||||
return 0;
|
||||
|
||||
/* wait for ready to write ATAPI command block */
|
||||
while (timeout--) {
|
||||
int reason = ATA_IDX_INB(ch, ATA_IREASON);
|
||||
int status = ATA_IDX_INB(ch, ATA_STATUS);
|
||||
while (timeout--) {
|
||||
int reason = ATA_IDX_INB(ch, ATA_IREASON);
|
||||
int status = ATA_IDX_INB(ch, ATA_STATUS);
|
||||
|
||||
if (((reason & (ATA_I_CMD | ATA_I_IN)) |
|
||||
(status & (ATA_S_DRQ | ATA_S_BUSY))) == ATAPI_P_CMDOUT)
|
||||
break;
|
||||
DELAY(20);
|
||||
}
|
||||
if (timeout <= 0) {
|
||||
device_printf(request->dev,"timeout waiting for ATAPI ready\n");
|
||||
request->result = EIO;
|
||||
return -1;
|
||||
}
|
||||
if (((reason & (ATA_I_CMD | ATA_I_IN)) |
|
||||
(status & (ATA_S_DRQ | ATA_S_BUSY))) == ATAPI_P_CMDOUT)
|
||||
break;
|
||||
DELAY(20);
|
||||
}
|
||||
if (timeout <= 0) {
|
||||
device_printf(request->dev,"timeout waiting for ATAPI ready\n");
|
||||
request->result = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* this seems to be needed for some (slow) devices */
|
||||
DELAY(10);
|
||||
|
||||
/* output command block */
|
||||
ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (int16_t *)request->u.atapi.ccb,
|
||||
(atadev->param.config & ATA_PROTO_MASK) ==
|
||||
ATA_PROTO_ATAPI_12 ? 6 : 8);
|
||||
/* this seems to be needed for some (slow) devices */
|
||||
DELAY(10);
|
||||
|
||||
/* output command block */
|
||||
ATA_IDX_OUTSW_STRM(ch, ATA_DATA, (int16_t *)request->u.atapi.ccb,
|
||||
(atadev->param.config & ATA_PROTO_MASK) ==
|
||||
ATA_PROTO_ATAPI_12 ? 6 : 8);
|
||||
}
|
||||
else {
|
||||
u_int8_t command = ata_modify_if_48bit(request);
|
||||
@ -726,42 +725,42 @@ ata_generic_command(struct ata_request *request)
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
|
||||
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_LBA | atadev->unit);
|
||||
}
|
||||
else {
|
||||
else {
|
||||
command = request->u.ata.command;
|
||||
ATA_IDX_OUTB(ch, ATA_FEATURE, request->u.ata.feature);
|
||||
ATA_IDX_OUTB(ch, ATA_COUNT, request->u.ata.count);
|
||||
if (atadev->flags & ATA_D_USE_CHS) {
|
||||
int heads, sectors;
|
||||
int heads, sectors;
|
||||
|
||||
if (atadev->param.atavalid & ATA_FLAG_54_58) {
|
||||
if (atadev->param.atavalid & ATA_FLAG_54_58) {
|
||||
heads = atadev->param.current_heads;
|
||||
sectors = atadev->param.current_sectors;
|
||||
}
|
||||
else {
|
||||
}
|
||||
else {
|
||||
heads = atadev->param.heads;
|
||||
sectors = atadev->param.sectors;
|
||||
}
|
||||
ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_LSB,
|
||||
}
|
||||
ATA_IDX_OUTB(ch, ATA_SECTOR, (request->u.ata.lba % sectors)+1);
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_LSB,
|
||||
(request->u.ata.lba / (sectors * heads)));
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_MSB,
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_MSB,
|
||||
(request->u.ata.lba / (sectors * heads)) >> 8);
|
||||
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit |
|
||||
ATA_IDX_OUTB(ch, ATA_DRIVE, ATA_D_IBM | atadev->unit |
|
||||
(((request->u.ata.lba% (sectors * heads)) /
|
||||
sectors) & 0xf));
|
||||
}
|
||||
else {
|
||||
ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
|
||||
ATA_IDX_OUTB(ch, ATA_DRIVE,
|
||||
ATA_IDX_OUTB(ch, ATA_SECTOR, request->u.ata.lba);
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_LSB, request->u.ata.lba >> 8);
|
||||
ATA_IDX_OUTB(ch, ATA_CYL_MSB, request->u.ata.lba >> 16);
|
||||
ATA_IDX_OUTB(ch, ATA_DRIVE,
|
||||
ATA_D_IBM | ATA_D_LBA | atadev->unit |
|
||||
((request->u.ata.lba >> 24) & 0x0f));
|
||||
}
|
||||
}
|
||||
|
||||
/* issue command to controller */
|
||||
ATA_IDX_OUTB(ch, ATA_COMMAND, command);
|
||||
/* issue command to controller */
|
||||
ATA_IDX_OUTB(ch, ATA_COMMAND, command);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -141,11 +141,11 @@ struct ata_connect_task {
|
||||
#define ATA_I82801FB_S1 0x26518086
|
||||
#define ATA_I82801FB_R1 0x26528086
|
||||
#define ATA_I82801FB_M 0x26538086
|
||||
#define ATA_I82801GB 0x27df8086
|
||||
#define ATA_I82801GB_S1 0x27c08086
|
||||
#define ATA_I82801GB_R1 0x27c38086
|
||||
#define ATA_I82801GB_AH 0x27c18086
|
||||
#define ATA_I82801GB_M 0x27c58086
|
||||
#define ATA_I82801GB 0x27df8086
|
||||
#define ATA_I82801GB_S1 0x27c08086
|
||||
#define ATA_I82801GB_R1 0x27c38086
|
||||
#define ATA_I82801GB_AH 0x27c18086
|
||||
#define ATA_I82801GB_M 0x27c58086
|
||||
|
||||
#define ATA_ITE_ID 0x1283
|
||||
#define ATA_IT8212F 0x82121283
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
689
sys/sys/ata.h
689
sys/sys/ata.h
@ -35,384 +35,373 @@
|
||||
|
||||
/* ATA/ATAPI device parameters */
|
||||
struct ata_params {
|
||||
/*000*/ u_int16_t config; /* configuration info */
|
||||
#define ATA_PROTO_MASK 0x8003
|
||||
#define ATA_PROTO_ATAPI 0x8000
|
||||
#define ATA_PROTO_ATAPI_12 0x8000
|
||||
#define ATA_PROTO_ATAPI_16 0x8001
|
||||
#define ATA_ATAPI_TYPE_MASK 0x1f00
|
||||
#define ATA_ATAPI_TYPE_DIRECT 0x0000 /* disk/floppy */
|
||||
#define ATA_ATAPI_TYPE_TAPE 0x0100 /* streaming tape */
|
||||
#define ATA_ATAPI_TYPE_CDROM 0x0500 /* CD-ROM device */
|
||||
#define ATA_ATAPI_TYPE_OPTICAL 0x0700 /* optical disk */
|
||||
#define ATA_DRQ_MASK 0x0060
|
||||
#define ATA_DRQ_SLOW 0x0000 /* cpu 3 ms delay */
|
||||
#define ATA_DRQ_INTR 0x0020 /* interrupt 10 ms delay */
|
||||
#define ATA_DRQ_FAST 0x0040 /* accel 50 us delay */
|
||||
/*000*/ u_int16_t config; /* configuration info */
|
||||
#define ATA_PROTO_MASK 0x8003
|
||||
#define ATA_PROTO_ATAPI 0x8000
|
||||
#define ATA_PROTO_ATAPI_12 0x8000
|
||||
#define ATA_PROTO_ATAPI_16 0x8001
|
||||
#define ATA_ATAPI_TYPE_MASK 0x1f00
|
||||
#define ATA_ATAPI_TYPE_DIRECT 0x0000 /* disk/floppy */
|
||||
#define ATA_ATAPI_TYPE_TAPE 0x0100 /* streaming tape */
|
||||
#define ATA_ATAPI_TYPE_CDROM 0x0500 /* CD-ROM device */
|
||||
#define ATA_ATAPI_TYPE_OPTICAL 0x0700 /* optical disk */
|
||||
#define ATA_DRQ_MASK 0x0060
|
||||
#define ATA_DRQ_SLOW 0x0000 /* cpu 3 ms delay */
|
||||
#define ATA_DRQ_INTR 0x0020 /* interrupt 10 ms delay */
|
||||
#define ATA_DRQ_FAST 0x0040 /* accel 50 us delay */
|
||||
|
||||
/*001*/ u_int16_t cylinders; /* # of cylinders */
|
||||
u_int16_t reserved2;
|
||||
/*003*/ u_int16_t heads; /* # heads */
|
||||
u_int16_t obsolete4;
|
||||
u_int16_t obsolete5;
|
||||
/*006*/ u_int16_t sectors; /* # sectors/track */
|
||||
/*007*/ u_int16_t vendor7[3];
|
||||
/*010*/ u_int8_t serial[20]; /* serial number */
|
||||
/*020*/ u_int16_t retired20;
|
||||
u_int16_t retired21;
|
||||
u_int16_t obsolete22;
|
||||
/*023*/ u_int8_t revision[8]; /* firmware revision */
|
||||
/*027*/ u_int8_t model[40]; /* model name */
|
||||
/*047*/ u_int16_t sectors_intr; /* sectors per interrupt */
|
||||
/*048*/ u_int16_t usedmovsd; /* double word read/write? */
|
||||
/*049*/ u_int16_t capabilities1;
|
||||
#define ATA_SUPPORT_DMA 0x0100
|
||||
#define ATA_SUPPORT_LBA 0x0200
|
||||
#define ATA_SUPPORT_OVERLAP 0x4000
|
||||
/*001*/ u_int16_t cylinders; /* # of cylinders */
|
||||
u_int16_t reserved2;
|
||||
/*003*/ u_int16_t heads; /* # heads */
|
||||
u_int16_t obsolete4;
|
||||
u_int16_t obsolete5;
|
||||
/*006*/ u_int16_t sectors; /* # sectors/track */
|
||||
/*007*/ u_int16_t vendor7[3];
|
||||
/*010*/ u_int8_t serial[20]; /* serial number */
|
||||
/*020*/ u_int16_t retired20;
|
||||
u_int16_t retired21;
|
||||
u_int16_t obsolete22;
|
||||
/*023*/ u_int8_t revision[8]; /* firmware revision */
|
||||
/*027*/ u_int8_t model[40]; /* model name */
|
||||
/*047*/ u_int16_t sectors_intr; /* sectors per interrupt */
|
||||
/*048*/ u_int16_t usedmovsd; /* double word read/write? */
|
||||
/*049*/ u_int16_t capabilities1;
|
||||
#define ATA_SUPPORT_DMA 0x0100
|
||||
#define ATA_SUPPORT_LBA 0x0200
|
||||
#define ATA_SUPPORT_OVERLAP 0x4000
|
||||
|
||||
/*050*/ u_int16_t capabilities2;
|
||||
/*051*/ u_int16_t retired_piomode; /* PIO modes 0-2 */
|
||||
#define ATA_RETIRED_PIO_MASK 0x0300
|
||||
/*050*/ u_int16_t capabilities2;
|
||||
/*051*/ u_int16_t retired_piomode; /* PIO modes 0-2 */
|
||||
#define ATA_RETIRED_PIO_MASK 0x0300
|
||||
|
||||
/*052*/ u_int16_t retired_dmamode; /* DMA modes */
|
||||
#define ATA_RETIRED_DMA_MASK 0x0003
|
||||
/*052*/ u_int16_t retired_dmamode; /* DMA modes */
|
||||
#define ATA_RETIRED_DMA_MASK 0x0003
|
||||
|
||||
/*053*/ u_int16_t atavalid; /* fields valid */
|
||||
#define ATA_FLAG_54_58 0x0001 /* words 54-58 valid */
|
||||
#define ATA_FLAG_64_70 0x0002 /* words 64-70 valid */
|
||||
#define ATA_FLAG_88 0x0004 /* word 88 valid */
|
||||
/*053*/ u_int16_t atavalid; /* fields valid */
|
||||
#define ATA_FLAG_54_58 0x0001 /* words 54-58 valid */
|
||||
#define ATA_FLAG_64_70 0x0002 /* words 64-70 valid */
|
||||
#define ATA_FLAG_88 0x0004 /* word 88 valid */
|
||||
|
||||
/*054*/ u_int16_t current_cylinders;
|
||||
/*055*/ u_int16_t current_heads;
|
||||
/*056*/ u_int16_t current_sectors;
|
||||
/*057*/ u_int16_t current_size_1;
|
||||
/*058*/ u_int16_t current_size_2;
|
||||
/*059*/ u_int16_t multi;
|
||||
#define ATA_MULTI_VALID 0x0100
|
||||
/*054*/ u_int16_t current_cylinders;
|
||||
/*055*/ u_int16_t current_heads;
|
||||
/*056*/ u_int16_t current_sectors;
|
||||
/*057*/ u_int16_t current_size_1;
|
||||
/*058*/ u_int16_t current_size_2;
|
||||
/*059*/ u_int16_t multi;
|
||||
#define ATA_MULTI_VALID 0x0100
|
||||
|
||||
/*060*/ u_int16_t lba_size_1;
|
||||
u_int16_t lba_size_2;
|
||||
u_int16_t obsolete62;
|
||||
/*063*/ u_int16_t mwdmamodes; /* multiword DMA modes */
|
||||
/*064*/ u_int16_t apiomodes; /* advanced PIO modes */
|
||||
/*060*/ u_int16_t lba_size_1;
|
||||
u_int16_t lba_size_2;
|
||||
u_int16_t obsolete62;
|
||||
/*063*/ u_int16_t mwdmamodes; /* multiword DMA modes */
|
||||
/*064*/ u_int16_t apiomodes; /* advanced PIO modes */
|
||||
|
||||
/*065*/ u_int16_t mwdmamin; /* min. M/W DMA time/word ns */
|
||||
/*066*/ u_int16_t mwdmarec; /* rec. M/W DMA time ns */
|
||||
/*067*/ u_int16_t pioblind; /* min. PIO cycle w/o flow */
|
||||
/*068*/ u_int16_t pioiordy; /* min. PIO cycle IORDY flow */
|
||||
u_int16_t reserved69;
|
||||
u_int16_t reserved70;
|
||||
/*071*/ u_int16_t rlsovlap; /* rel time (us) for overlap */
|
||||
/*072*/ u_int16_t rlsservice; /* rel time (us) for service */
|
||||
u_int16_t reserved73;
|
||||
u_int16_t reserved74;
|
||||
/*075*/ u_int16_t queue;
|
||||
#define ATA_QUEUE_LEN(x) ((x) & 0x001f)
|
||||
/*065*/ u_int16_t mwdmamin; /* min. M/W DMA time/word ns */
|
||||
/*066*/ u_int16_t mwdmarec; /* rec. M/W DMA time ns */
|
||||
/*067*/ u_int16_t pioblind; /* min. PIO cycle w/o flow */
|
||||
/*068*/ u_int16_t pioiordy; /* min. PIO cycle IORDY flow */
|
||||
u_int16_t reserved69;
|
||||
u_int16_t reserved70;
|
||||
/*071*/ u_int16_t rlsovlap; /* rel time (us) for overlap */
|
||||
/*072*/ u_int16_t rlsservice; /* rel time (us) for service */
|
||||
u_int16_t reserved73;
|
||||
u_int16_t reserved74;
|
||||
/*075*/ u_int16_t queue;
|
||||
#define ATA_QUEUE_LEN(x) ((x) & 0x001f)
|
||||
|
||||
u_int16_t satacapabilities;
|
||||
#define ATA_SATA_GEN1 0x0002
|
||||
#define ATA_SATA_GEN2 0x0004
|
||||
#define ATA_SUPPORT_NCQ 0x0100
|
||||
#define ATA_SUPPORT_IFPWRMNGTRCV 0x0200
|
||||
u_int16_t satacapabilities;
|
||||
#define ATA_SATA_GEN1 0x0002
|
||||
#define ATA_SATA_GEN2 0x0004
|
||||
#define ATA_SUPPORT_NCQ 0x0100
|
||||
#define ATA_SUPPORT_IFPWRMNGTRCV 0x0200
|
||||
|
||||
u_int16_t reserved77;
|
||||
u_int16_t satasupport;
|
||||
#define ATA_SUPPORT_NONZERO 0x0002
|
||||
#define ATA_SUPPORT_AUTOACTIVATE 0x0004
|
||||
#define ATA_SUPPORT_IFPWRMNGT 0x0008
|
||||
#define ATA_SUPPORT_INORDERDATA 0x0010
|
||||
u_int16_t sataenabled;
|
||||
u_int16_t reserved77;
|
||||
u_int16_t satasupport;
|
||||
#define ATA_SUPPORT_NONZERO 0x0002
|
||||
#define ATA_SUPPORT_AUTOACTIVATE 0x0004
|
||||
#define ATA_SUPPORT_IFPWRMNGT 0x0008
|
||||
#define ATA_SUPPORT_INORDERDATA 0x0010
|
||||
u_int16_t sataenabled;
|
||||
|
||||
/*080*/ u_int16_t version_major;
|
||||
/*081*/ u_int16_t version_minor;
|
||||
/*080*/ u_int16_t version_major;
|
||||
/*081*/ u_int16_t version_minor;
|
||||
|
||||
struct {
|
||||
/*082/085*/ u_int16_t command1;
|
||||
#define ATA_SUPPORT_SMART 0x0001
|
||||
#define ATA_SUPPORT_SECURITY 0x0002
|
||||
#define ATA_SUPPORT_REMOVABLE 0x0004
|
||||
#define ATA_SUPPORT_POWERMGT 0x0008
|
||||
#define ATA_SUPPORT_PACKET 0x0010
|
||||
#define ATA_SUPPORT_WRITECACHE 0x0020
|
||||
#define ATA_SUPPORT_LOOKAHEAD 0x0040
|
||||
#define ATA_SUPPORT_RELEASEIRQ 0x0080
|
||||
#define ATA_SUPPORT_SERVICEIRQ 0x0100
|
||||
#define ATA_SUPPORT_RESET 0x0200
|
||||
#define ATA_SUPPORT_PROTECTED 0x0400
|
||||
#define ATA_SUPPORT_WRITEBUFFER 0x1000
|
||||
#define ATA_SUPPORT_READBUFFER 0x2000
|
||||
#define ATA_SUPPORT_NOP 0x4000
|
||||
/*082/085*/ u_int16_t command1;
|
||||
#define ATA_SUPPORT_SMART 0x0001
|
||||
#define ATA_SUPPORT_SECURITY 0x0002
|
||||
#define ATA_SUPPORT_REMOVABLE 0x0004
|
||||
#define ATA_SUPPORT_POWERMGT 0x0008
|
||||
#define ATA_SUPPORT_PACKET 0x0010
|
||||
#define ATA_SUPPORT_WRITECACHE 0x0020
|
||||
#define ATA_SUPPORT_LOOKAHEAD 0x0040
|
||||
#define ATA_SUPPORT_RELEASEIRQ 0x0080
|
||||
#define ATA_SUPPORT_SERVICEIRQ 0x0100
|
||||
#define ATA_SUPPORT_RESET 0x0200
|
||||
#define ATA_SUPPORT_PROTECTED 0x0400
|
||||
#define ATA_SUPPORT_WRITEBUFFER 0x1000
|
||||
#define ATA_SUPPORT_READBUFFER 0x2000
|
||||
#define ATA_SUPPORT_NOP 0x4000
|
||||
|
||||
/*083/086*/ u_int16_t command2;
|
||||
#define ATA_SUPPORT_MICROCODE 0x0001
|
||||
#define ATA_SUPPORT_QUEUED 0x0002
|
||||
#define ATA_SUPPORT_CFA 0x0004
|
||||
#define ATA_SUPPORT_APM 0x0008
|
||||
#define ATA_SUPPORT_NOTIFY 0x0010
|
||||
#define ATA_SUPPORT_STANDBY 0x0020
|
||||
#define ATA_SUPPORT_SPINUP 0x0040
|
||||
#define ATA_SUPPORT_MAXSECURITY 0x0100
|
||||
#define ATA_SUPPORT_AUTOACOUSTIC 0x0200
|
||||
#define ATA_SUPPORT_ADDRESS48 0x0400
|
||||
#define ATA_SUPPORT_OVERLAY 0x0800
|
||||
#define ATA_SUPPORT_FLUSHCACHE 0x1000
|
||||
#define ATA_SUPPORT_FLUSHCACHE48 0x2000
|
||||
/*083/086*/ u_int16_t command2;
|
||||
#define ATA_SUPPORT_MICROCODE 0x0001
|
||||
#define ATA_SUPPORT_QUEUED 0x0002
|
||||
#define ATA_SUPPORT_CFA 0x0004
|
||||
#define ATA_SUPPORT_APM 0x0008
|
||||
#define ATA_SUPPORT_NOTIFY 0x0010
|
||||
#define ATA_SUPPORT_STANDBY 0x0020
|
||||
#define ATA_SUPPORT_SPINUP 0x0040
|
||||
#define ATA_SUPPORT_MAXSECURITY 0x0100
|
||||
#define ATA_SUPPORT_AUTOACOUSTIC 0x0200
|
||||
#define ATA_SUPPORT_ADDRESS48 0x0400
|
||||
#define ATA_SUPPORT_OVERLAY 0x0800
|
||||
#define ATA_SUPPORT_FLUSHCACHE 0x1000
|
||||
#define ATA_SUPPORT_FLUSHCACHE48 0x2000
|
||||
|
||||
/*084/087*/ u_int16_t extension;
|
||||
/*084/087*/ u_int16_t extension;
|
||||
} __packed support, enabled;
|
||||
|
||||
/*088*/ u_int16_t udmamodes; /* UltraDMA modes */
|
||||
/*089*/ u_int16_t erase_time;
|
||||
/*090*/ u_int16_t enhanced_erase_time;
|
||||
/*091*/ u_int16_t apm_value;
|
||||
/*092*/ u_int16_t master_passwd_revision;
|
||||
/*093*/ u_int16_t hwres;
|
||||
#define ATA_CABLE_ID 0x2000
|
||||
/*088*/ u_int16_t udmamodes; /* UltraDMA modes */
|
||||
/*089*/ u_int16_t erase_time;
|
||||
/*090*/ u_int16_t enhanced_erase_time;
|
||||
/*091*/ u_int16_t apm_value;
|
||||
/*092*/ u_int16_t master_passwd_revision;
|
||||
/*093*/ u_int16_t hwres;
|
||||
#define ATA_CABLE_ID 0x2000
|
||||
|
||||
/*094*/ u_int16_t acoustic;
|
||||
#define ATA_ACOUSTIC_CURRENT(x) ((x) & 0x00ff)
|
||||
#define ATA_ACOUSTIC_VENDOR(x) (((x) & 0xff00) >> 8)
|
||||
/*094*/ u_int16_t acoustic;
|
||||
#define ATA_ACOUSTIC_CURRENT(x) ((x) & 0x00ff)
|
||||
#define ATA_ACOUSTIC_VENDOR(x) (((x) & 0xff00) >> 8)
|
||||
|
||||
/*095*/ u_int16_t stream_min_req_size;
|
||||
/*096*/ u_int16_t stream_transfer_time;
|
||||
/*097*/ u_int16_t stream_access_latency;
|
||||
/*098*/ u_int32_t stream_granularity;
|
||||
/*100*/ u_int16_t lba_size48_1;
|
||||
u_int16_t lba_size48_2;
|
||||
u_int16_t lba_size48_3;
|
||||
u_int16_t lba_size48_4;
|
||||
u_int16_t reserved104[23];
|
||||
/*127*/ u_int16_t removable_status;
|
||||
/*128*/ u_int16_t security_status;
|
||||
u_int16_t reserved129[31];
|
||||
/*160*/ u_int16_t cfa_powermode1;
|
||||
u_int16_t reserved161[15];
|
||||
/*176*/ u_int16_t media_serial[30];
|
||||
u_int16_t reserved206[49];
|
||||
/*255*/ u_int16_t integrity;
|
||||
/*095*/ u_int16_t stream_min_req_size;
|
||||
/*096*/ u_int16_t stream_transfer_time;
|
||||
/*097*/ u_int16_t stream_access_latency;
|
||||
/*098*/ u_int32_t stream_granularity;
|
||||
/*100*/ u_int16_t lba_size48_1;
|
||||
u_int16_t lba_size48_2;
|
||||
u_int16_t lba_size48_3;
|
||||
u_int16_t lba_size48_4;
|
||||
u_int16_t reserved104[23];
|
||||
/*127*/ u_int16_t removable_status;
|
||||
/*128*/ u_int16_t security_status;
|
||||
u_int16_t reserved129[31];
|
||||
/*160*/ u_int16_t cfa_powermode1;
|
||||
u_int16_t reserved161[15];
|
||||
/*176*/ u_int16_t media_serial[30];
|
||||
u_int16_t reserved206[49];
|
||||
/*255*/ u_int16_t integrity;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* ATA transfer modes */
|
||||
#define ATA_MODE_MASK 0x0f
|
||||
#define ATA_DMA_MASK 0xf0
|
||||
#define ATA_PIO 0x00
|
||||
#define ATA_PIO0 0x08
|
||||
#define ATA_PIO1 0x09
|
||||
#define ATA_PIO2 0x0a
|
||||
#define ATA_PIO3 0x0b
|
||||
#define ATA_PIO4 0x0c
|
||||
#define ATA_PIO_MAX 0x0f
|
||||
#define ATA_DMA 0x10
|
||||
#define ATA_WDMA0 0x20
|
||||
#define ATA_WDMA1 0x21
|
||||
#define ATA_WDMA2 0x22
|
||||
#define ATA_UDMA0 0x40
|
||||
#define ATA_UDMA1 0x41
|
||||
#define ATA_UDMA2 0x42
|
||||
#define ATA_UDMA3 0x43
|
||||
#define ATA_UDMA4 0x44
|
||||
#define ATA_UDMA5 0x45
|
||||
#define ATA_UDMA6 0x46
|
||||
#define ATA_SA150 0x47
|
||||
#define ATA_DMA_MAX 0x4f
|
||||
#define ATA_MODE_MASK 0x0f
|
||||
#define ATA_DMA_MASK 0xf0
|
||||
#define ATA_PIO 0x00
|
||||
#define ATA_PIO0 0x08
|
||||
#define ATA_PIO1 0x09
|
||||
#define ATA_PIO2 0x0a
|
||||
#define ATA_PIO3 0x0b
|
||||
#define ATA_PIO4 0x0c
|
||||
#define ATA_PIO_MAX 0x0f
|
||||
#define ATA_DMA 0x10
|
||||
#define ATA_WDMA0 0x20
|
||||
#define ATA_WDMA1 0x21
|
||||
#define ATA_WDMA2 0x22
|
||||
#define ATA_UDMA0 0x40
|
||||
#define ATA_UDMA1 0x41
|
||||
#define ATA_UDMA2 0x42
|
||||
#define ATA_UDMA3 0x43
|
||||
#define ATA_UDMA4 0x44
|
||||
#define ATA_UDMA5 0x45
|
||||
#define ATA_UDMA6 0x46
|
||||
#define ATA_SA150 0x47
|
||||
#define ATA_DMA_MAX 0x4f
|
||||
|
||||
|
||||
/* ATA commands */
|
||||
#define ATA_NOP 0x00 /* NOP command */
|
||||
#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_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_FLUSHCACHE 0xe7 /* flush cache to disk */
|
||||
#define ATA_FLUSHCACHE48 0xea /* flush cache to disk */
|
||||
#define ATA_ATA_IDENTIFY 0xec /* get ATA params */
|
||||
#define ATA_SETFEATURES 0xef /* features command */
|
||||
#define ATA_SF_SETXFER 0x03 /* set transfer mode */
|
||||
#define ATA_SF_ENAB_WCACHE 0x02 /* enable write cache */
|
||||
#define ATA_SF_DIS_WCACHE 0x82 /* disable write cache */
|
||||
#define ATA_SF_ENAB_RCACHE 0xaa /* enable readahead cache */
|
||||
#define ATA_SF_DIS_RCACHE 0x55 /* disable readahead cache */
|
||||
#define ATA_SF_ENAB_RELIRQ 0x5d /* enable release interrupt */
|
||||
#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_NOP 0x00 /* NOP */
|
||||
#define ATA_NF_FLUSHQUEUE 0x00 /* flush queued cmd's */
|
||||
#define ATA_NF_AUTOPOLL 0x01 /* start autopoll function */
|
||||
#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_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 */
|
||||
#define ATA_SETFEATURES 0xef /* features command */
|
||||
#define ATA_SF_SETXFER 0x03 /* set transfer mode */
|
||||
#define ATA_SF_ENAB_WCACHE 0x02 /* enable write cache */
|
||||
#define ATA_SF_DIS_WCACHE 0x82 /* disable write cache */
|
||||
#define ATA_SF_ENAB_RCACHE 0xaa /* enable readahead cache */
|
||||
#define ATA_SF_DIS_RCACHE 0x55 /* disable readahead cache */
|
||||
#define ATA_SF_ENAB_RELIRQ 0x5d /* enable release interrupt */
|
||||
#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 */
|
||||
#define ATAPI_REZERO 0x01 /* rewind */
|
||||
#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */
|
||||
#define ATAPI_FORMAT 0x04 /* format unit */
|
||||
#define ATAPI_READ 0x08 /* read data */
|
||||
#define ATAPI_WRITE 0x0a /* write data */
|
||||
#define ATAPI_WEOF 0x10 /* write filemark */
|
||||
#define ATAPI_WF_WRITE 0x01
|
||||
#define ATAPI_SPACE 0x11 /* space command */
|
||||
#define ATAPI_SP_FM 0x01
|
||||
#define ATAPI_SP_EOD 0x03
|
||||
#define ATAPI_MODE_SELECT 0x15 /* mode select */
|
||||
#define ATAPI_ERASE 0x19 /* erase */
|
||||
#define ATAPI_MODE_SENSE 0x1a /* mode sense */
|
||||
#define ATAPI_START_STOP 0x1b /* start/stop unit */
|
||||
#define ATAPI_SS_LOAD 0x01
|
||||
#define ATAPI_SS_RETENSION 0x02
|
||||
#define ATAPI_SS_EJECT 0x04
|
||||
#define ATAPI_PREVENT_ALLOW 0x1e /* media removal */
|
||||
#define ATAPI_READ_FORMAT_CAPACITIES 0x23 /* get format capacities */
|
||||
#define ATAPI_READ_CAPACITY 0x25 /* get volume capacity */
|
||||
#define ATAPI_READ_BIG 0x28 /* read data */
|
||||
#define ATAPI_WRITE_BIG 0x2a /* write data */
|
||||
#define ATAPI_LOCATE 0x2b /* locate to position */
|
||||
#define ATAPI_READ_POSITION 0x34 /* read position */
|
||||
#define ATAPI_SYNCHRONIZE_CACHE 0x35 /* flush buf, close channel */
|
||||
#define ATAPI_WRITE_BUFFER 0x3b /* write device buffer */
|
||||
#define ATAPI_READ_BUFFER 0x3c /* read device buffer */
|
||||
#define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */
|
||||
#define ATAPI_READ_TOC 0x43 /* get table of contents */
|
||||
#define ATAPI_PLAY_10 0x45 /* play by lba */
|
||||
#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */
|
||||
#define ATAPI_PLAY_TRACK 0x48 /* play by track number */
|
||||
#define ATAPI_PAUSE 0x4b /* pause audio operation */
|
||||
#define ATAPI_READ_DISK_INFO 0x51 /* get disk info structure */
|
||||
#define ATAPI_READ_TRACK_INFO 0x52 /* get track info structure */
|
||||
#define ATAPI_RESERVE_TRACK 0x53 /* reserve track */
|
||||
#define ATAPI_SEND_OPC_INFO 0x54 /* send OPC structurek */
|
||||
#define ATAPI_MODE_SELECT_BIG 0x55 /* set device parameters */
|
||||
#define ATAPI_REPAIR_TRACK 0x58 /* repair track */
|
||||
#define ATAPI_READ_MASTER_CUE 0x59 /* read master CUE info */
|
||||
#define ATAPI_MODE_SENSE_BIG 0x5a /* get device parameters */
|
||||
#define ATAPI_CLOSE_TRACK 0x5b /* close track/session */
|
||||
#define ATAPI_READ_BUFFER_CAPACITY 0x5c /* get buffer capicity */
|
||||
#define ATAPI_SEND_CUE_SHEET 0x5d /* send CUE sheet */
|
||||
#define ATAPI_BLANK 0xa1 /* blank the media */
|
||||
#define ATAPI_SEND_KEY 0xa3 /* send DVD key structure */
|
||||
#define ATAPI_REPORT_KEY 0xa4 /* get DVD key structure */
|
||||
#define ATAPI_PLAY_12 0xa5 /* play by lba */
|
||||
#define ATAPI_LOAD_UNLOAD 0xa6 /* changer control command */
|
||||
#define ATAPI_READ_STRUCTURE 0xad /* get DVD structure */
|
||||
#define ATAPI_PLAY_CD 0xb4 /* universal play command */
|
||||
#define ATAPI_SET_SPEED 0xbb /* set drive speed */
|
||||
#define ATAPI_MECH_STATUS 0xbd /* get changer status */
|
||||
#define ATAPI_READ_CD 0xbe /* read data */
|
||||
#define ATAPI_POLL_DSC 0xff /* poll DSC status bit */
|
||||
#define ATAPI_TEST_UNIT_READY 0x00 /* check if device is ready */
|
||||
#define ATAPI_REZERO 0x01 /* rewind */
|
||||
#define ATAPI_REQUEST_SENSE 0x03 /* get sense data */
|
||||
#define ATAPI_FORMAT 0x04 /* format unit */
|
||||
#define ATAPI_READ 0x08 /* read data */
|
||||
#define ATAPI_WRITE 0x0a /* write data */
|
||||
#define ATAPI_WEOF 0x10 /* write filemark */
|
||||
#define ATAPI_WF_WRITE 0x01
|
||||
#define ATAPI_SPACE 0x11 /* space command */
|
||||
#define ATAPI_SP_FM 0x01
|
||||
#define ATAPI_SP_EOD 0x03
|
||||
#define ATAPI_MODE_SELECT 0x15 /* mode select */
|
||||
#define ATAPI_ERASE 0x19 /* erase */
|
||||
#define ATAPI_MODE_SENSE 0x1a /* mode sense */
|
||||
#define ATAPI_START_STOP 0x1b /* start/stop unit */
|
||||
#define ATAPI_SS_LOAD 0x01
|
||||
#define ATAPI_SS_RETENSION 0x02
|
||||
#define ATAPI_SS_EJECT 0x04
|
||||
#define ATAPI_PREVENT_ALLOW 0x1e /* media removal */
|
||||
#define ATAPI_READ_FORMAT_CAPACITIES 0x23 /* get format capacities */
|
||||
#define ATAPI_READ_CAPACITY 0x25 /* get volume capacity */
|
||||
#define ATAPI_READ_BIG 0x28 /* read data */
|
||||
#define ATAPI_WRITE_BIG 0x2a /* write data */
|
||||
#define ATAPI_LOCATE 0x2b /* locate to position */
|
||||
#define ATAPI_READ_POSITION 0x34 /* read position */
|
||||
#define ATAPI_SYNCHRONIZE_CACHE 0x35 /* flush buf, close channel */
|
||||
#define ATAPI_WRITE_BUFFER 0x3b /* write device buffer */
|
||||
#define ATAPI_READ_BUFFER 0x3c /* read device buffer */
|
||||
#define ATAPI_READ_SUBCHANNEL 0x42 /* get subchannel info */
|
||||
#define ATAPI_READ_TOC 0x43 /* get table of contents */
|
||||
#define ATAPI_PLAY_10 0x45 /* play by lba */
|
||||
#define ATAPI_PLAY_MSF 0x47 /* play by MSF address */
|
||||
#define ATAPI_PLAY_TRACK 0x48 /* play by track number */
|
||||
#define ATAPI_PAUSE 0x4b /* pause audio operation */
|
||||
#define ATAPI_READ_DISK_INFO 0x51 /* get disk info structure */
|
||||
#define ATAPI_READ_TRACK_INFO 0x52 /* get track info structure */
|
||||
#define ATAPI_RESERVE_TRACK 0x53 /* reserve track */
|
||||
#define ATAPI_SEND_OPC_INFO 0x54 /* send OPC structurek */
|
||||
#define ATAPI_MODE_SELECT_BIG 0x55 /* set device parameters */
|
||||
#define ATAPI_REPAIR_TRACK 0x58 /* repair track */
|
||||
#define ATAPI_READ_MASTER_CUE 0x59 /* read master CUE info */
|
||||
#define ATAPI_MODE_SENSE_BIG 0x5a /* get device parameters */
|
||||
#define ATAPI_CLOSE_TRACK 0x5b /* close track/session */
|
||||
#define ATAPI_READ_BUFFER_CAPACITY 0x5c /* get buffer capicity */
|
||||
#define ATAPI_SEND_CUE_SHEET 0x5d /* send CUE sheet */
|
||||
#define ATAPI_BLANK 0xa1 /* blank the media */
|
||||
#define ATAPI_SEND_KEY 0xa3 /* send DVD key structure */
|
||||
#define ATAPI_REPORT_KEY 0xa4 /* get DVD key structure */
|
||||
#define ATAPI_PLAY_12 0xa5 /* play by lba */
|
||||
#define ATAPI_LOAD_UNLOAD 0xa6 /* changer control command */
|
||||
#define ATAPI_READ_STRUCTURE 0xad /* get DVD structure */
|
||||
#define ATAPI_PLAY_CD 0xb4 /* universal play command */
|
||||
#define ATAPI_SET_SPEED 0xbb /* set drive speed */
|
||||
#define ATAPI_MECH_STATUS 0xbd /* get changer status */
|
||||
#define ATAPI_READ_CD 0xbe /* read data */
|
||||
#define ATAPI_POLL_DSC 0xff /* poll DSC status bit */
|
||||
|
||||
struct ata_cmd {
|
||||
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;
|
||||
|
||||
struct {
|
||||
union {
|
||||
struct {
|
||||
u_int8_t command;
|
||||
u_int8_t feature;
|
||||
u_int64_t lba;
|
||||
u_int16_t count;
|
||||
} ata;
|
||||
struct {
|
||||
char ccb[16];
|
||||
} atapi;
|
||||
} u;
|
||||
caddr_t data;
|
||||
int count;
|
||||
int flags;
|
||||
#define ATA_CMD_CONTROL 0x01
|
||||
#define ATA_CMD_READ 0x02
|
||||
#define ATA_CMD_WRITE 0x04
|
||||
#define ATA_CMD_ATAPI 0x08
|
||||
|
||||
int timeout;
|
||||
int error;
|
||||
} request;
|
||||
|
||||
struct raid_setup {
|
||||
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
|
||||
|
||||
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
|
||||
#define AR_DEGRADED 2
|
||||
#define AR_REBUILDING 4
|
||||
|
||||
int progress;
|
||||
} raid_status;
|
||||
|
||||
struct {
|
||||
int disk;
|
||||
} raid_spare;
|
||||
|
||||
struct {
|
||||
int fan;
|
||||
int temp;
|
||||
int v05;
|
||||
int v12;
|
||||
} enclosure;
|
||||
} u;
|
||||
struct ata_ioc_devices {
|
||||
int channel;
|
||||
char name[2][32];
|
||||
struct ata_params params[2];
|
||||
};
|
||||
|
||||
#define IOCATA _IOWR('a', 1, struct ata_cmd)
|
||||
/* 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 ata_ioc_request {
|
||||
union {
|
||||
struct {
|
||||
u_int8_t command;
|
||||
u_int8_t feature;
|
||||
u_int64_t lba;
|
||||
u_int16_t count;
|
||||
} ata;
|
||||
struct {
|
||||
char ccb[16];
|
||||
} atapi;
|
||||
} u;
|
||||
caddr_t data;
|
||||
int count;
|
||||
int flags;
|
||||
#define ATA_CMD_CONTROL 0x01
|
||||
#define ATA_CMD_READ 0x02
|
||||
#define ATA_CMD_WRITE 0x04
|
||||
#define ATA_CMD_ATAPI 0x08
|
||||
|
||||
int timeout;
|
||||
int error;
|
||||
};
|
||||
|
||||
/* 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 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 interleave;
|
||||
int status;
|
||||
#define AR_READY 1
|
||||
#define AR_DEGRADED 2
|
||||
#define AR_REBUILDING 4
|
||||
|
||||
int progress;
|
||||
int total_disks;
|
||||
int disks[16];
|
||||
};
|
||||
|
||||
/* 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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user