[Kos-dev] IDE Eclairage :)
Laurent
pelat_a at epita.fr
Thu Apr 28 17:45:00 CEST 2005
Salut a tous, j'ai pas mal regarde vos sources et plus particulierement
la partie IDE qui m'interesse vraiment.
Y'a plusieurs trucs que je ne comprends pas, peut etre que vous pouvez m'eclairer ;)
Bon mon post va etre long... desole pour les petits joueurs ;)
Voici le morceau de code que j'ai du mal a cerner.
J'ai mis des commentaires pour que vous puissiez me suivre ;)
static result_t _ide_init_controller(ide_controller_t *ctrl)
{
int status0, status1;
int mask = 0;
int timeout;
/* COMMENTAIRE
** 1 ere Partie, On recupere le status des devices (disques durs)
** Si les devices sont occupes ou non presents on retourne :)
*/
/* Get status of controllers */
outb(ATA_D_IBM | ATA_D_MASTER, ctrl->ioaddr + ATA_DRIVE);
udelay(1);
status0 = inb(ctrl->ioaddr + ATA_STATUS);
outb(ATA_D_IBM | ATA_D_SLAVE, ctrl->ioaddr + ATA_DRIVE);
udelay(1);
status1 = inb(ctrl->ioaddr + ATA_STATUS);
if((status0 & 0xf8) != 0xf8)
mask |= 0x01;
if((status1 & 0xf8) != 0xf8)
mask |= 0x02;
/* If both BSY bit are set => leave */
if((status0 & ATA_S_BSY) && (status1 & ATA_S_BSY))
return ESUCCESS;
/* no device present */
if(!mask)
return ESUCCESS;
/* COMMENTAIRE
** 2eme Partie, on reset le controleur, on desactive les interruptions
** On recupere le status des devices (disques durs)
** Si les devices sont occupes ou non presents on retourne :)
*/
/* select the master */
outb(ATA_D_IBM | ATA_D_MASTER, ctrl->ioaddr + ATA_DRIVE);
usleep(1);
/* send reset */
outb(ATA_A_nIEN | ATA_A_RESET, ctrl->ioaddr + ATA_DEVICE_CONTROL);
udelay(1);
outb(ATA_A_nIEN, ctrl->ioaddr + ATA_DEVICE_CONTROL);
udelay(1);
inb(ctrl->ioaddr + ATA_ERROR);
outb(ATA_A_4BIT, ctrl->ioaddr + ATA_DEVICE_CONTROL);
udelay(1);
/* wait busy */
for(timeout = 0; timeout < 300000; timeout++)
{
/* select master and get status register */
outb(ATA_D_IBM | ATA_D_MASTER, ctrl->ioaddr + ATA_DRIVE);
udelay(1);
status0 = inb(ctrl->ioaddr + ATA_STATUS);
/* select slave and get status register */
outb(ATA_D_IBM | ATA_D_SLAVE, ctrl->ioaddr + ATA_DRIVE);
udelay(1);
status1 = inb(ctrl->ioaddr + ATA_STATUS);
if(mask == 0x01)
if(!(status0 & ATA_S_BSY))
break;
if(mask == 0x02)
if(!(status1 & ATA_S_BSY))
break;
if(mask == 0x03)
if(!(status0 & ATA_S_BSY) && !(status1 & ATA_S_BSY))
break;
udelay(1);
}
if(status0 & ATA_S_BSY)
mask &= ~0x01;
if(status1 & ATA_S_BSY)
mask &= ~0x02;
/* no device */
if(!mask)
return ESUCCESS;
Question 1:
-----------
Pourquoi est on oblige de passer par la partie 1?
Pourquoi ne pas "reseter" directement le controleur
et regarder le status des devices?
Question 2:
-----------
/* send reset */
outb(ATA_A_nIEN | ATA_A_RESET, ctrl->ioaddr + ATA_DEVICE_CONTROL);
udelay(1);
outb(ATA_A_nIEN, ctrl->ioaddr + ATA_DEVICE_CONTROL);
udelay(1);
Quel interet de desactiver 2 fois a la suite les interruptions?
Question 3:
-----------
outb(ATA_A_nIEN, ctrl->ioaddr + ATA_DEVICE_CONTROL);
udelay(1);
inb(ctrl->ioaddr + ATA_ERROR);
Quel est l'interet de ce inb? vu qu'on ne recupere aucune valeur?
Voila c'est des petits bugs? ou quelque chose m'echappe?
Bug:
----
Sinon en passant un petit bug:
if((status1 != 0x00) &&
(ctrl->devices[IDE_SLAVE].type == IDE_DEV_NOT_PRESENT))
{
outb(ATA_D_IBM | ATA_D_SLAVE, ctrl->ioaddr + ATA_DRIVE);
usleep(1);
outb(0x58, ctrl->ioaddr + ATA_ERROR);
outb(0xa5, ctrl->ioaddr + ATA_CYL_LSB);
if(inb(ctrl->ioaddr + ATA_ERROR) != 0x58 &&
inb(ctrl->ioaddr + ATA_CYL_LSB) == 0xa5)
{
ctrl->devices[IDE_MASTER].type = IDE_DEV_ATA; <--------- Oops ;)
}
}
A remplacer par ctrl->devices[IDE_SLAVE].type = IDE_DEV_ATA;
Merci d'avance pour vos reponses
Encore bravo pour votre OS.
Il est clair et assez abouti, tres agreable a lire.
--
Laurent
More information about the Kos-dev
mailing list