2010-03-22 18:18:04     pata_pcmcia CompactFLASH load error

Document created by Aaronwu Employee on Aug 21, 2013
Version 1Show Document
  • View in full screen mode

2010-03-22 18:18:04     pata_pcmcia CompactFLASH load error


Message: 87593   


I am running the 2009R1.1-RC4 tag distro on a BF537 based board.  Configured on

this board is a pcmcia slot used for interfacing a compactflash drive.  I am

using the blackfin pcmcia adapter and the pata_pcmcia driver with ATA SFF

support for the device drivers.  I am building these devices as loadable modules.


I have a situation where occasionally the compact flash card is not

recognized by the pata_pcmcia driver.when the driver is loading.  I have tracked

the problem to after the soft reset performed by the ata_sff_softreset function.

(It writes an 0xe to the device control register).  After the reset is

complete, the taskfile error register is read by ata_sff_dev_classify.  If the

function reads an error, the drive is not recognized.


The occurrence of the above error sequence is relatively rare.  However, once an error is

detected, it stays on the CF device until a power cycle.  Even strobing the

reset line to the device for > 200 mS will not clear the error.  After the power

cycle, the compact flash comes up and does not report any error.


The errors are not always consistent.  I have seen 0x93 and 0xd2 reported in the error



Is there a way to clear the error reported by the error task file register?  Is

there something I am missing in the load sequence?





Doug Bailey




2010-03-22 23:08:34     Re: pata_pcmcia CompactFLASH load error

Sonic Zhang (CHINA)

Message: 87598   


Please following the instruction in   docs.blackfin.uclinux.org/doku.php?id=linux-kernel:drivers:bfin_cf_pcmcia


and use blackfin specific cf pcmcia driver instead.




2010-03-23 10:02:22     Re: pata_pcmcia CompactFLASH load error


Message: 87619   


Is there any advantage in using the old IDE driver over the libata based driver?  Any anecdotal evidence that one is superior to the other?




2010-03-23 15:22:02     Re: pata_pcmcia CompactFLASH load error

Mike Frysinger (UNITED STATES)

Message: 87626   


the old ide driver has been punted while the libata one is supported going forward ...




2010-03-24 15:03:40     Re: pata_pcmcia CompactFLASH load error


Message: 87674   


This indicates that I need to use the pata_pcmcia driver that uses the libata

library.  This means that I need to overcome the problem where my drive is

sometimes not detected.


This issue manifests itself in the with ata_sff_softreset function in libata-sff.c

and its use of ata_sff_dev_classify to determine the type of device that it is interfacing.


After perfroming a soft reset, the ata_sff_dev_classify function reads the error

register (offset 1) of the taskfile registers.  It uses this value as a

qualifier to filter out return values indicating non ATA drive types.  I am

missing something here as I do not see where in the ATAPI spec it indicates that

the error register has any diagnostic value to be used for this purpose.

Further, the ATAPI spec indicates that the ERR bit in the status register

(offset 7) should be checked to indicate if the error register contents are

meaningful.  Yet, the ata_sff_dev_classify simply uses the error register contents

looking for a signature that I have not seen decribed.


Can anyone point me to a reference in the ATAPI spec that details the motivation

behind the ata_sff_dev_classify function's logic?



---------- The functions in question -------------------


int ata_sff_softreset(struct ata_link *link, unsigned int *classes,

              unsigned long deadline)


    struct ata_port *ap = link->ap;

    unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;

    unsigned int devmask = 0;

    int rc;

    u8 err;




    /* determine if device 0/1 are present */

    if (ata_devchk(ap, 0))

        devmask |= (1 << 0);

    if (slave_possible && ata_devchk(ap, 1))

        devmask |= (1 << 1);


    /* select device 0 again */

    ap->ops->sff_dev_select(ap, 0);


    /* issue bus reset */

    DPRINTK("about to softreset, devmask=%x\n", devmask);

    rc = ata_bus_softreset(ap, devmask, deadline);

    /* if link is occupied, -ENODEV too is an error */

    if (rc && (rc != -ENODEV || sata_scr_valid(link))) {

        ata_link_printk(link, KERN_ERR, "SRST failed (errno=%d)\n", rc);

        return rc;



    /* determine by signature whether we have ATA or ATAPI devices */

    classes[0] = ata_sff_dev_classify(&link->device[0],

                      devmask & (1 << 0), &err);

    if (slave_possible && err != 0x81)

        classes[1] = ata_sff_dev_classify(&link->device[1],

                          devmask & (1 << 1), &err);


    DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);

    return 0;





unsigned int ata_sff_dev_classify(struct ata_device *dev, int present,

                  u8 *r_err)


    struct ata_port *ap = dev->link->ap;

    struct ata_taskfile tf;

    unsigned int class;

    u8 err;


    ap->ops->sff_dev_select(ap, dev->devno);


    memset(&tf, 0, sizeof(tf));


    ap->ops->sff_tf_read(ap, &tf);

    err = tf.feature;

    if (r_err)

        *r_err = err;


    /* see if device passed diags: continue and warn later */

    if (err == 0)

        /* diagnostic fail : do nothing _YET_ */

        dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;

    else if (err == 1)

        /* do nothing */ ;

    else if ((dev->devno == 0) && (err == 0x81))

        /* do nothing */ ;


        return ATA_DEV_NONE;


    /* determine if device is ATA or ATAPI */

    class = ata_dev_classify(&tf);


    if (class == ATA_DEV_UNKNOWN) {

        /* If the device failed diagnostic, it's likely to

         * have reported incorrect device signature too.

         * Assume ATA device if the device seems present but

         * device signature is invalid with diagnostic

         * failure.


        if (present && (dev->horkage & ATA_HORKAGE_DIAGNOSTIC))

            class = ATA_DEV_ATA;


            class = ATA_DEV_NONE;

    } else if ((class == ATA_DEV_ATA) &&

           (ap->ops->sff_check_status(ap) == 0))

        class = ATA_DEV_NONE;


    return class;