Modifying code using ata_cmd to FBSD 6.0-Release
Matthew Hagerty
matthew at digitalstratum.com
Mon Nov 14 16:11:54 GMT 2005
Greetings,
I'm trying to use a AoE (ata over ethernet) EtherDrive (from
coraid.com), but their "FreeBSD 6.0" kernel patch seems to have been
developed against 6.0 early on, or they just renamed the 5.x patch and
hoped no one would notice. Needless to say, the patch fails to compile
because they are using the ata_cmd struct, which seems to have been
totally rewritten in 6.0.
I don't know very much about kernel hacking (yet) and I'm hoping to be
able to just replace some structure references and a few defines and get
things working. My initial problems are trying to find references to
tie all this together. I cannot seem to find much documentation on GEOM
or how to add new 'services' (correct term?) to the kernel, hence my
post here for help.
I have isolated the parts of the patch that seem to reference the old
struct, listed below. I looked at the old ata_cmd struct (from a 5.4
install) and found a new ata_ioc_request struct that seems to contain
almost all the members (that I need) that were used from the old ata_cmd
struct, so is it feasible that I can simply re-cast against
ata_ioc_request and change the references?
Here are the members that are currently used:
struct ata_cmd *iocmd;
iocmd->cmd
iocmd->u.request.count
iocmd->u.request.data
iocmd->u.request.u.ata.count
iocmd->u.request.u.ata.command
iocmd->u.request.u.ata.feature
iocmd->u.request.timeout
iocmd->u.request.u.ata.lba
The only reference that is not in ata_ioc_request is the 'cmd' member,
which is used in the code like this:
if (iocmd->cmd != ATAREQUEST) {
Which leads me to the other problem I'm having. Two defines are used
that I cannot reliably find a replacement for:
IOCATA
ATAREQUEST
I did find a IOCATAREQUEST that could maybe be the replacement for
ATAREQUEST? But as for IOCATA, I can find nothing that seem cut and dry.
Last, the function that uses the ata_cmd struct the most (there is one
other, but it does nothing new) seems to be called by GEOM? The only
reference to the function call is while creating a new disk with
disk_create(), like this:
struct disk *disk;
...
disk = disk_alloc();
...
disk->d_ioctl = aoeblk_ioctl;
...
disk_create(disk, DISK_VERSION_00);
What I can't find is where GEOM defines the prototypes for the functions
it can call (d_open, d_close, d_strategy, d_ioctl, d_dump), but the
prototype for the aoeblk_ioctl() function has the ata_cmd struct passed
in as a void pointer and casts it to ata_cmd... So how do I know what
kind of data the GEOM system is passing the function for any given
call? I see there is a 'cmd' parameter (unrelated to the above
ioctl->cmd), but without docs for each of the the disk_create() support
functions, I can't really tell how to use it.
I've included (for reference) the two main functions below that I need
to modify. Any insight would be greatly appreciated as to how I can
proceed with the modifications, or where I can get more documentation
about the ata.h changes, disk_create() function prototypes, etc..
Thank you,
Matthew
/*
* Ioctl only for select smartmontools ata commands.
* We fake out the ATAREQUEST ata ioctl -- ugly, but
effective.
*/
static int
aoeblk_ioctl(struct disk *disk, ulong cmd, void *vp, int flag, struct
thread *td)
{
struct ata_cmd *iocmd;
Aoedev *d;
int n;
if (cmd != IOCATA) {
log(LOG_INFO, "aoe: aoeblk_ioctl: cmd %ld not
IOCATA.\n", cmd);
return ENOTTY;
}
iocmd = (struct ata_cmd *) vp;
if (iocmd == NULL) {
log(LOG_INFO, "aoe: aoeblk_ioctl: NULL arg ptr.\n");
return EINVAL;
}
if (iocmd->cmd != ATAREQUEST) {
log(LOG_INFO, "aoe: aoeblk_ioctl: unknown
iocmd->cmd=%d\n", iocmd->cmd);
return ENOTTY;
}
if (iocmd->u.request.count) {
if (iocmd->u.request.data == NULL) {
log(LOG_INFO, "aoe: aoeblk_ioctl: null return
data pointer\n");
return EINVAL;
}
iocmd->u.request.count = 512;
iocmd->u.request.u.ata.count = 1;
}
d = disk->d_drv1;
mtx_lock(&d->mtx);
if ((d->flags & DEVFL_UP) == 0) {
log(LOG_INFO, "aoe: aoeblk_ioctl: device for unit %ld is
not up.\n", d->unit);
mtx_unlock(&d->mtx);
return ENXIO;
}
switch (iocmd->u.request.u.ata.command) {
case ATA_ATA_IDENTIFY:
copyout(d->ident, iocmd->u.request.data, sizeof d->ident);
mtx_unlock(&d->mtx);
return 0;
case ATA_SMART:
if (iocmd->u.request.u.ata.feature !=
ATA_SMART_ATTR_AUTOSAVE) {
n = aoecmd_ata_smart(d, iocmd);
mtx_unlock(&d->mtx);
return n;
}
default:
mtx_unlock(&d->mtx);
log(LOG_INFO, "aoe: aoeblk_ioctl: unallowed ata command; "
"cmd=%2.2X feat=%2.2X.\n",
iocmd->u.request.u.ata.command,
iocmd->u.request.u.ata.feature);
return EINVAL;
}
}
static void
disk_create_task(void *ctx, int useless)
{
struct disk *disk;
Aoedev *d;
d = (Aoedev *) ctx;
disk = disk_alloc(); /* Disk_destroy triggers freeing the
allocated disk. */
if (disk == NULL) {
log(LOG_INFO, "aoe: disk_create_task: cannot alloc disk
structure.\n");
mtx_lock(&d->mtx);
d->flags &= ~DEVFL_TASKON;
mtx_unlock(&d->mtx);
return;
}
d->disk = disk;
disk->d_drv1 = d;
disk->d_maxsize = DFLTPHYS;
disk->d_sectorsize = DEV_BSIZE;
disk->d_mediasize = DEV_BSIZE * d->nsectors;
disk->d_unit = d->unit;
disk->d_name = "aoed";
disk->d_open = aoeblk_open;
disk->d_close = aoeblk_close;
disk->d_ioctl = aoeblk_ioctl;
disk->d_strategy = aoeblk_strategy;
disk_create(disk, DISK_VERSION_00);
mtx_lock(&d->mtx);
d->flags &= ~DEVFL_TASKON;
d->flags |= DEVFL_UP;
mtx_unlock(&d->mtx);
}
More information about the freebsd-hackers
mailing list