Skip to content
Snippets Groups Projects
Commit fb9e9d40 authored by arvoreen's avatar arvoreen
Browse files

Fixes to FreeBSD ATA device recognition. I was making a bad assumption about

how to convert DEVNAME (ad0,ad1) to channel/unit number.  If you have an ATA
CD on say channel 0, device 1 (slave on first ATA channel) and hard drives on
channel 0, unit 0 and channel 1, unit 0 (master on first 2 ATA channels), the
names are still ad0, ad1 for the drives, and acd0 for the CD.  So my magic
of taking the digit and dividing by 2 doesn't work.  Instead, we now scan
through all ATA devices to match name.

Thanks to Sean Kelly for discovering the flaw.


git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@1105 4ea69e1a-61f1-4043-bf83-b5c94c648137
parent feef474e
No related branches found
No related tags found
No related merge requests found
CHANGELOG for smartmontools CHANGELOG for smartmontools
$Id: CHANGELOG,v 1.207 2003/10/12 19:21:57 arvoreen Exp $ $Id: CHANGELOG,v 1.208 2003/10/13 02:28:15 arvoreen Exp $
Maintainers / Developers Key: Maintainers / Developers Key:
[BA] Bruce Allen [BA] Bruce Allen
...@@ -21,6 +21,9 @@ CURRENT DEVELOPMENT VERSION (see VERSION file in this directory): ...@@ -21,6 +21,9 @@ CURRENT DEVELOPMENT VERSION (see VERSION file in this directory):
<ADDITIONS TO THE CHANGE LOG SHOULD BE ADDED HERE, PLEASE> <ADDITIONS TO THE CHANGE LOG SHOULD BE ADDED HERE, PLEASE>
[EM] Fix first user found bug....I guess I was making the wrong assumption
on how to convert ATA devnames to channel/unit numbers.
[EM] Allow for option --enable-sample to append '.sample' to installed [EM] Allow for option --enable-sample to append '.sample' to installed
smartd.conf and rc script files. Also, let rc script shell setting smartd.conf and rc script files. Also, let rc script shell setting
be determined by configure be determined by configure
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include "utility.h" #include "utility.h"
#include "os_freebsd.h" #include "os_freebsd.h"
const char *os_XXXX_c_cvsid="$Id: os_freebsd.c,v 1.15 2003/10/12 09:10:03 ballen4705 Exp $" \ const char *os_XXXX_c_cvsid="$Id: os_freebsd.c,v 1.16 2003/10/13 02:28:15 arvoreen Exp $" \
ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
// to hold onto exit code for atexit routine // to hold onto exit code for atexit routine
...@@ -409,6 +409,50 @@ int escalade_command_interface(int fd, int disknum, smart_command_set command, i ...@@ -409,6 +409,50 @@ int escalade_command_interface(int fd, int disknum, smart_command_set command, i
return -1; return -1;
} }
static int get_ata_channel_unit ( const char* name, int* unit, int* dev) {
// there is no direct correlation between name 'ad0, ad1, ...' and
// channel/unit number. So we need to iterate through the possible
// channels and check each unit to see if we match names
struct ata_cmd iocmd;
int fd,maxunit;
bzero(&iocmd, sizeof(struct ata_cmd));
if ((fd = open("/dev/ata", O_RDWR)) < 0)
return -errno;
iocmd.cmd = ATAGMAXCHANNEL;
if (ioctl(fd, IOCATA, &iocmd) < 0) {
return -errno;
close(fd);
}
maxunit = iocmd.u.maxchan;
for (*unit = 0; *unit < maxunit; (*unit)++) {
iocmd.channel = *unit;
iocmd.device = -1;
iocmd.cmd = ATAGPARM;
if (ioctl(fd, IOCATA, &iocmd) < 0) {
close(fd);
return -errno;
}
if (iocmd.u.param.type[0] && !strcmp(name,iocmd.u.param.name[0])) {
*dev = 0;
break;
}
if (iocmd.u.param.type[1] && !strcmp(name,iocmd.u.param.name[1])) {
*dev = 1;
break;
}
}
close(fd);
if (*unit == maxunit)
return -1;
else
return 0;
}
// Guess device type (ata or scsi) based on device name (FreeBSD // Guess device type (ata or scsi) based on device name (FreeBSD
// specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst, // specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst,
// osst, nosst and sg. // osst, nosst and sg.
...@@ -438,10 +482,10 @@ static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel ...@@ -438,10 +482,10 @@ static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel
// form /dev/ad* or ad* // form /dev/ad* or ad*
if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name, if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name,
strlen(fbsd_dev_ata_disk_prefix))) { strlen(fbsd_dev_ata_disk_prefix))) {
int devnum = *(dev_name += strlen(fbsd_dev_ata_disk_prefix)) - '0';
if (chan != NULL) { if (chan != NULL) {
chan->channel=devnum/2; // 2 drives per channel if (get_ata_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
chan->device=devnum%2; // so dividend = channel, remainder=device return GUESS_DEVTYPE_DONT_KNOW;
}
} }
return GUESS_DEVTYPE_ATA; return GUESS_DEVTYPE_ATA;
} }
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include "utility.h" #include "utility.h"
#include "os_freebsd.h" #include "os_freebsd.h"
const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.15 2003/10/12 09:10:03 ballen4705 Exp $" \ const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp,v 1.16 2003/10/13 02:28:15 arvoreen Exp $" \
ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; ATACMDS_H_CVSID CONFIG_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
// to hold onto exit code for atexit routine // to hold onto exit code for atexit routine
...@@ -409,6 +409,50 @@ int escalade_command_interface(int fd, int disknum, smart_command_set command, i ...@@ -409,6 +409,50 @@ int escalade_command_interface(int fd, int disknum, smart_command_set command, i
return -1; return -1;
} }
static int get_ata_channel_unit ( const char* name, int* unit, int* dev) {
// there is no direct correlation between name 'ad0, ad1, ...' and
// channel/unit number. So we need to iterate through the possible
// channels and check each unit to see if we match names
struct ata_cmd iocmd;
int fd,maxunit;
bzero(&iocmd, sizeof(struct ata_cmd));
if ((fd = open("/dev/ata", O_RDWR)) < 0)
return -errno;
iocmd.cmd = ATAGMAXCHANNEL;
if (ioctl(fd, IOCATA, &iocmd) < 0) {
return -errno;
close(fd);
}
maxunit = iocmd.u.maxchan;
for (*unit = 0; *unit < maxunit; (*unit)++) {
iocmd.channel = *unit;
iocmd.device = -1;
iocmd.cmd = ATAGPARM;
if (ioctl(fd, IOCATA, &iocmd) < 0) {
close(fd);
return -errno;
}
if (iocmd.u.param.type[0] && !strcmp(name,iocmd.u.param.name[0])) {
*dev = 0;
break;
}
if (iocmd.u.param.type[1] && !strcmp(name,iocmd.u.param.name[1])) {
*dev = 1;
break;
}
}
close(fd);
if (*unit == maxunit)
return -1;
else
return 0;
}
// Guess device type (ata or scsi) based on device name (FreeBSD // Guess device type (ata or scsi) based on device name (FreeBSD
// specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst, // specific) SCSI device name in FreeBSD can be sd, sr, scd, st, nst,
// osst, nosst and sg. // osst, nosst and sg.
...@@ -438,10 +482,10 @@ static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel ...@@ -438,10 +482,10 @@ static int parse_ata_chan_dev(const char * dev_name, struct freebsd_dev_channel
// form /dev/ad* or ad* // form /dev/ad* or ad*
if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name, if (!strncmp(fbsd_dev_ata_disk_prefix, dev_name,
strlen(fbsd_dev_ata_disk_prefix))) { strlen(fbsd_dev_ata_disk_prefix))) {
int devnum = *(dev_name += strlen(fbsd_dev_ata_disk_prefix)) - '0';
if (chan != NULL) { if (chan != NULL) {
chan->channel=devnum/2; // 2 drives per channel if (get_ata_channel_unit(dev_name,&(chan->channel),&(chan->device))<0) {
chan->device=devnum%2; // so dividend = channel, remainder=device return GUESS_DEVTYPE_DONT_KNOW;
}
} }
return GUESS_DEVTYPE_ATA; return GUESS_DEVTYPE_ATA;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment