[Kos-dev] contrôleurs ATA tertiaire et quaternaire

Christophe kos-dev@enix.org
Mon, 25 Feb 2002 16:30:30 +0100


Il se trouve que je possède une carte Promise UltraDMA 100 de Matrox : ça me
permet d'avoir en tout pour tout jusq'à 8 périphérique ATA/ATAPI au lieu de
4. Je pourrais soit ajouter du code pour gérer cette carte ou créer un autre
module compatible avec l'ide existant. Qu'en penses-tu Thomas ?

Une petite option à ajouter dans l'ide.c serait la possibilité de définir un
callback avec un cookie lors d'un transfert à partir ou vers le contrôleur.
Si ce callback est nul, alors on utilise le transfert habituel du secteur ou
du groupe de secteur, sinon on appelle ce callback pour qu'il gère lui-même
ce transfert. Je vois ça juste comme une option.

En revanche, je l'utilisais pour le SH1 car il est big endian et c'est assez
chiant de faire des transferts en swappant les octets dans un secteur (pour
que le secteur est la même qu'un PC aurait) puis plus tard les reswaper pour
pouvoir accéder en mot 32-bits aux entrées de cluster par exemple. En
utilisant ce callback, j'avais juste à faire :

void callback_in (short *data) {
    int i;
    for (i = 128; i; --i, data += 2) {
        data[1] = inb (ATA_DATA);
        data[0] = inb (ATA_DATA);
    }
}

void callback_out (short *data) {
    int i;
    for (i = 128; i; --i, data += 2) {
         outb (data[1],ATA_DATA);
         outb (data[0],ATA_DATA);
    }
}

Et là j'étais sûr que la zone de mémoire où je transférais le secteur de FAT
était directement exploitable par FAT.C

Mais je suis d'accord, il y a probablement moins d'intérêt pour le PC.

Ah oui j'utilise ce même système de callback pour les commandes ATA liées à
la sécurité par mot de passe.

Voici un code exemple (simplifié) :

////////////////////////////////////////////////////////////////////////////
//////////
// SECURITY FEATURES :
//////////////////////
// - SET PASSWORD
// - UNLOCK
// - ERASE PASSWORD
// - FREEZE LOCK
// - DISABLE PASSWORD
//
////////////////////////////////////////////////////////////////////////////
//////////

struct security_password_cookie {
    char const *password;
    short flags;
};

static int security_transfer_password  (
    char command,
    struct security_password_cookie *cookie
) {
    if (!ata_device_is_ready ())
        return 0;
    outb((char)command,ATA_CMD);
    if (ata_device_waits_for_transfer ()) {
        int i;
        char const *password = cookie->password;
        // OUTPUT FLAGS TO TELL IT
        // IF IT IS A USER OR MASTER
        // PASSWORD
        outw(cookie->flags,ATA_DATA) ;
        // OUTPUT PASSWORD
        // (32 CHARACTERS MAX)
        for (i = 16; i; --i,password += 2)
            outw(*((short *)password),ATA_DATA);
        // OUTPUT DUMMY WORDS
        // FOR TRANSFER COMPLETION
        for (i = 256 - 16 - 1; i; --i)
            outw(0,ATA_DATA);
    }else
        return 0;
    return ata_device_is_ready ();
}

int ata_security_set_password (
    char const password[32],
    short flags
) {
    struct security_password_cookie cookie = {
        password,
        flags /* bit 0 : 0(USER)/1(MASTER); bit 8 : 0(HIGH)/1(MAXIMUM)
SECURITY LEVEL */
     };
    return security_transfer_password
(ATA_CMD_SECURITY_SET_PASSWORD,&cookie);
}

int ata_security_unlock (
    char const password[32],
    short flags
) {
    struct security_password_cookie cookie = {
        password,
        flags /* bit 0 : 0(USER)/1(MASTER);  */
    };
    return security_transfer_password (ATAR_CMD_SECURITY_UNLOCK,&cookie);
}

int ata_security_erase_password (
    char const password[32],
    char flags
) {
    struct security_password_cookie cookie =
      { password, flags /* bit 0 : 0(USER)/1(MASTER); bit 1 :
0(NORMAL)/1(ENHANCED) ERASE */ };
    if (!ata_device_is_ready ())
      return 0;
    QI(ATAR_CMD) = (char)(ATAR_CMD_SECURITY_ERASE_PREPARE);
    return security_transfer_password
(ATAR_CMD_SECURITY_ERASE_UNIT,&cookie);
  }

int ata_security_freeze_lock (void) {
    if (!ata_device_is_ready ())
        return 0;
    outb((char)(ATAR_CMD_SECURITY_FREEZE_LOCK),ATA_CMD);
    return ata_device_is_ready ();
}

int ata_security_disable_password (
    char const password[32],
    char flags
) {
    struct security_password_cookie cookie = {
        password,
        flags /* bit 0 : 0(USER)/1(MASTER);  */
    };
    return security_transfer_password
(ATAR_CMD_SECURITY_DISABLE_PASSWORD,&cookie);
}