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